Home | History | Annotate | Line # | Download | only in ic
lemac.c revision 1.53
      1 /* $NetBSD: lemac.c,v 1.53 2019/05/28 07:41:48 msaitoh Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1994, 1995, 1997 Matt Thomas <matt (at) 3am-software.com>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. The name of the author may not be used to endorse or promote products
     13  *    derived from this software without specific prior written permission
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 /*
     28  * DEC EtherWORKS 3 Ethernet Controllers
     29  *
     30  * Written by Matt Thomas
     31  * BPF support code stolen directly from if_ec.c
     32  *
     33  *   This driver supports the LEMAC DE203/204/205 cards.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 __KERNEL_RCSID(0, "$NetBSD: lemac.c,v 1.53 2019/05/28 07:41:48 msaitoh Exp $");
     38 
     39 #include "opt_inet.h"
     40 
     41 #include <sys/param.h>
     42 #include <sys/systm.h>
     43 #include <sys/mbuf.h>
     44 #include <sys/protosw.h>
     45 #include <sys/socket.h>
     46 #include <sys/sockio.h>
     47 #include <sys/errno.h>
     48 #include <sys/malloc.h>
     49 #include <sys/device.h>
     50 #include <sys/rndsource.h>
     51 
     52 #include <net/if.h>
     53 #include <net/if_types.h>
     54 #include <net/if_dl.h>
     55 #include <net/route.h>
     56 #include <net/if_ether.h>
     57 #include <net/if_media.h>
     58 #include <net/bpf.h>
     59 
     60 #ifdef INET
     61 #include <netinet/in.h>
     62 #include <netinet/in_systm.h>
     63 #include <netinet/in_var.h>
     64 #include <netinet/ip.h>
     65 #include <netinet/if_inarp.h>
     66 #endif
     67 
     68 
     69 #include <sys/bus.h>
     70 
     71 #include <dev/ic/lemacreg.h>
     72 #include <dev/ic/lemacvar.h>
     73 #if 0
     74 #include <i386/isa/decether.h>
     75 #endif
     76 
     77 static void lemac_init(lemac_softc_t *sc);
     78 static void lemac_ifstart(struct ifnet *ifp);
     79 static void lemac_reset(lemac_softc_t *sc);
     80 static void lemac_rne_intr(lemac_softc_t *sc);
     81 static void lemac_tne_intr(lemac_softc_t *sc);
     82 static void lemac_txd_intr(lemac_softc_t *sc, unsigned cs_value);
     83 static void lemac_rxd_intr(lemac_softc_t *sc, unsigned cs_value);
     84 static int  lemac_read_eeprom(lemac_softc_t *sc);
     85 static void lemac_init_adapmem(lemac_softc_t *sc);
     86 
     87 static const uint16_t lemac_allmulti_mctbl[LEMAC_MCTBL_SIZE/sizeof(uint16_t)] =  {
     88 	0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
     89 	0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
     90 	0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
     91 	0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
     92 	0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
     93 	0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
     94 	0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
     95 	0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
     96 };
     97 
     98 /*
     99  * Some tuning/monitoring variables.
    100  */
    101 unsigned lemac_txmax = 16;
    102 
    103 static void
    105 lemac_rxd_intr(lemac_softc_t *sc, unsigned cs_value)
    106 {
    107 	/*
    108 	 * Handle CS_RXD (Receiver disabled) here.
    109 	 *
    110 	 * Check Free Memory Queue Count. If not equal to zero
    111 	 * then just turn Receiver back on. If it is equal to
    112 	 * zero then check to see if transmitter is disabled.
    113 	 * Process transmit TXD loop once more.  If all else
    114 	 * fails then do software init (0xC0 to EEPROM Init)
    115 	 * and rebuild Free Memory Queue.
    116 	 */
    117 
    118 	sc->sc_cntrs.cntr_rxd_intrs++;
    119 
    120 	/* Re-enable Receiver. */
    121 
    122 	cs_value &= ~LEMAC_CS_RXD;
    123 	LEMAC_OUTB(sc, LEMAC_REG_CS, cs_value);
    124 
    125 	if (LEMAC_INB(sc, LEMAC_REG_FMC) > 0)
    126 		return;
    127 
    128 	if (cs_value & LEMAC_CS_TXD)
    129 		lemac_txd_intr(sc, cs_value);
    130 
    131 	if ((LEMAC_INB(sc, LEMAC_REG_CS) & LEMAC_CS_RXD) == 0)
    132 		return;
    133 
    134 	printf("%s: fatal RXD error, attempting recovery\n",
    135 	    sc->sc_if.if_xname);
    136 
    137 	lemac_reset(sc);
    138 	if (sc->sc_if.if_flags & IFF_UP) {
    139 		lemac_init(sc);
    140 		return;
    141 	}
    142 
    143 	/* Error during initialization.  Mark card as disabled. */
    144 	printf("%s: recovery failed -- board disabled\n", sc->sc_if.if_xname);
    145 }
    146 
    147 static void
    149 lemac_tne_intr(lemac_softc_t *sc)
    150 {
    151 	unsigned txcount = LEMAC_INB(sc, LEMAC_REG_TDC);
    152 
    153 	sc->sc_cntrs.cntr_tne_intrs++;
    154 	while (txcount-- > 0) {
    155 		unsigned txsts = LEMAC_INB(sc, LEMAC_REG_TDQ);
    156 		sc->sc_if.if_opackets++;		/* another one done */
    157 		if ((txsts & (LEMAC_TDQ_LCL | LEMAC_TDQ_NCL))
    158 		    || (txsts & LEMAC_TDQ_COL) == LEMAC_TDQ_EXCCOL) {
    159 			if (txsts & LEMAC_TDQ_NCL)
    160 				sc->sc_flags &= ~LEMAC_LINKUP;
    161 			sc->sc_if.if_oerrors++;
    162 		} else {
    163 			sc->sc_flags |= LEMAC_LINKUP;
    164 			if ((txsts & LEMAC_TDQ_COL) != LEMAC_TDQ_NOCOL)
    165 				sc->sc_if.if_collisions++;
    166 		}
    167 	}
    168 	sc->sc_if.if_flags &= ~IFF_OACTIVE;
    169 	if_schedule_deferred_start(&sc->sc_if);
    170 }
    171 
    172 static void
    173 lemac_txd_intr(lemac_softc_t *sc, unsigned cs_value)
    174 {
    175 	/*
    176 	 * Read transmit status, remove transmit buffer from
    177 	 * transmit queue and place on free memory queue,
    178 	 * then reset transmitter.
    179 	 * Increment appropriate counters.
    180 	 */
    181 
    182 	sc->sc_cntrs.cntr_txd_intrs++;
    183 	if (sc->sc_txctl & LEMAC_TX_STP) {
    184 		sc->sc_if.if_oerrors++;
    185 		/* return page to free queue */
    186 		LEMAC_OUTB(sc, LEMAC_REG_FMQ, LEMAC_INB(sc, LEMAC_REG_TDQ));
    187 	}
    188 
    189 	/* Turn back on transmitter if disabled */
    190 	LEMAC_OUTB(sc, LEMAC_REG_CS, cs_value & ~LEMAC_CS_TXD);
    191 	sc->sc_if.if_flags &= ~IFF_OACTIVE;
    192 }
    193 
    194 static int
    196 lemac_read_eeprom(lemac_softc_t *sc)
    197 {
    198 	int	word_off, cksum;
    199 	u_char *ep;
    200 
    201 	cksum = 0;
    202 	ep = sc->sc_eeprom;
    203 	for (word_off = 0; word_off < LEMAC_EEP_SIZE / 2; word_off++) {
    204 		LEMAC_OUTB(sc, LEMAC_REG_PI1, word_off);
    205 		LEMAC_OUTB(sc, LEMAC_REG_IOP, LEMAC_IOP_EEREAD);
    206 
    207 		DELAY(LEMAC_EEP_DELAY);
    208 
    209 		*ep = LEMAC_INB(sc, LEMAC_REG_EE1);	cksum += *ep++;
    210 		*ep = LEMAC_INB(sc, LEMAC_REG_EE2);	cksum += *ep++;
    211 	}
    212 
    213 	/* Set up Transmit Control Byte for use later during transmit. */
    214 
    215 	sc->sc_txctl |= LEMAC_TX_FLAGS;
    216 
    217 	if ((sc->sc_eeprom[LEMAC_EEP_SWFLAGS] & LEMAC_EEP_SW_SQE) == 0)
    218 		sc->sc_txctl &= ~LEMAC_TX_SQE;
    219 
    220 	if (sc->sc_eeprom[LEMAC_EEP_SWFLAGS] & LEMAC_EEP_SW_LAB)
    221 		sc->sc_txctl |= LEMAC_TX_LAB;
    222 
    223 	memcpy(sc->sc_prodname, &sc->sc_eeprom[LEMAC_EEP_PRDNM],
    224 	    LEMAC_EEP_PRDNMSZ);
    225 	sc->sc_prodname[LEMAC_EEP_PRDNMSZ] = '\0';
    226 
    227 	return cksum % 256;
    228 }
    229 
    230 static void
    232 lemac_init_adapmem(lemac_softc_t *sc)
    233 {
    234 	int pg, conf;
    235 
    236 	conf = LEMAC_INB(sc, LEMAC_REG_CNF);
    237 
    238 	if ((sc->sc_eeprom[LEMAC_EEP_SETUP] & LEMAC_EEP_ST_DRAM) == 0) {
    239 		sc->sc_lastpage = 63;
    240 		conf &= ~LEMAC_CNF_DRAM;
    241 	} else {
    242 		sc->sc_lastpage = 127;
    243 		conf |= LEMAC_CNF_DRAM;
    244 	}
    245 
    246 	LEMAC_OUTB(sc, LEMAC_REG_CNF, conf);
    247 
    248 	for (pg = 1; pg <= sc->sc_lastpage; pg++)
    249 		LEMAC_OUTB(sc, LEMAC_REG_FMQ, pg);
    250 }
    251 
    252 static void
    254 lemac_input(lemac_softc_t *sc, bus_addr_t offset, size_t length)
    255 {
    256 	struct ether_header eh;
    257 	struct mbuf *m;
    258 
    259 	if (length - sizeof(eh) > ETHERMTU || length - sizeof(eh) < ETHERMIN) {
    260 		sc->sc_if.if_ierrors++;
    261 		return;
    262 	}
    263 	if (LEMAC_USE_PIO_MODE(sc))
    264 		LEMAC_INSB(sc, LEMAC_REG_DAT, sizeof(eh), (void *)&eh);
    265 	else
    266 		LEMAC_GETBUF16(sc, offset, sizeof(eh) / 2, (void *)&eh);
    267 
    268 	MGETHDR(m, M_DONTWAIT, MT_DATA);
    269 	if (m == NULL) {
    270 		sc->sc_if.if_ierrors++;
    271 		return;
    272 	}
    273 	if (length + 2 > MHLEN) {
    274 		MCLGET(m, M_DONTWAIT);
    275 		if ((m->m_flags & M_EXT) == 0) {
    276 			m_free(m);
    277 			sc->sc_if.if_ierrors++;
    278 			return;
    279 		}
    280 	}
    281 	m->m_data += 2;
    282 	memcpy(m->m_data, (void *)&eh, sizeof(eh));
    283 	if (LEMAC_USE_PIO_MODE(sc)) {
    284 		LEMAC_INSB(sc, LEMAC_REG_DAT, length - sizeof(eh),
    285 		    mtod(m, char *) + sizeof(eh));
    286 	} else {
    287 		LEMAC_GETBUF16(sc, offset + sizeof(eh),
    288 		    (length - sizeof(eh)) / 2,
    289 		    (void *)(mtod(m, char *) + sizeof(eh)));
    290 		if (length & 1)
    291 			m->m_data[length - 1]
    292 			    = LEMAC_GET8(sc, offset + length - 1);
    293 	}
    294 
    295 	m->m_pkthdr.len = m->m_len = length;
    296 	m_set_rcvif(m, &sc->sc_if);
    297 
    298 	if_percpuq_enqueue((&sc->sc_if)->if_percpuq, m);
    299 }
    300 
    301 static void
    303 lemac_rne_intr(lemac_softc_t *sc)
    304 {
    305 	int rxcount;
    306 
    307 	sc->sc_cntrs.cntr_rne_intrs++;
    308 	rxcount = LEMAC_INB(sc, LEMAC_REG_RQC);
    309 	while (rxcount--) {
    310 		unsigned rxpg = LEMAC_INB(sc, LEMAC_REG_RQ);
    311 		uint32_t rxlen;
    312 
    313 		if (LEMAC_USE_PIO_MODE(sc)) {
    314 			LEMAC_OUTB(sc, LEMAC_REG_IOP, rxpg);
    315 			LEMAC_OUTB(sc, LEMAC_REG_PI1, 0);
    316 			LEMAC_OUTB(sc, LEMAC_REG_PI2, 0);
    317 			LEMAC_INSB(sc, LEMAC_REG_DAT, sizeof(rxlen),
    318 			    (void *)&rxlen);
    319 		} else {
    320 			LEMAC_OUTB(sc, LEMAC_REG_MPN, rxpg);
    321 			rxlen = LEMAC_GET32(sc, 0);
    322 		}
    323 		if (rxlen & LEMAC_RX_OK) {
    324 			sc->sc_flags |= LEMAC_LINKUP;
    325 			/* Get receive length - subtract out checksum. */
    326 			rxlen = ((rxlen >> 8) & 0x7FF) - 4;
    327 			lemac_input(sc, sizeof(rxlen), rxlen);
    328 		} else {
    329 			sc->sc_if.if_ierrors++;
    330 		}
    331 		/* Return this page to Free Memory Queue */
    332 		LEMAC_OUTB(sc, LEMAC_REG_FMQ, rxpg);
    333 	}  /* end while (recv_count--) */
    334 
    335 	return;
    336 }
    337 
    338 /*
    340  *  This is the standard method of reading the DEC Address ROMS.
    341  *  I don't understand it but it does work.
    342  */
    343 static int
    344 lemac_read_macaddr(unsigned char *hwaddr, const bus_space_tag_t iot,
    345 	const bus_space_handle_t ioh, const bus_addr_t ioreg, int skippat)
    346 {
    347 	int cksum, rom_cksum;
    348 	unsigned char addrbuf[6];
    349 
    350 	if (!skippat) {
    351 		int idx, idx2, found, octet;
    352 		static u_char testpat[]
    353 		    = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA };
    354 
    355 		idx2 = found = 0;
    356 
    357 		for (idx = 0; idx < 32; idx++) {
    358 			octet = bus_space_read_1(iot, ioh, ioreg);
    359 
    360 			if (octet == testpat[idx2]) {
    361 				if (++idx2 == sizeof(testpat)) {
    362 					++found;
    363 					break;
    364 				}
    365 			} else
    366 				idx2 = 0;
    367 		}
    368 
    369 		if (!found)
    370 			return -1;
    371 	}
    372 
    373 	if (hwaddr == NULL)
    374 		hwaddr = addrbuf;
    375 
    376 	cksum = 0;
    377 	hwaddr[0] = bus_space_read_1(iot, ioh, ioreg);
    378 	hwaddr[1] = bus_space_read_1(iot, ioh, ioreg);
    379 
    380 	/* hardware address can't be multicast */
    381 	if (hwaddr[0] & 1)
    382 		return -1;
    383 
    384 	cksum = *(u_short *)&hwaddr[0];
    385 
    386 	hwaddr[2] = bus_space_read_1(iot, ioh, ioreg);
    387 	hwaddr[3] = bus_space_read_1(iot, ioh, ioreg);
    388 	cksum *= 2;
    389 	if (cksum > 65535) cksum -= 65535;
    390 	cksum += *(u_short *) &hwaddr[2];
    391 	if (cksum > 65535) cksum -= 65535;
    392 
    393 	hwaddr[4] = bus_space_read_1(iot, ioh, ioreg);
    394 	hwaddr[5] = bus_space_read_1(iot, ioh, ioreg);
    395 	cksum *= 2;
    396 	if (cksum > 65535) cksum -= 65535;
    397 	cksum += *(u_short *)&hwaddr[4];
    398 	if (cksum >= 65535) cksum -= 65535;
    399 
    400 	/* 00-00-00 is an illegal OUI */
    401 	if (hwaddr[0] == 0 && hwaddr[1] == 0 && hwaddr[2] == 0)
    402 		return -1;
    403 
    404 	rom_cksum = bus_space_read_1(iot, ioh, ioreg);
    405 	rom_cksum |= bus_space_read_1(iot, ioh, ioreg) << 8;
    406 
    407 	if (cksum != rom_cksum)
    408 		return -1;
    409 	return 0;
    410 }
    411 
    412 static void
    414 lemac_multicast_op(
    415 	uint16_t *mctbl,
    416 	const u_char *mca,
    417 	int enable)
    418 {
    419 	u_int idx, bit, crc;
    420 
    421 	crc = ether_crc32_le(mca, ETHER_ADDR_LEN);
    422 
    423 	/*
    424 	 * The following two lines convert the N bit index into a longword
    425 	 * index and a longword mask.
    426 	 */
    427 #if LEMAC_MCTBL_BITS < 0
    428 	crc >>= (32 + LEMAC_MCTBL_BITS);
    429 	crc &= (1 << -LEMAC_MCTBL_BITS) - 1;
    430 #else
    431 	crc &= (1 << LEMAC_MCTBL_BITS) - 1;
    432 #endif
    433 	bit = 1 << (crc & 0x0F);
    434 	idx = crc >> 4;
    435 
    436 	/* Set or clear hash filter bit in our table. */
    437 	if (enable)
    438 		mctbl[idx] |= bit;		/* Set Bit */
    439 	else
    440 		mctbl[idx] &= ~bit;		/* Clear Bit */
    441 }
    442 
    443 static void
    445 lemac_multicast_filter(lemac_softc_t *sc)
    446 {
    447 	struct ethercom *ec = &sc->sc_ec;
    448 	struct ether_multistep step;
    449 	struct ether_multi *enm;
    450 
    451 	memset(sc->sc_mctbl, 0, LEMAC_MCTBL_BITS / 8);
    452 
    453 	lemac_multicast_op(sc->sc_mctbl, etherbroadcastaddr, TRUE);
    454 
    455 	ETHER_LOCK(ec);
    456 	ETHER_FIRST_MULTI(step, ec, enm);
    457 	while (enm != NULL) {
    458 		if (!LEMAC_ADDREQUAL(enm->enm_addrlo, enm->enm_addrhi)) {
    459 			sc->sc_flags |= LEMAC_ALLMULTI;
    460 			sc->sc_if.if_flags |= IFF_ALLMULTI;
    461 			ETHER_UNLOCK(ec);
    462 			return;
    463 		}
    464 		lemac_multicast_op(sc->sc_mctbl, enm->enm_addrlo, TRUE);
    465 		ETHER_NEXT_MULTI(step, enm);
    466 	}
    467 	ETHER_UNLOCK(ec);
    468 	sc->sc_flags &= ~LEMAC_ALLMULTI;
    469 	sc->sc_if.if_flags &= ~IFF_ALLMULTI;
    470 }
    471 
    472 /*
    474  * Do a hard reset of the board;
    475  */
    476 static void
    477 lemac_reset(lemac_softc_t * const sc)
    478 {
    479 	unsigned data;
    480 
    481 	/*
    482 	 * Initialize board..
    483 	 */
    484 	sc->sc_flags &= ~LEMAC_LINKUP;
    485 	sc->sc_if.if_flags &= ~IFF_OACTIVE;
    486 	LEMAC_INTR_DISABLE(sc);
    487 
    488 	LEMAC_OUTB(sc, LEMAC_REG_IOP, LEMAC_IOP_EEINIT);
    489 	DELAY(LEMAC_EEP_DELAY);
    490 
    491 	/*
    492 	 * Read EEPROM information.  NOTE - the placement of this function
    493 	 * is important because functions hereafter may rely on information
    494 	 * read from the EEPROM.
    495 	 */
    496 	if ((data = lemac_read_eeprom(sc)) != LEMAC_EEP_CKSUM) {
    497 		printf("%s: reset: EEPROM checksum failed (0x%x)\n",
    498 		    sc->sc_if.if_xname, data);
    499 		return;
    500 	}
    501 
    502 	/* Update the control register to reflect the media choice */
    503 	data = LEMAC_INB(sc, LEMAC_REG_CTL);
    504 	if ((data & (LEMAC_CTL_APD | LEMAC_CTL_PSL)) != sc->sc_ctlmode) {
    505 		data &= ~(LEMAC_CTL_APD | LEMAC_CTL_PSL);
    506 		data |= sc->sc_ctlmode;
    507 		LEMAC_OUTB(sc, LEMAC_REG_CTL, data);
    508 	}
    509 
    510 	/* Force to 2K mode if not already configured. */
    511 
    512 	data = LEMAC_INB(sc, LEMAC_REG_MBR);
    513 	if (LEMAC_IS_2K_MODE(data)) {
    514 		sc->sc_flags |= LEMAC_2K_MODE;
    515 	} else if (LEMAC_IS_64K_MODE(data)) {
    516 		data = (((data * 2) & 0xF) << 4);
    517 		sc->sc_flags |= LEMAC_WAS_64K_MODE;
    518 		LEMAC_OUTB(sc, LEMAC_REG_MBR, data);
    519 	} else if (LEMAC_IS_32K_MODE(data)) {
    520 		data = ((data & 0xF) << 4);
    521 		sc->sc_flags |= LEMAC_WAS_32K_MODE;
    522 		LEMAC_OUTB(sc, LEMAC_REG_MBR, data);
    523 	} else {
    524 		sc->sc_flags |= LEMAC_PIO_MODE;
    525 		/* PIO mode */
    526 	}
    527 
    528 	/* Initialize Free Memory Queue, Init mcast table with broadcast. */
    529 
    530 	lemac_init_adapmem(sc);
    531 	sc->sc_flags |= LEMAC_ALIVE;
    532 }
    533 
    534 static void
    536 lemac_init(lemac_softc_t * const sc)
    537 {
    538 	if ((sc->sc_flags & LEMAC_ALIVE) == 0)
    539 		return;
    540 
    541 	/*
    542 	 * If the interface has the up flag
    543 	 */
    544 	if (sc->sc_if.if_flags & IFF_UP) {
    545 		int saved_cs = LEMAC_INB(sc, LEMAC_REG_CS);
    546 		LEMAC_OUTB(sc, LEMAC_REG_CS,
    547 		    saved_cs | (LEMAC_CS_TXD | LEMAC_CS_RXD));
    548 		LEMAC_OUTB(sc, LEMAC_REG_PA0, sc->sc_enaddr[0]);
    549 		LEMAC_OUTB(sc, LEMAC_REG_PA1, sc->sc_enaddr[1]);
    550 		LEMAC_OUTB(sc, LEMAC_REG_PA2, sc->sc_enaddr[2]);
    551 		LEMAC_OUTB(sc, LEMAC_REG_PA3, sc->sc_enaddr[3]);
    552 		LEMAC_OUTB(sc, LEMAC_REG_PA4, sc->sc_enaddr[4]);
    553 		LEMAC_OUTB(sc, LEMAC_REG_PA5, sc->sc_enaddr[5]);
    554 
    555 		LEMAC_OUTB(sc, LEMAC_REG_IC,
    556 		    LEMAC_INB(sc, LEMAC_REG_IC) | LEMAC_IC_IE);
    557 
    558 		if (sc->sc_if.if_flags & IFF_PROMISC) {
    559 			LEMAC_OUTB(sc, LEMAC_REG_CS,
    560 			    LEMAC_CS_MCE | LEMAC_CS_PME);
    561 		} else {
    562 			LEMAC_INTR_DISABLE(sc);
    563 			lemac_multicast_filter(sc);
    564 			if (sc->sc_flags & LEMAC_ALLMULTI)
    565 				memcpy(sc->sc_mctbl, lemac_allmulti_mctbl,
    566 				    sizeof(sc->sc_mctbl));
    567 			if (LEMAC_USE_PIO_MODE(sc)) {
    568 				LEMAC_OUTB(sc, LEMAC_REG_IOP, 0);
    569 				LEMAC_OUTB(sc, LEMAC_REG_PI1,
    570 				    LEMAC_MCTBL_OFF & 0xFF);
    571 				LEMAC_OUTB(sc, LEMAC_REG_PI2,
    572 				    LEMAC_MCTBL_OFF >> 8);
    573 				LEMAC_OUTSB(sc, LEMAC_REG_DAT,
    574 				    sizeof(sc->sc_mctbl),
    575 				    (void *)sc->sc_mctbl);
    576 			} else {
    577 				LEMAC_OUTB(sc, LEMAC_REG_MPN, 0);
    578 				LEMAC_PUTBUF8(sc, LEMAC_MCTBL_OFF,
    579 				    sizeof(sc->sc_mctbl),
    580 				    (void *)sc->sc_mctbl);
    581 			}
    582 
    583 			LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE);
    584 		}
    585 
    586 		LEMAC_OUTB(sc, LEMAC_REG_CTL,
    587 		    LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED);
    588 
    589 		LEMAC_INTR_ENABLE(sc);
    590 		sc->sc_if.if_flags |= IFF_RUNNING;
    591 		lemac_ifstart(&sc->sc_if);
    592 	} else {
    593 		LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_RXD | LEMAC_CS_TXD);
    594 
    595 		LEMAC_INTR_DISABLE(sc);
    596 		sc->sc_if.if_flags &= ~IFF_RUNNING;
    597 	}
    598 }
    599 
    600 static void
    602 lemac_ifstart(
    603 	struct ifnet *ifp)
    604 {
    605 	lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
    606 
    607 	if ((ifp->if_flags & IFF_RUNNING) == 0)
    608 		return;
    609 
    610 	LEMAC_INTR_DISABLE(sc);
    611 
    612 	for (;;) {
    613 		struct mbuf *m;
    614 		struct mbuf *m0;
    615 		int tx_pg;
    616 
    617 		IFQ_POLL(&ifp->if_snd, m);
    618 		if (m == NULL)
    619 			break;
    620 
    621 		if ((sc->sc_csr.csr_tqc = LEMAC_INB(sc, LEMAC_REG_TQC))
    622 		    >= lemac_txmax) {
    623 			sc->sc_cntrs.cntr_txfull++;
    624 			ifp->if_flags |= IFF_OACTIVE;
    625 			break;
    626 		}
    627 
    628 		/* Get free memory page */
    629 		tx_pg = sc->sc_csr.csr_fmq = LEMAC_INB(sc, LEMAC_REG_FMQ);
    630 
    631 		/* Check for good transmit page. */
    632 		if (tx_pg == 0 || tx_pg > sc->sc_lastpage) {
    633 			sc->sc_cntrs.cntr_txnospc++;
    634 			ifp->if_flags |= IFF_OACTIVE;
    635 			break;
    636 		}
    637 
    638 		IFQ_DEQUEUE(&ifp->if_snd, m);
    639 
    640 		/*
    641 		 * The first four bytes of each transmit buffer are for
    642 		 * control information.  The first byte is the control
    643 		 * byte, then the length (why not word aligned?), then
    644 		 * the offset to the buffer.
    645 		 */
    646 
    647 		if (LEMAC_USE_PIO_MODE(sc)) {
    648 			/* Shift 2K window. */
    649 			LEMAC_OUTB(sc, LEMAC_REG_IOP, tx_pg);
    650 
    651 			LEMAC_OUTB(sc, LEMAC_REG_PI1, 0);
    652 			LEMAC_OUTB(sc, LEMAC_REG_PI2, 0);
    653 			LEMAC_OUTB(sc, LEMAC_REG_DAT, sc->sc_txctl);
    654 			LEMAC_OUTB(sc, LEMAC_REG_DAT,
    655 			    (m->m_pkthdr.len >> 0) & 0xFF);
    656 			LEMAC_OUTB(sc, LEMAC_REG_DAT,
    657 			    (m->m_pkthdr.len >> 8) & 0xFF);
    658 			LEMAC_OUTB(sc, LEMAC_REG_DAT, LEMAC_TX_HDRSZ);
    659 			for (m0 = m; m0 != NULL; m0 = m0->m_next)
    660 				LEMAC_OUTSB(sc, LEMAC_REG_DAT,
    661 				    m0->m_len, m0->m_data);
    662 		} else {
    663 			bus_size_t txoff = /* (mtod(m, uint32_t) & (sizeof(uint32_t) - 1)) + */ LEMAC_TX_HDRSZ;
    664 
    665 			/* Shift 2K window. */
    666 			LEMAC_OUTB(sc, LEMAC_REG_MPN, tx_pg);
    667 
    668 			LEMAC_PUT8(sc, 0, sc->sc_txctl);
    669 			LEMAC_PUT8(sc, 1, (m->m_pkthdr.len >> 0) & 0xFF);
    670 			LEMAC_PUT8(sc, 2, (m->m_pkthdr.len >> 8) & 0xFF);
    671 			LEMAC_PUT8(sc, 3, txoff);
    672 
    673 			/* Copy the packet to the board */
    674 			for (m0 = m; m0 != NULL; m0 = m0->m_next) {
    675 #if 0
    676 				LEMAC_PUTBUF8(sc, txoff, m0->m_len, m0->m_data);
    677 				txoff += m0->m_len;
    678 #else
    679 				const uint8_t *cp = m0->m_data;
    680 				int len = m0->m_len;
    681 #if 0
    682 				if ((txoff & 3) == (((long)cp) & 3)
    683 				    && len >= 4) {
    684 					if (txoff & 3) {
    685 						int alen = (~txoff & 3);
    686 						LEMAC_PUTBUF8(sc, txoff, alen,
    687 						    cp);
    688 						cp += alen;
    689 						txoff += alen;
    690 						len -= alen;
    691 					}
    692 					if (len >= 4) {
    693 						LEMAC_PUTBUF32(sc, txoff,
    694 						    len / 4, cp);
    695 						cp += len & ~3;
    696 						txoff += len & ~3;
    697 						len &= 3;
    698 					}
    699 				}
    700 #endif
    701 				if ((txoff & 1) == (((long)cp) & 1)
    702 				    && len >= 2) {
    703 					if (txoff & 1) {
    704 						int alen = (~txoff & 1);
    705 						LEMAC_PUTBUF8(sc, txoff, alen,
    706 						    cp);
    707 						cp += alen;
    708 						txoff += alen;
    709 						len -= alen;
    710 					}
    711 					if (len >= 2) {
    712 						LEMAC_PUTBUF16(sc, txoff,
    713 						    len / 2, (const void *)cp);
    714 						cp += len & ~1;
    715 						txoff += len & ~1;
    716 						len &= 1;
    717 					}
    718 				}
    719 				if (len > 0) {
    720 					LEMAC_PUTBUF8(sc, txoff, len, cp);
    721 					txoff += len;
    722 				}
    723 #endif
    724 			}
    725 		}
    726 
    727 		/* Tell chip to transmit this packet */
    728 		LEMAC_OUTB(sc, LEMAC_REG_TQ, tx_pg);
    729 		bpf_mtap(&sc->sc_if, m, BPF_D_OUT);
    730 		m_freem(m);			/* Free the mbuf */
    731 	}
    732 	LEMAC_INTR_ENABLE(sc);
    733 }
    734 
    735 static int
    737 lemac_ifioctl(
    738 	struct ifnet *ifp,
    739 	u_long cmd,
    740 	void *data)
    741 {
    742 	lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
    743 	int s;
    744 	int error = 0;
    745 
    746 	s = splnet();
    747 
    748 	switch (cmd) {
    749 	case SIOCINITIFADDR: {
    750 		struct ifaddr *ifa = (struct ifaddr *)data;
    751 
    752 		ifp->if_flags |= IFF_UP;
    753 		lemac_init(sc);
    754 		switch (ifa->ifa_addr->sa_family) {
    755 #ifdef INET
    756 		case AF_INET:
    757 			arp_ifinit(&sc->sc_if, ifa);
    758 			break;
    759 #endif /* INET */
    760 
    761 
    762 		default:
    763 			break;
    764 		}
    765 		break;
    766 	}
    767 
    768 	case SIOCSIFFLAGS:
    769 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
    770 			break;
    771 		lemac_init(sc);
    772 		break;
    773 
    774 	case SIOCADDMULTI:
    775 	case SIOCDELMULTI:
    776 		/*
    777 		 * Update multicast listeners
    778 		 */
    779 		if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
    780 			/* reset multicast filtering */
    781 			if (ifp->if_flags & IFF_RUNNING)
    782 				lemac_init(sc);
    783 			error = 0;
    784 		}
    785 		break;
    786 
    787 	case SIOCSIFMEDIA:
    788 	case SIOCGIFMEDIA:
    789 		error = ifmedia_ioctl(ifp, (struct ifreq *)data,
    790 		    &sc->sc_ifmedia, cmd);
    791 		break;
    792 
    793 	default:
    794 		error = ether_ioctl(ifp, cmd, data);
    795 		break;
    796 	}
    797 
    798 	splx(s);
    799 	return error;
    800 }
    801 
    802 static int
    804 lemac_ifmedia_change(struct ifnet * const ifp)
    805 {
    806 	lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
    807 	unsigned new_ctl;
    808 
    809 	switch (IFM_SUBTYPE(sc->sc_ifmedia.ifm_media)) {
    810 	case IFM_10_T: new_ctl = LEMAC_CTL_APD; break;
    811 	case IFM_10_2:
    812 	case IFM_10_5: new_ctl = LEMAC_CTL_APD | LEMAC_CTL_PSL; break;
    813 	case IFM_AUTO: new_ctl = 0; break;
    814 	default:       return EINVAL;
    815 	}
    816 	if (sc->sc_ctlmode != new_ctl) {
    817 		sc->sc_ctlmode = new_ctl;
    818 		lemac_reset(sc);
    819 		if (sc->sc_if.if_flags & IFF_UP)
    820 			lemac_init(sc);
    821 	}
    822 	return 0;
    823 }
    824 
    825 /*
    826  * Media status callback
    827  */
    828 static void
    829 lemac_ifmedia_status(struct ifnet * const ifp, struct ifmediareq *req)
    830 {
    831 	lemac_softc_t *sc = LEMAC_IFP_TO_SOFTC(ifp);
    832 	unsigned data = LEMAC_INB(sc, LEMAC_REG_CNF);
    833 
    834 	req->ifm_status = IFM_AVALID;
    835 	if (sc->sc_flags & LEMAC_LINKUP)
    836 		req->ifm_status |= IFM_ACTIVE;
    837 
    838 	if (sc->sc_ctlmode & LEMAC_CTL_APD) {
    839 		if (sc->sc_ctlmode & LEMAC_CTL_PSL)
    840 			req->ifm_active = IFM_10_5;
    841 		else
    842 			req->ifm_active = IFM_10_T;
    843 	} else {
    844 		/*
    845 		 * The link bit of the configuration register reflects the
    846 		 * current media choice when auto-port is enabled.
    847 		 */
    848 		if (data & LEMAC_CNF_NOLINK)
    849 			req->ifm_active = IFM_10_5;
    850 		else
    851 			req->ifm_active = IFM_10_T;
    852 	}
    853 
    854 	req->ifm_active |= IFM_ETHER;
    855 }
    856 
    857 int
    859 lemac_port_check(const bus_space_tag_t iot, const bus_space_handle_t ioh)
    860 {
    861 	unsigned char hwaddr[6];
    862 
    863 	if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 0) == 0)
    864 		return 1;
    865 	if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 1) == 0)
    866 		return 1;
    867 	return 0;
    868 }
    869 
    870 void
    872 lemac_info_get(const bus_space_tag_t iot, const bus_space_handle_t ioh,
    873 	bus_addr_t *maddr_p, bus_size_t *msize_p, int *irq_p)
    874 {
    875 	unsigned data;
    876 
    877 	*irq_p = LEMAC_DECODEIRQ(bus_space_read_1(iot, ioh, LEMAC_REG_IC)
    878 	    & LEMAC_IC_IRQMSK);
    879 
    880 	data = bus_space_read_1(iot, ioh, LEMAC_REG_MBR);
    881 	if (LEMAC_IS_2K_MODE(data)) {
    882 		*maddr_p = data * (2 * 1024) + (512 * 1024);
    883 		*msize_p =  2 * 1024;
    884 	} else if (LEMAC_IS_64K_MODE(data)) {
    885 		*maddr_p = data * 64 * 1024;
    886 		*msize_p = 64 * 1024;
    887 	} else if (LEMAC_IS_32K_MODE(data)) {
    888 		*maddr_p = data * 32 * 1024;
    889 		*msize_p = 32* 1024;
    890 	} else {
    891 		*maddr_p = 0;
    892 		*msize_p = 0;
    893 	}
    894 }
    895 
    896 /*
    898  * What to do upon receipt of an interrupt.
    899  */
    900 int
    901 lemac_intr(void *arg)
    902 {
    903 	lemac_softc_t * const sc = arg;
    904 	int cs_value;
    905 
    906 	LEMAC_INTR_DISABLE(sc);	/* Mask interrupts */
    907 
    908 	/*
    909 	 * Determine cause of interrupt.  Receive events take
    910 	 * priority over Transmit.
    911 	 */
    912 
    913 	cs_value = LEMAC_INB(sc, LEMAC_REG_CS);
    914 
    915 	/*
    916 	 * Check for Receive Queue not being empty.
    917 	 * Check for Transmit Done Queue not being empty.
    918 	 */
    919 
    920 	if (cs_value & LEMAC_CS_RNE)
    921 		lemac_rne_intr(sc);
    922 	if (cs_value & LEMAC_CS_TNE)
    923 		lemac_tne_intr(sc);
    924 
    925 	/*
    926 	 * Check for Transmitter Disabled.
    927 	 * Check for Receiver Disabled.
    928 	 */
    929 
    930 	if (cs_value & LEMAC_CS_TXD)
    931 		lemac_txd_intr(sc, cs_value);
    932 	if (cs_value & LEMAC_CS_RXD)
    933 		lemac_rxd_intr(sc, cs_value);
    934 
    935 	/* Toggle LED and unmask interrupts. */
    936 
    937 	sc->sc_csr.csr_cs = LEMAC_INB(sc, LEMAC_REG_CS);
    938 
    939 	LEMAC_OUTB(sc, LEMAC_REG_CTL,
    940 	    LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED);
    941 	LEMAC_INTR_ENABLE(sc);		/* Unmask interrupts */
    942 
    943 	if (cs_value)
    944 		rnd_add_uint32(&sc->rnd_source, cs_value);
    945 
    946 	return 1;
    947 }
    948 
    949 void
    950 lemac_shutdown(void *arg)
    951 {
    952 
    953 	lemac_reset((lemac_softc_t *) arg);
    954 }
    955 
    956 static const char * const lemac_modes[4] = {
    958 	"PIO mode (internal 2KB window)",
    959 	"2KB window",
    960 	"changed 32KB window to 2KB",
    961 	"changed 64KB window to 2KB",
    962 };
    963 
    964 void
    965 lemac_ifattach(lemac_softc_t *sc)
    966 {
    967 	struct ifnet * const ifp = &sc->sc_if;
    968 
    969 	strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
    970 
    971 	lemac_reset(sc);
    972 
    973 	(void)lemac_read_macaddr(sc->sc_enaddr, sc->sc_iot, sc->sc_ioh,
    974 	    LEMAC_REG_APD, 0);
    975 
    976 	printf(": %s\n", sc->sc_prodname);
    977 
    978 	printf("%s: address %s, %dKB RAM, %s\n",
    979 	    ifp->if_xname,
    980 	    ether_sprintf(sc->sc_enaddr),
    981 	    sc->sc_lastpage * 2 + 2,
    982 	    lemac_modes[sc->sc_flags & LEMAC_MODE_MASK]);
    983 
    984 	ifp->if_softc = (void *)sc;
    985 	ifp->if_start = lemac_ifstart;
    986 	ifp->if_ioctl = lemac_ifioctl;
    987 
    988 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    989 
    990 	if (sc->sc_flags & LEMAC_ALIVE) {
    991 		int media;
    992 
    993 		IFQ_SET_READY(&ifp->if_snd);
    994 
    995 		if_attach(ifp);
    996 		if_deferred_start_init(ifp, NULL);
    997 		ether_ifattach(ifp, sc->sc_enaddr);
    998 
    999 		rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
   1000 		    RND_TYPE_NET, RND_FLAG_DEFAULT);
   1001 
   1002 		ifmedia_init(&sc->sc_ifmedia, 0,
   1003 		    lemac_ifmedia_change,
   1004 		    lemac_ifmedia_status);
   1005 		if (sc->sc_prodname[4] == '5')	/* DE205 is UTP/AUI */
   1006 			ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO,
   1007 			    0, 0);
   1008 		if (sc->sc_prodname[4] != '3')	/* DE204 & 205 have UTP */
   1009 			ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T,
   1010 			    0, 0);
   1011 		if (sc->sc_prodname[4] != '4')	/* DE203 & 205 have BNC */
   1012 			ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_5,
   1013 			    0, 0);
   1014 		switch (sc->sc_prodname[4]) {
   1015 		case '3': media = IFM_10_5; break;
   1016 		case '4': media = IFM_10_T; break;
   1017 		default:  media = IFM_AUTO; break;
   1018 		}
   1019 		ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | media);
   1020 	} else
   1021 		printf("%s: disabled due to error\n", ifp->if_xname);
   1022 }
   1023