Example #1
0
static int
ed_rtl_set_media(struct ifnet *ifp)
{
	struct ed_softc *sc;

	sc = ifp->if_softc;
	ED_LOCK(sc);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3
		| (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP)));
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);

	switch(IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) {
	case IFM_10_T:
		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_T
			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
				& ~ED_RTL80X9_CF2_MEDIA));
		break;
	case IFM_10_2:
		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_2
			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
				& ~ED_RTL80X9_CF2_MEDIA));
		break;
	case IFM_10_5:
		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_5
			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
				& ~ED_RTL80X9_CF2_MEDIA));
		break;
	case IFM_AUTO:
		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_AUTO
			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
				& ~ED_RTL80X9_CF2_MEDIA));
		break;
	}
	ed_nic_outb(sc, ED_RTL80X9_CONFIG3,
		(sc->ifmedia.ifm_cur->ifm_media & IFM_FDX) ?
		(ed_nic_inb(sc, ED_RTL80X9_CONFIG3) | ED_RTL80X9_CF3_FUDUP) :
		(ed_nic_inb(sc, ED_RTL80X9_CONFIG3) & ~ED_RTL80X9_CF3_FUDUP));

	ED_UNLOCK(sc);
	return (0);
}
Example #2
0
/*
 * Stripped down routine for writing a linear buffer to NIC memory.
 *	Only used in the probe routine to test the memory. 'len' must
 *	be even.
 */
