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