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