void
ed_pio_writemem(struct ed_softc *sc, uint8_t *src, uint16_t dst, uint16_t len)
{
	int     maxwait = 200;	/* about 240us */

	/* select page 0 registers */
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STA);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);

	/* reset remote DMA complete flag */
	ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RDC);

	/* set up DMA byte count */
	ed_nic_outb(sc, ED_P0_RBCR0, len);
	ed_nic_outb(sc, ED_P0_RBCR1, len >> 8);

	/* set up destination address in NIC mem */
	ed_nic_outb(sc, ED_P0_RSAR0, dst);
	ed_nic_outb(sc, ED_P0_RSAR1, dst >> 8);

	/* set remote DMA write */
	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD1 | ED_CR_STA);

	if (sc->isa16bit)
		ed_asic_outsw(sc, ED_NOVELL_DATA, src, len / 2);
	else
		ed_asic_outsb(sc, ED_NOVELL_DATA, src, len);

	/*
	 * Wait for remote DMA complete. This is necessary because on the
	 * transmit side, data is handled internally by the NIC in bursts and
	 * we can't start another remote DMA until this one completes. Not
	 * waiting causes really bad things to happen - like the NIC
	 * irrecoverably jamming the ISA bus.
	 */
	while (((ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RDC) != ED_ISR_RDC) &&
	    --maxwait)
		continue;
}
Example #3
0
static void
ed_pccard_ax88x90_reset(struct ed_softc *sc)
{
	int i;

	/* Reset Card */
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP | ED_CR_PAGE_0);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_asic_outb(sc, ED_NOVELL_RESET, ed_asic_inb(sc, ED_NOVELL_RESET));

	/* Wait for the RST bit to assert, but cap it at 10ms */
	for (i = 10000; !(ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RST) && i > 0;
	     i--)
		continue;
	ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RST);	/* ACK INTR */
	if (i == 0)
		device_printf(sc->dev, "Reset didn't finish\n");
}
Example #4
0
static void
ed_pccard_tc5299j_mii_bitbang_write(device_t dev, uint32_t val)
{
	struct ed_softc *sc;

	sc = device_get_softc(dev);

	/* We are already on page 3. */
	ed_nic_outb(sc, ED_TC5299J_MIIBUS, val);
	ed_nic_barrier(sc, ED_TC5299J_MIIBUS, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
}
Example #5
0
static uint32_t
ed_pccard_tc5299j_mii_bitbang_read(device_t dev)
{
	struct ed_softc *sc;
	uint32_t val;

	sc = device_get_softc(dev);

	/* We are already on page 3. */
	val = ed_asic_inb(sc, ED_TC5299J_MIIBUS);
	ed_nic_barrier(sc, ED_TC5299J_MIIBUS, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	return (val);
}
Example #6
0
static int
ed_miibus_writereg(device_t dev, int phy, int reg, int data)
{
	struct ed_softc *sc;
	uint8_t cr = 0;

	sc = device_get_softc(dev);
	/* See ed_miibus_readreg for details */
	if (sc->chip_type == ED_CHIP_TYPE_AX88790) {
		if (phy > 0x10)
			return (0);
		if (phy == 0x10)
			ed_asic_outb(sc, ED_AX88X90_GPIO,
			    ED_AX88X90_GPIO_INT_PHY);
		else
			ed_asic_outb(sc, ED_AX88X90_GPIO, 0);
		ed_asic_barrier(sc, ED_AX88X90_GPIO, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	} else if (sc->chip_type == ED_CHIP_TYPE_TC5299J) {
		/* Select page 3. */
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
		cr = ed_nic_inb(sc, ED_P0_CR);
		ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3);
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	}
	mii_bitbang_writereg(dev, sc->mii_bitbang_ops, phy, reg, data);
	if (sc->chip_type == ED_CHIP_TYPE_TC5299J) {
		/* Restore prior page. */
		ed_nic_outb(sc, ED_P0_CR, cr);
		ed_nic_barrier(sc, ED_P0_CR, 1,
	    	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	}
	return (0);
}
Example #7
0
int
ed_probe_RTL80x9(device_t dev, int port_rid, int flags)
{
	struct ed_softc *sc = device_get_softc(dev);
	char *ts;
	int error;

	if ((error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS)))
		return (error);
	
	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;

	if (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_PS0 | ED_CR_PS1))
		ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);

	if (ed_nic_inb(sc, ED_RTL80X9_80X9ID0) != ED_RTL80X9_ID0)
		return (ENXIO);

	switch (ed_nic_inb(sc, ED_RTL80X9_80X9ID1)) {
	case ED_RTL8019_ID1:
		sc->chip_type = ED_CHIP_TYPE_RTL8019;
		ts = "RTL8019";
		break;
	case ED_RTL8029_ID1:
		sc->chip_type = ED_CHIP_TYPE_RTL8029;
		ts = "RTL8029";
		break;
	default:
		return (ENXIO);
	}

	if ((error = ed_probe_Novell_generic(dev, flags)))
		return (error);

	sc->type_str = ts;
	sc->sc_media_ioctl = &ed_rtl80x9_media_ioctl;
	ifmedia_init(&sc->ifmedia, 0, ed_rtl_set_media, ed_rtl_get_media);

	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX, 0, 0);
	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T, 0, 0);
	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_2, 0, 0);
	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_5, 0, 0);
	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_AUTO, 0, 0);

	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_3 | ED_CR_STP);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);

	switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) & ED_RTL80X9_CF2_MEDIA) {
	case ED_RTL80X9_CF2_AUTO:
		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO);
		break;
	case ED_RTL80X9_CF2_10_5:
		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_5);
		break;
	case ED_RTL80X9_CF2_10_2:
		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_2);
		break;
	case ED_RTL80X9_CF2_10_T:
		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T |
		    ((ed_nic_inb(sc, ED_RTL80X9_CONFIG3)
		    & ED_RTL80X9_CF3_FUDUP) ? IFM_FDX : 0));
		break;
	}
	return (0);
}
Example #8
0
/*
 * Ethernet interface interrupt processor
 */
