[BACK]Return to lemac.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/lemac.c, Revision 1.1.1.1

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

CVSweb