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