void
edintr(void *arg)
{
	struct ed_softc *sc = (struct ed_softc*) arg;
	struct ifnet *ifp = sc->ifp;
	u_char  isr;
	int	count;

	ED_LOCK(sc);
	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
		ED_UNLOCK(sc);
		return;
	}
	/*
	 * Set NIC to page 0 registers
	 */
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_STA);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);

	/*
	 * loop until there are no more new interrupts.  When the card goes
	 * away, the hardware will read back 0xff.  Looking at the interrupts,
	 * it would appear that 0xff is impossible as ED_ISR_RST is normally
	 * clear. ED_ISR_RDC is also normally clear and only set while
	 * we're transferring memory to the card and we're holding the
	 * ED_LOCK (so we can't get into here).
	 */
	while ((isr = ed_nic_inb(sc, ED_P0_ISR)) != 0 && isr != 0xff) {

		/*
		 * reset all the bits that we are 'acknowledging' by writing a
		 * '1' to each bit position that was set (writing a '1'
		 * *clears* the bit)
		 */
		ed_nic_outb(sc, ED_P0_ISR, isr);

		/*
		 * The AX88190 and AX88190A has problems acking an interrupt
		 * and having them clear.  This interferes with top-level loop
		 * here.  Wait for all the bits to clear.
		 *
		 * We limit this to 5000 iterations.  At 1us per inb/outb,
		 * this translates to about 15ms, which should be plenty of
		 * time, and also gives protection in the card eject case.
		 */
		if (sc->chip_type == ED_CHIP_TYPE_AX88190) {
			count = 5000;		/* 15ms */
			while (count-- && (ed_nic_inb(sc, ED_P0_ISR) & isr)) {
				ed_nic_outb(sc, ED_P0_ISR,0);
				ed_nic_outb(sc, ED_P0_ISR,isr);
			}
			if (count == 0)
				break;
		}

		/*
		 * Handle transmitter interrupts. Handle these first because
		 * the receiver will reset the board under some conditions.
		 */
		if (isr & (ED_ISR_PTX | ED_ISR_TXE)) {
			u_char  collisions = ed_nic_inb(sc, ED_P0_NCR) & 0x0f;

			/*
			 * Check for transmit error. If a TX completed with an
			 * error, we end up throwing the packet away. Really
			 * the only error that is possible is excessive
			 * collisions, and in this case it is best to allow
			 * the automatic mechanisms of TCP to backoff the
			 * flow. Of course, with UDP we're screwed, but this
			 * is expected when a network is heavily loaded.
			 */
			(void) ed_nic_inb(sc, ED_P0_TSR);
			if (isr & ED_ISR_TXE) {
				u_char tsr;

				/*
				 * Excessive collisions (16)
				 */
				tsr = ed_nic_inb(sc, ED_P0_TSR);
				if ((tsr & ED_TSR_ABT)	
				    && (collisions == 0)) {

					/*
					 * When collisions total 16, the
					 * P0_NCR will indicate 0, and the
					 * TSR_ABT is set.
					 */
					collisions = 16;
					sc->mibdata.dot3StatsExcessiveCollisions++;
					sc->mibdata.dot3StatsCollFrequencies[15]++;
				}
				if (tsr & ED_TSR_OWC)
					sc->mibdata.dot3StatsLateCollisions++;
				if (tsr & ED_TSR_CDH)
					sc->mibdata.dot3StatsSQETestErrors++;
				if (tsr & ED_TSR_CRS)
					sc->mibdata.dot3StatsCarrierSenseErrors++;
				if (tsr & ED_TSR_FU)
					sc->mibdata.dot3StatsInternalMacTransmitErrors++;

				/*
				 * update output errors counter
				 */
				if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
			} else {

				/*
				 * Update total number of successfully
				 * transmitted packets.
				 */
				if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
			}

			/*
			 * reset tx busy and output active flags
			 */
			sc->xmit_busy = 0;
			ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;

			/*
			 * clear watchdog timer
			 */
			sc->tx_timer = 0;

			/*
			 * Add in total number of collisions on last
			 * transmission.
			 */
			if_inc_counter(ifp, IFCOUNTER_COLLISIONS, collisions);
			switch(collisions) {
			case 0:
			case 16:
				break;
			case 1:
				sc->mibdata.dot3StatsSingleCollisionFrames++;
				sc->mibdata.dot3StatsCollFrequencies[0]++;
				break;
			default:
				sc->mibdata.dot3StatsMultipleCollisionFrames++;
				sc->mibdata.
					dot3StatsCollFrequencies[collisions-1]
						++;
				break;
			}

			/*
			 * Decrement buffer in-use count if not zero (can only
			 * be zero if a transmitter interrupt occured while
			 * not actually transmitting). If data is ready to
			 * transmit, start it transmitting, otherwise defer
			 * until after handling receiver
			 */
			if (sc->txb_inuse && --sc->txb_inuse)
				ed_xmit(sc);
		}

		/*
		 * Handle receiver interrupts
		 */
		if (isr & (ED_ISR_PRX | ED_ISR_RXE | ED_ISR_OVW)) {

			/*
			 * Overwrite warning. In order to make sure that a
			 * lockup of the local DMA hasn't occurred, we reset
			 * and re-init the NIC. The NSC manual suggests only a
			 * partial reset/re-init is necessary - but some chips
			 * seem to want more. The DMA lockup has been seen
			 * only with early rev chips - Methinks this bug was
			 * fixed in later revs. -DG
			 */
			if (isr & ED_ISR_OVW) {
				if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
#ifdef DIAGNOSTIC
				log(LOG_WARNING,
				    "%s: warning - receiver ring buffer overrun\n",
				    ifp->if_xname);
#endif

				/*
				 * Stop/reset/re-init NIC
				 */
				ed_reset(ifp);
			} else {

				/*
				 * Receiver Error. One or more of: CRC error,
				 * frame alignment error FIFO overrun, or
				 * missed packet.
				 */
				if (isr & ED_ISR_RXE) {
					u_char rsr;
					rsr = ed_nic_inb(sc, ED_P0_RSR);
					if (rsr & ED_RSR_CRC)
						sc->mibdata.dot3StatsFCSErrors++;
					if (rsr & ED_RSR_FAE)
						sc->mibdata.dot3StatsAlignmentErrors++;
					if (rsr & ED_RSR_FO)
						sc->mibdata.dot3StatsInternalMacReceiveErrors++;
					if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
#ifdef ED_DEBUG
					if_printf(ifp, "receive error %x\n",
					       ed_nic_inb(sc, ED_P0_RSR));
#endif
				}

				/*
				 * Go get the packet(s) XXX - Doing this on an
				 * error is dubious because there shouldn't be
				 * any data to get (we've configured the
				 * interface to not accept packets with
				 * errors).
				 */

				/*
				 * Enable 16bit access to shared memory first
				 * on WD/SMC boards.
				 */
				ed_enable_16bit_access(sc);
				ed_rint(sc);
				ed_disable_16bit_access(sc);
			}
		}

		/*
		 * If it looks like the transmitter can take more data,
		 * attempt to start output on the interface. This is done
		 * after handling the receiver to give the receiver priority.
		 */
		if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
			ed_start_locked(ifp);

		/*
		 * return NIC CR to standard state: page 0, remote DMA
		 * complete, start (toggling the TXP bit off, even if was just
		 * set in the transmit routine, is *okay* - it is 'edge'
		 * triggered from low to high)
		 */
		ed_nic_barrier(sc, ED_P0_CR, 1,
	  	  BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
		ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_STA);
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);

		/*
		 * If the Network Talley Counters overflow, read them to reset
		 * them. It appears that old 8390's won't clear the ISR flag
		 * otherwise - resulting in an infinite loop.
		 */
		if (isr & ED_ISR_CNT) {
			(void) ed_nic_inb(sc, ED_P0_CNTR0);
			(void) ed_nic_inb(sc, ED_P0_CNTR1);
			(void) ed_nic_inb(sc, ED_P0_CNTR2);
		}
	}
	ED_UNLOCK(sc);
}
Example #9
0
/*
 * Ethernet interface receiver interrupt.
 */
