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