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