static __inline void
ed_rint(struct ed_softc *sc)
{
	struct ifnet *ifp = sc->ifp;
	u_char  boundry;
	u_short len;
	struct ed_ring packet_hdr;
	bus_size_t packet_ptr;

	ED_ASSERT_LOCKED(sc);

	/*
	 * Set NIC to page 1 registers to get 'current' pointer
	 */
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STA);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);

	/*
	 * 'sc->next_packet' is the logical beginning of the ring-buffer -
	 * i.e. it points to where new data has been buffered. The 'CURR'
	 * (current) register points to the logical end of the ring-buffer -
	 * i.e. it points to where additional new data will be added. We loop
	 * here until the logical beginning equals the logical end (or in
	 * other words, until the ring-buffer is empty).
	 */
	while (sc->next_packet != ed_nic_inb(sc, ED_P1_CURR)) {

		/* get pointer to this buffer's header structure */
		packet_ptr = sc->mem_ring +
		    (sc->next_packet - sc->rec_page_start) * ED_PAGE_SIZE;
	
		/*
		 * The byte count includes a 4 byte header that was added by
		 * the NIC.
		 */
		sc->readmem(sc, packet_ptr, (char *) &packet_hdr,
		    sizeof(packet_hdr));
		len = packet_hdr.count;
		if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN + sizeof(struct ed_ring)) ||
		    len < (ETHER_MIN_LEN - ETHER_CRC_LEN + sizeof(struct ed_ring))) {
			/*
			 * Length is a wild value. There's a good chance that
			 * this was caused by the NIC being old and buggy.
			 * The bug is that the length low byte is duplicated
			 * in the high byte. Try to recalculate the length
			 * based on the pointer to the next packet.  Also,
			 * need ot preserve offset into page.
			 *
			 * NOTE: sc->next_packet is pointing at the current
			 * packet.
			 */
			len &= ED_PAGE_SIZE - 1;
			if (packet_hdr.next_packet >= sc->next_packet)
				len += (packet_hdr.next_packet -
				    sc->next_packet) * ED_PAGE_SIZE;
			else
				len += 
				    ((packet_hdr.next_packet - sc->rec_page_start) +
				    (sc->rec_page_stop - sc->next_packet)) * ED_PAGE_SIZE;
			/*
			 * because buffers are aligned on 256-byte boundary,
			 * the length computed above is off by 256 in almost
			 * all cases. Fix it...
			 */
			if (len & 0xff)
				len -= 256;
			if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN 
			    + sizeof(struct ed_ring)))
				sc->mibdata.dot3StatsFrameTooLongs++;
		}

		/*
		 * Be fairly liberal about what we allow as a "reasonable"
		 * length so that a [crufty] packet will make it to BPF (and
		 * can thus be analyzed). Note that all that is really
		 * important is that we have a length that will fit into one
		 * mbuf cluster or less; the upper layer protocols can then
		 * figure out the length from their own length field(s).  But
		 * make sure that we have at least a full ethernet header or
		 * we would be unable to call ether_input() later.
		 */
		if ((len >= sizeof(struct ed_ring) + ETHER_HDR_LEN) &&
		    (len <= MCLBYTES) &&
		    (packet_hdr.next_packet >= sc->rec_page_start) &&
		    (packet_hdr.next_packet < sc->rec_page_stop)) {
			/*
			 * Go get packet.
			 */
			ed_get_packet(sc, packet_ptr + sizeof(struct ed_ring),
				      len - sizeof(struct ed_ring));
			if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
		} else {
			/*
			 * Really BAD. The ring pointers are corrupted.
			 */
			log(LOG_ERR,
			    "%s: NIC memory corrupt - invalid packet length %d\n",
			    ifp->if_xname, len);
			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
			ed_reset(ifp);
			return;
		}

		/*
		 * Update next packet pointer
		 */
		sc->next_packet = packet_hdr.next_packet;

		/*
		 * Update NIC boundry pointer - being careful to keep it one
		 * buffer behind. (as recommended by NS databook)
		 */
		boundry = sc->next_packet - 1;
		if (boundry < sc->rec_page_start)
			boundry = sc->rec_page_stop - 1;

		/*
		 * Set NIC to page 0 registers to update boundry register
		 */
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
		ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_STA);
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
		ed_nic_outb(sc, ED_P0_BNRY, boundry);

		/*
		 * Set NIC to page 1 registers before looping to top (prepare
		 * to get 'CURR' current pointer)
		 */
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
		ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STA);
		ed_nic_barrier(sc, ED_P0_CR, 1,
		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	}
}
Example #10
0
static void
ed_init_locked(struct ed_softc *sc)
{
	struct ifnet *ifp = sc->ifp;
	int     i;

	ED_ASSERT_LOCKED(sc);

	/*
	 * Initialize the NIC in the exact order outlined in the NS manual.
	 * This init procedure is "mandatory"...don't change what or when
	 * things happen.
	 */

	/* reset transmitter flags */
	sc->xmit_busy = 0;
	sc->tx_timer = 0;

	sc->txb_inuse = 0;
	sc->txb_new = 0;
	sc->txb_next_tx = 0;

	/* This variable is used below - don't move this assignment */
	sc->next_packet = sc->rec_page_start + 1;

	/*
	 * Set interface for page 0, Remote DMA complete, Stopped
	 */
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_STP);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);

	if (sc->isa16bit)
		/*
		 * Set FIFO threshold to 8, No auto-init Remote DMA, byte
		 * order=80x86, word-wide DMA xfers,
		 */
		ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_WTS | ED_DCR_LS);
	else
		/*
		 * Same as above, but byte-wide DMA xfers
		 */
		ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);

	/*
	 * Clear Remote Byte Count Registers
	 */
	ed_nic_outb(sc, ED_P0_RBCR0, 0);
	ed_nic_outb(sc, ED_P0_RBCR1, 0);

	/*
	 * For the moment, don't store incoming packets in memory.
	 */
	ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON);

	/*
	 * Place NIC in internal loopback mode
	 */
	ed_nic_outb(sc, ED_P0_TCR, ED_TCR_LB0);

	/*
	 * Initialize transmit/receive (ring-buffer) Page Start
	 */
	ed_nic_outb(sc, ED_P0_TPSR, sc->tx_page_start);
	ed_nic_outb(sc, ED_P0_PSTART, sc->rec_page_start);
	/* Set lower bits of byte addressable framing to 0 */
	if (sc->chip_type == ED_CHIP_TYPE_WD790)
		ed_nic_outb(sc, 0x09, 0);

	/*
	 * Initialize Receiver (ring-buffer) Page Stop and Boundry
	 */
	ed_nic_outb(sc, ED_P0_PSTOP, sc->rec_page_stop);
	ed_nic_outb(sc, ED_P0_BNRY, sc->rec_page_start);

	/*
	 * Clear all interrupts. A '1' in each bit position clears the
	 * corresponding flag.
	 */
	ed_nic_outb(sc, ED_P0_ISR, 0xff);

	/*
	 * Enable the following interrupts: receive/transmit complete,
	 * receive/transmit error, and Receiver OverWrite.
	 *
	 * Counter overflow and Remote DMA complete are *not* enabled.
	 */
	ed_nic_outb(sc, ED_P0_IMR,
	ED_IMR_PRXE | ED_IMR_PTXE | ED_IMR_RXEE | ED_IMR_TXEE | ED_IMR_OVWE);

	/*
	 * Program Command Register for page 1
	 */
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STP);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);

	/*
	 * Copy out our station address
	 */
	for (i = 0; i < ETHER_ADDR_LEN; ++i)
		ed_nic_outb(sc, ED_P1_PAR(i), IF_LLADDR(sc->ifp)[i]);

	/*
	 * Set Current Page pointer to next_packet (initialized above)
	 */
	ed_nic_outb(sc, ED_P1_CURR, sc->next_packet);

	/*
	 * Program Receiver Configuration Register and multicast filter. CR is
	 * set to page 0 on return.
	 */
	ed_setrcr(sc);

	/*
	 * Take interface out of loopback
	 */
	ed_nic_outb(sc, ED_P0_TCR, 0);

	if (sc->sc_mediachg)
		sc->sc_mediachg(sc);

	/*
	 * Set 'running' flag, and clear output active flag.
	 */
	ifp->if_drv_flags |= IFF_DRV_RUNNING;
	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;

	/*
	 * ...and attempt to start output
	 */
	ed_start_locked(ifp);

	callout_reset(&sc->tick_ch, hz, ed_tick, sc);
}
Example #11
0
/*
 * Write an mbuf chain to the destination NIC memory address using
 *	programmed I/O.
 */
u_short
ed_pio_write_mbufs(struct ed_softc *sc, struct mbuf *m, bus_size_t dst)
{
	struct ifnet *ifp = sc->ifp;
	unsigned short total_len, dma_len;
	struct mbuf *mp;
	int     maxwait = 200;	/* about 240us */

	ED_ASSERT_LOCKED(sc);

	/* Regular Novell cards */
	/* First, count up the total number of bytes to copy */
	for (total_len = 0, mp = m; mp; mp = mp->m_next)
		total_len += mp->m_len;

	dma_len = total_len;
	if (sc->isa16bit && (dma_len & 1))
		dma_len++;

	/* select page 0 registers */
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STA);
	ed_nic_barrier(sc, ED_P0_CR, 1,
	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);

	/* reset remote DMA complete flag */
	ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RDC);

	/* set up DMA byte count */
	ed_nic_outb(sc, ED_P0_RBCR0, dma_len);
	ed_nic_outb(sc, ED_P0_RBCR1, dma_len >> 8);

	/* set up destination address in NIC mem */
	ed_nic_outb(sc, ED_P0_RSAR0, dst);
	ed_nic_outb(sc, ED_P0_RSAR1, dst >> 8);

	/* set remote DMA write */
	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD1 | ED_CR_STA);

  /*
   * Transfer the mbuf chain to the NIC memory.
   * 16-bit cards require that data be transferred as words, and only words.
   * So that case requires some extra code to patch over odd-length mbufs.
   */

	if (!sc->isa16bit) {
		/* NE1000s are easy */
		while (m) {
			if (m->m_len)
				ed_asic_outsb(sc, ED_NOVELL_DATA, 
				    m->m_data, m->m_len);
			m = m->m_next;
		}
	} else {
		/* NE2000s are a pain */
		uint8_t *data;
		int len, wantbyte;
		union {
			uint16_t w;
			uint8_t b[2];
		} saveword;

		wantbyte = 0;

		while (m) {
			len = m->m_len;
			if (len) {
				data = mtod(m, caddr_t);
				/* finish the last word */
				if (wantbyte) {
					saveword.b[1] = *data;
					ed_asic_outw(sc, ED_NOVELL_DATA,
					    saveword.w);
					data++;
					len--;
					wantbyte = 0;
				}
				/* output contiguous words */
				if (len > 1) {
					ed_asic_outsw(sc, ED_NOVELL_DATA,
						      data, len >> 1);
					data += len & ~1;
					len &= 1;
				}
				/* save last byte, if necessary */
				if (len == 1) {
					saveword.b[0] = *data;
					wantbyte = 1;
				}
			}
			m = m->m_next;
		}
		/* spit last byte */
		if (wantbyte)
			ed_asic_outw(sc, ED_NOVELL_DATA, saveword.w);
	}