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

Annotation of sys/dev/pci/if_lmc.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_lmc.c,v 1.23 2006/05/13 19:10:02 brad Exp $ */
                      2: /*     $NetBSD: if_lmc.c,v 1.1 1999/03/25 03:32:43 explorer Exp $      */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1997-1999 LAN Media Corporation (LMC)
                      6:  * All rights reserved.  www.lanmedia.com
                      7:  *
                      8:  * This code is written by Michael Graff <graff@vix.com> for LMC.
                      9:  * The code is derived from permitted modifications to software created
                     10:  * by Matt Thomas (matt@3am-software.com).
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above
                     18:  *    copyright notice, this list of conditions and the following disclaimer
                     19:  *    in the documentation and/or other materials provided with the
                     20:  *    distribution.
                     21:  * 3. All marketing or advertising materials mentioning features or
                     22:  *    use of this software must display the following acknowledgement:
                     23:  *      This product includes software developed by LAN Media Corporation
                     24:  *      and its contributors.
                     25:  * 4. Neither the name of LAN Media Corporation nor the names of its
                     26:  *    contributors may be used to endorse or promote products derived
                     27:  *    from this software without specific prior written permission.
                     28:  *
                     29:  * THIS SOFTWARE IS PROVIDED BY LAN MEDIA CORPORATION AND CONTRIBUTORS
                     30:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     31:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     32:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     33:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     34:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     35:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     36:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     37:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     38:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     39:  * THE POSSIBILITY OF SUCH DAMAGE.
                     40:  */
                     41:
                     42: /*-
                     43:  * Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
                     44:  * All rights reserved.
                     45:  *
                     46:  * Redistribution and use in source and binary forms, with or without
                     47:  * modification, are permitted provided that the following conditions
                     48:  * are met:
                     49:  * 1. Redistributions of source code must retain the above copyright
                     50:  *    notice, this list of conditions and the following disclaimer.
                     51:  * 2. The name of the author may not be used to endorse or promote products
                     52:  *    derived from this software without specific prior written permission
                     53:  *
                     54:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     55:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     56:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     57:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     58:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     59:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     60:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     61:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     62:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     63:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     64:  */
                     65:
                     66: /*
                     67:  * LMC1200 (DS1) & LMC5245 (DS3) LED definitions
                     68:  * led0 yellow = far-end link is in Red alarm condition
                     69:  * led1 blue   = received an Alarm Indication signal (upstream failure)
                     70:  * led2 Green  = power to adapter, Gate Array loaded & driver attached
                     71:  * led3 red    = Loss of Signal (LOS) or out of frame (OOF) conditions
                     72:  *               detected on T3 receive signal
                     73:  *
                     74:  * LMC1000 (SSI) & LMC5200 (HSSI) LED definitions
                     75:  * led0 Green  = power to adapter, Gate Array loaded & driver attached
                     76:  * led1 Green  = DSR and DTR and RTS and CTS are set (CA, TA for LMC5200)
                     77:  * led2 Green  = Cable detected (Green indicates non-loopback mode for LMC5200)
                     78:  * led3 red    = No timing is available from the cable or the on-board
                     79:  *               frequency generator. (ST not available for LMC5200)
                     80:  */
                     81:
                     82: #include "bpfilter.h"
                     83:
                     84: #include <sys/param.h>
                     85: #include <sys/systm.h>
                     86: #include <sys/mbuf.h>
                     87: #include <sys/socket.h>
                     88: #include <sys/ioctl.h>
                     89: #include <sys/errno.h>
                     90: #include <sys/malloc.h>
                     91: #include <sys/kernel.h>
                     92: #include <sys/proc.h>
                     93: #include <sys/device.h>
                     94:
                     95: #include <dev/pci/pcidevs.h>
                     96:
                     97: #include <net/if.h>
                     98: #include <net/if_types.h>
                     99: #include <net/if_dl.h>
                    100: #include <net/netisr.h>
                    101:
                    102: #if NBPFILTER > 0
                    103: #include <net/bpf.h>
                    104: #endif
                    105:
                    106: #include <net/if_sppp.h>
                    107:
                    108: #include <machine/bus.h>
                    109:
                    110: #include <dev/pci/pcireg.h>
                    111: #include <dev/pci/pcivar.h>
                    112: #include <dev/ic/dc21040reg.h>
                    113:
                    114: #include <dev/pci/if_lmc_types.h>
                    115: #include <dev/pci/if_lmcioctl.h>
                    116: #include <dev/pci/if_lmcvar.h>
                    117:
                    118: /*
                    119:  * This module supports
                    120:  *     the DEC 21140A pass 2.2 PCI Fast Ethernet Controller.
                    121:  */
                    122: static ifnet_ret_t lmc_ifstart_one(struct ifnet *ifp);
                    123: static ifnet_ret_t lmc_ifstart(struct ifnet *ifp);
                    124: static struct mbuf *lmc_txput(lmc_softc_t * const sc, struct mbuf *m);
                    125: static void lmc_rx_intr(lmc_softc_t * const sc);
                    126:
                    127: static void lmc_watchdog(struct ifnet *ifp);
                    128: static void lmc_ifup(lmc_softc_t * const sc);
                    129: static void lmc_ifdown(lmc_softc_t * const sc);
                    130:
                    131: /*
                    132:  * Code the read the SROM and MII bit streams (I2C)
                    133:  */
                    134: static inline void
                    135: lmc_delay_300ns(lmc_softc_t * const sc)
                    136: {
                    137:        int idx;
                    138:        for (idx = (300 / 33) + 1; idx > 0; idx--)
                    139:                (void)LMC_CSR_READ(sc, csr_busmode);
                    140: }
                    141:
                    142: #define EMIT    \
                    143: do { \
                    144:        LMC_CSR_WRITE(sc, csr_srom_mii, csr); \
                    145:        lmc_delay_300ns(sc); \
                    146: } while (0)
                    147:
                    148: static inline void
                    149: lmc_srom_idle(lmc_softc_t * const sc)
                    150: {
                    151:        unsigned bit, csr;
                    152:
                    153:        csr  = SROMSEL ; EMIT;
                    154:        csr  = SROMSEL | SROMRD; EMIT;
                    155:        csr ^= SROMCS; EMIT;
                    156:        csr ^= SROMCLKON; EMIT;
                    157:
                    158:        /*
                    159:         * Write 25 cycles of 0 which will force the SROM to be idle.
                    160:         */
                    161:        for (bit = 3 + SROM_BITWIDTH + 16; bit > 0; bit--) {
                    162:                csr ^= SROMCLKOFF; EMIT;    /* clock low; data not valid */
                    163:                csr ^= SROMCLKON; EMIT;     /* clock high; data valid */
                    164:        }
                    165:        csr ^= SROMCLKOFF; EMIT;
                    166:        csr ^= SROMCS; EMIT;
                    167:        csr  = 0; EMIT;
                    168: }
                    169:
                    170:
                    171: static void
                    172: lmc_srom_read(lmc_softc_t * const sc)
                    173: {
                    174:        unsigned idx;
                    175:        const unsigned bitwidth = SROM_BITWIDTH;
                    176:        const unsigned cmdmask = (SROMCMD_RD << bitwidth);
                    177:        const unsigned msb = 1 << (bitwidth + 3 - 1);
                    178:        unsigned lastidx = (1 << bitwidth) - 1;
                    179:
                    180:        lmc_srom_idle(sc);
                    181:
                    182:        for (idx = 0; idx <= lastidx; idx++) {
                    183:                unsigned lastbit, data, bits, bit, csr;
                    184:                csr  = SROMSEL ;                EMIT;
                    185:                csr  = SROMSEL | SROMRD;        EMIT;
                    186:                csr ^= SROMCSON;                EMIT;
                    187:                csr ^=            SROMCLKON;    EMIT;
                    188:
                    189:                lastbit = 0;
                    190:                for (bits = idx|cmdmask, bit = bitwidth + 3
                    191:                             ; bit > 0
                    192:                             ; bit--, bits <<= 1) {
                    193:                        const unsigned thisbit = bits & msb;
                    194:                        csr ^= SROMCLKOFF; EMIT;    /* clock L data invalid */
                    195:                        if (thisbit != lastbit) {
                    196:                                csr ^= SROMDOUT; EMIT;/* clock L invert data */
                    197:                        } else {
                    198:                                EMIT;
                    199:                        }
                    200:                        csr ^= SROMCLKON; EMIT;     /* clock H data valid */
                    201:                        lastbit = thisbit;
                    202:                }
                    203:                csr ^= SROMCLKOFF; EMIT;
                    204:
                    205:                for (data = 0, bits = 0; bits < 16; bits++) {
                    206:                        data <<= 1;
                    207:                        csr ^= SROMCLKON; EMIT;     /* clock H data valid */
                    208:                        data |= LMC_CSR_READ(sc, csr_srom_mii) & SROMDIN ? 1 : 0;
                    209:                        csr ^= SROMCLKOFF; EMIT;    /* clock L data invalid */
                    210:                }
                    211:                sc->lmc_rombuf[idx*2] = data & 0xFF;
                    212:                sc->lmc_rombuf[idx*2+1] = data >> 8;
                    213:                csr  = SROMSEL | SROMRD; EMIT;
                    214:                csr  = 0; EMIT;
                    215:        }
                    216:        lmc_srom_idle(sc);
                    217: }
                    218: 
                    219: #define MII_EMIT    do { LMC_CSR_WRITE(sc, csr_srom_mii, csr); lmc_delay_300ns(sc); } while (0)
                    220:
                    221: static inline void
                    222: lmc_mii_writebits(lmc_softc_t * const sc, unsigned data, unsigned bits)
                    223: {
                    224:     unsigned msb = 1 << (bits - 1);
                    225:     unsigned csr = LMC_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
                    226:     unsigned lastbit = (csr & MII_DOUT) ? msb : 0;
                    227:
                    228:     csr |= MII_WR; MII_EMIT;           /* clock low; assert write */
                    229:
                    230:     for (; bits > 0; bits--, data <<= 1) {
                    231:        const unsigned thisbit = data & msb;
                    232:        if (thisbit != lastbit) {
                    233:            csr ^= MII_DOUT; MII_EMIT;  /* clock low; invert data */
                    234:        }
                    235:        csr ^= MII_CLKON; MII_EMIT;     /* clock high; data valid */
                    236:        lastbit = thisbit;
                    237:        csr ^= MII_CLKOFF; MII_EMIT;    /* clock low; data not valid */
                    238:     }
                    239: }
                    240:
                    241: static void
                    242: lmc_mii_turnaround(lmc_softc_t * const sc, u_int32_t cmd)
                    243: {
                    244:     u_int32_t csr;
                    245:
                    246:     csr = LMC_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
                    247:     if (cmd == MII_WRCMD) {
                    248:        csr |= MII_DOUT; MII_EMIT;      /* clock low; change data */
                    249:        csr ^= MII_CLKON; MII_EMIT;     /* clock high; data valid */
                    250:        csr ^= MII_CLKOFF; MII_EMIT;    /* clock low; data not valid */
                    251:        csr ^= MII_DOUT; MII_EMIT;      /* clock low; change data */
                    252:     } else {
                    253:        csr |= MII_RD; MII_EMIT;        /* clock low; switch to read */
                    254:     }
                    255:     csr ^= MII_CLKON; MII_EMIT;                /* clock high; data valid */
                    256:     csr ^= MII_CLKOFF; MII_EMIT;       /* clock low; data not valid */
                    257: }
                    258:
                    259: static u_int32_t
                    260: lmc_mii_readbits(lmc_softc_t * const sc)
                    261: {
                    262:     u_int32_t data;
                    263:     u_int32_t csr = LMC_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
                    264:     int idx;
                    265:
                    266:     for (idx = 0, data = 0; idx < 16; idx++) {
                    267:        data <<= 1;     /* this is NOOP on the first pass through */
                    268:        csr ^= MII_CLKON; MII_EMIT;     /* clock high; data valid */
                    269:        if (LMC_CSR_READ(sc, csr_srom_mii) & MII_DIN)
                    270:            data |= 1;
                    271:        csr ^= MII_CLKOFF; MII_EMIT;    /* clock low; data not valid */
                    272:     }
                    273:     csr ^= MII_RD; MII_EMIT;           /* clock low; turn off read */
                    274:
                    275:     return data;
                    276: }
                    277:
                    278: u_int32_t
                    279: lmc_mii_readreg(lmc_softc_t * const sc, u_int32_t devaddr, u_int32_t regno)
                    280: {
                    281:     u_int32_t csr = LMC_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
                    282:     u_int32_t data;
                    283:
                    284:     csr &= ~(MII_RD|MII_CLK); MII_EMIT;
                    285:     lmc_mii_writebits(sc, MII_PREAMBLE, 32);
                    286:     lmc_mii_writebits(sc, MII_RDCMD, 8);
                    287:     lmc_mii_writebits(sc, devaddr, 5);
                    288:     lmc_mii_writebits(sc, regno, 5);
                    289:     lmc_mii_turnaround(sc, MII_RDCMD);
                    290:
                    291:     data = lmc_mii_readbits(sc);
                    292:     return (data);
                    293: }
                    294:
                    295: void
                    296: lmc_mii_writereg(lmc_softc_t * const sc, u_int32_t devaddr,
                    297:                   u_int32_t regno, u_int32_t data)
                    298: {
                    299:     u_int32_t csr;
                    300:
                    301:     csr = LMC_CSR_READ(sc, csr_srom_mii) & (MII_RD|MII_DOUT|MII_CLK);
                    302:     csr &= ~(MII_RD|MII_CLK); MII_EMIT;
                    303:     lmc_mii_writebits(sc, MII_PREAMBLE, 32);
                    304:     lmc_mii_writebits(sc, MII_WRCMD, 8);
                    305:     lmc_mii_writebits(sc, devaddr, 5);
                    306:     lmc_mii_writebits(sc, regno, 5);
                    307:     lmc_mii_turnaround(sc, MII_WRCMD);
                    308:     lmc_mii_writebits(sc, data, 16);
                    309: }
                    310: 
                    311: int
                    312: lmc_read_macaddr(lmc_softc_t * const sc)
                    313: {
                    314:        lmc_srom_read(sc);
                    315:
                    316:        bcopy(sc->lmc_rombuf + 20, sc->lmc_enaddr, 6);
                    317:
                    318:        return 0;
                    319: }
                    320: 
                    321: /*
                    322:  * Check to make certain there is a signal from the modem, and flicker
                    323:  * lights as needed.
                    324:  */
                    325: static void
                    326: lmc_watchdog(struct ifnet *ifp)
                    327: {
                    328:        lmc_softc_t * const sc = LMC_IFP_TO_SOFTC(ifp);
                    329:        int state;
                    330:        u_int32_t ostatus;
                    331:        u_int32_t link_status;
                    332:        u_int32_t ticks;
                    333:
                    334:        state = 0;
                    335:
                    336:        /*
                    337:         * Make sure the tx jabber and rx watchdog are off,
                    338:         * and the transmit and receive processes are running.
                    339:         */
                    340:        LMC_CSR_WRITE (sc, csr_15, 0x00000011);
                    341:        sc->lmc_cmdmode |= TULIP_CMD_TXRUN | TULIP_CMD_RXRUN;
                    342:        LMC_CSR_WRITE (sc, csr_command, sc->lmc_cmdmode);
                    343:
                    344:        /* Is the transmit clock still available? */
                    345:        ticks = LMC_CSR_READ (sc, csr_gp_timer);
                    346:        ticks = 0x0000ffff - (ticks & 0x0000ffff);
                    347:        if (ticks == 0)
                    348:        {
                    349:                /* no clock found ? */
                    350:                if (sc->tx_clockState != 0)
                    351:                {
                    352:                        sc->tx_clockState = 0;
                    353:                        if (sc->lmc_cardtype == LMC_CARDTYPE_SSI)
                    354:                                lmc_led_on (sc, LMC_MII16_LED3); /* ON red */
                    355:                }
                    356:        else
                    357:                if (sc->tx_clockState == 0)
                    358:                {
                    359:                        sc->tx_clockState = 1;
                    360:                        if (sc->lmc_cardtype == LMC_CARDTYPE_SSI)
                    361:                                lmc_led_off (sc, LMC_MII16_LED3); /* OFF red */
                    362:                }
                    363:        }
                    364:
                    365:        link_status = sc->lmc_media->get_link_status(sc);
                    366:        ostatus = ((sc->lmc_flags & LMC_MODEMOK) == LMC_MODEMOK);
                    367:
                    368:        /*
                    369:         * hardware level link lost, but the interface is marked as up.
                    370:         * Mark it as down.
                    371:         */
                    372:         if (link_status == LMC_LINK_DOWN && ostatus) {
                    373:                printf(LMC_PRINTF_FMT ": physical link down\n",
                    374:                       LMC_PRINTF_ARGS);
                    375:                sc->lmc_flags &= ~LMC_MODEMOK;
                    376:                if (sc->lmc_cardtype == LMC_CARDTYPE_DS3 ||
                    377:                    sc->lmc_cardtype == LMC_CARDTYPE_T1)
                    378:                        lmc_led_on (sc, LMC_DS3_LED3 | LMC_DS3_LED2);
                    379:                                                        /* turn on red LED */
                    380:                else {
                    381:                        lmc_led_off (sc, LMC_MII16_LED1);
                    382:                        lmc_led_on (sc, LMC_MII16_LED0);
                    383:                        if (sc->lmc_timing == LMC_CTL_CLOCK_SOURCE_EXT)
                    384:                                lmc_led_on (sc, LMC_MII16_LED3);
                    385:                }
                    386:
                    387:        }
                    388:
                    389:        /*
                    390:         * hardware link is up, but the interface is marked as down.
                    391:         * Bring it back up again.
                    392:         */
                    393:        if (link_status != LMC_LINK_DOWN && !ostatus) {
                    394:                printf(LMC_PRINTF_FMT ": physical link up\n",
                    395:                       LMC_PRINTF_ARGS);
                    396:                if (sc->lmc_flags & LMC_IFUP)
                    397:                        lmc_ifup(sc);
                    398:                sc->lmc_flags |= LMC_MODEMOK;
                    399:                if (sc->lmc_cardtype == LMC_CARDTYPE_DS3 ||
                    400:                    sc->lmc_cardtype == LMC_CARDTYPE_T1)
                    401:                {
                    402:                        sc->lmc_miireg16 |= LMC_DS3_LED3;
                    403:                        lmc_led_off (sc, LMC_DS3_LED3);
                    404:                                                        /* turn off red LED */
                    405:                        lmc_led_on (sc, LMC_DS3_LED2);
                    406:                } else {
                    407:                        lmc_led_on (sc, LMC_MII16_LED0 | LMC_MII16_LED1
                    408:                                    | LMC_MII16_LED2);
                    409:                        if (sc->lmc_timing != LMC_CTL_CLOCK_SOURCE_EXT)
                    410:                                lmc_led_off (sc, LMC_MII16_LED3);
                    411:                }
                    412:
                    413:                return;
                    414:        }
                    415:
                    416:        /* Call media specific watchdog functions */
                    417:        sc->lmc_media->watchdog(sc);
                    418:
                    419:        /*
                    420:         * remember the timer value
                    421:         */
                    422:        ticks = LMC_CSR_READ(sc, csr_gp_timer);
                    423:        LMC_CSR_WRITE(sc, csr_gp_timer, 0xffffffffUL);
                    424:        sc->ictl.ticks = 0x0000ffff - (ticks & 0x0000ffff);
                    425:
                    426:        ifp->if_timer = 1;
                    427: }
                    428:
                    429: /*
                    430:  * Mark the interface as "up" and enable TX/RX and TX/RX interrupts.
                    431:  * This also does a full software reset.
                    432:  */
                    433: static void
                    434: lmc_ifup(lmc_softc_t * const sc)
                    435: {
                    436:        sc->lmc_if.if_timer = 0;
                    437:
                    438:        lmc_dec_reset(sc);
                    439:        lmc_reset(sc);
                    440:
                    441:        sc->lmc_media->set_link_status(sc, LMC_LINK_UP);
                    442:        sc->lmc_media->set_status(sc, NULL);
                    443:
                    444:        sc->lmc_flags |= LMC_IFUP;
                    445:
                    446:        /*
                    447:         * for DS3 & DS1 adapters light the green light, led2
                    448:         */
                    449:        if (sc->lmc_cardtype == LMC_CARDTYPE_DS3 ||
                    450:            sc->lmc_cardtype == LMC_CARDTYPE_T1)
                    451:                lmc_led_on (sc, LMC_MII16_LED2);
                    452:        else
                    453:                lmc_led_on (sc, LMC_MII16_LED0 | LMC_MII16_LED2);
                    454:
                    455:        /*
                    456:         * select what interrupts we want to get
                    457:         */
                    458:        sc->lmc_intrmask |= (TULIP_STS_NORMALINTR
                    459:                               | TULIP_STS_RXINTR
                    460:                               | TULIP_STS_RXNOBUF
                    461:                               | TULIP_STS_TXINTR
                    462:                               | TULIP_STS_ABNRMLINTR
                    463:                               | TULIP_STS_SYSERROR
                    464:                               | TULIP_STS_TXSTOPPED
                    465:                               | TULIP_STS_TXUNDERFLOW
                    466:                               | TULIP_STS_RXSTOPPED
                    467:                               );
                    468:        LMC_CSR_WRITE(sc, csr_intr, sc->lmc_intrmask);
                    469:
                    470:        sc->lmc_cmdmode |= TULIP_CMD_TXRUN;
                    471:        sc->lmc_cmdmode |= TULIP_CMD_RXRUN;
                    472:        LMC_CSR_WRITE(sc, csr_command, sc->lmc_cmdmode);
                    473:
                    474:        sc->lmc_if.if_timer = 1;
                    475: }
                    476:
                    477: /*
                    478:  * Mark the interface as "down" and disable TX/RX and TX/RX interrupts.
                    479:  * This is done by performing a full reset on the interface.
                    480:  */
                    481: static void
                    482: lmc_ifdown(lmc_softc_t * const sc)
                    483: {
                    484:        sc->lmc_if.if_timer = 0;
                    485:        sc->lmc_flags &= ~LMC_IFUP;
                    486:
                    487:        sc->lmc_media->set_link_status(sc, LMC_LINK_DOWN);
                    488:        lmc_led_off(sc, LMC_MII16_LED_ALL);
                    489:
                    490:        lmc_dec_reset(sc);
                    491:        lmc_reset(sc);
                    492:        sc->lmc_media->set_status(sc, NULL);
                    493: }
                    494:
                    495: static void
                    496: lmc_rx_intr(lmc_softc_t * const sc)
                    497: {
                    498:        lmc_ringinfo_t * const ri = &sc->lmc_rxinfo;
                    499:        struct ifnet * const ifp = &sc->lmc_if;
                    500:        u_int32_t status;
                    501:        int fillok = 1;
                    502:
                    503:        sc->lmc_rxtick++;
                    504:
                    505:        for (;;) {
                    506:                lmc_desc_t *eop = ri->ri_nextin;
                    507:                int total_len = 0, last_offset = 0;
                    508:                struct mbuf *ms = NULL, *me = NULL;
                    509:                int accept = 0;
                    510:                bus_dmamap_t map;
                    511:                int error;
                    512:
                    513:                if (fillok && sc->lmc_rxq.ifq_len < LMC_RXQ_TARGET)
                    514:                        goto queue_mbuf;
                    515:
                    516:                /*
                    517:                 * If the TULIP has no descriptors, there can't be any receive
                    518:                 * descriptors to process.
                    519:                 */
                    520:                if (eop == ri->ri_nextout)
                    521:                        break;
                    522:
                    523:                /*
                    524:                 * 90% of the packets will fit in one descriptor.  So we
                    525:                 * optimize for that case.
                    526:                 */
                    527:                LMC_RXDESC_POSTSYNC(sc, eop, sizeof(*eop));
                    528:                status = letoh32(((volatile lmc_desc_t *) eop)->d_status);
                    529:                if ((status &
                    530:                        (TULIP_DSTS_OWNER|TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) ==
                    531:                        (TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) {
                    532:                        IF_DEQUEUE(&sc->lmc_rxq, ms);
                    533:                        me = ms;
                    534:                } else {
                    535:                        /*
                    536:                         * If still owned by the TULIP, don't touch it.
                    537:                         */
                    538:                        if (status & TULIP_DSTS_OWNER)
                    539:                                break;
                    540:
                    541:                        /*
                    542:                         * It is possible (though improbable unless the
                    543:                         * BIG_PACKET support is enabled or MCLBYTES < 1518)
                    544:                         * for a received packet to cross more than one
                    545:                         * receive descriptor.
                    546:                         */
                    547:                        while ((status & TULIP_DSTS_RxLASTDESC) == 0) {
                    548:                                if (++eop == ri->ri_last)
                    549:                                        eop = ri->ri_first;
                    550:                                LMC_RXDESC_POSTSYNC(sc, eop, sizeof(*eop));
                    551:                                status = letoh32(((volatile lmc_desc_t *)
                    552:                                        eop)->d_status);
                    553:                                if (eop == ri->ri_nextout ||
                    554:                                        (status & TULIP_DSTS_OWNER)) {
                    555:                                        return;
                    556:                                }
                    557:                                total_len++;
                    558:                        }
                    559:
                    560:                        /*
                    561:                         * Dequeue the first buffer for the start of the
                    562:                         * packet.  Hopefully this will be the only one we
                    563:                         * need to dequeue.  However, if the packet consumed
                    564:                         * multiple descriptors, then we need to dequeue
                    565:                         * those buffers and chain to the starting mbuf.
                    566:                         * All buffers but the last buffer have the same
                    567:                         * length so we can set that now. (we add to
                    568:                         * last_offset instead of multiplying since we
                    569:                         * normally won't go into the loop and thereby
                    570:                         * saving a ourselves from doing a multiplication
                    571:                         * by 0 in the normal case).
                    572:                         */
                    573:                        IF_DEQUEUE(&sc->lmc_rxq, ms);
                    574:                        for (me = ms; total_len > 0; total_len--) {
                    575:                                map = LMC_GETCTX(me, bus_dmamap_t);
                    576:                                LMC_RXMAP_POSTSYNC(sc, map);
                    577:                                bus_dmamap_unload(sc->lmc_dmatag, map);
                    578:                                sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map;
                    579: #if defined(DIAGNOSTIC)
                    580:                                LMC_SETCTX(me, NULL);
                    581: #endif
                    582:                                me->m_len = LMC_RX_BUFLEN;
                    583:                                last_offset += LMC_RX_BUFLEN;
                    584:                                IF_DEQUEUE(&sc->lmc_rxq, me->m_next);
                    585:                                me = me->m_next;
                    586:                        }
                    587:                }
                    588:
                    589:                /*
                    590:                 *  Now get the size of received packet (minus the CRC).
                    591:                 */
                    592:                total_len = ((status >> 16) & 0x7FFF);
                    593:                if (sc->ictl.crc_length == 16)
                    594:                        total_len -= 2;
                    595:                else
                    596:                        total_len -= 4;
                    597:
                    598:                if ((sc->lmc_flags & LMC_RXIGNORE) == 0
                    599:                    && ((status & LMC_DSTS_ERRSUM) == 0
                    600: #ifdef BIG_PACKET
                    601:                        || (total_len <= sc->lmc_if.if_mtu + PPP_HEADER_LEN
                    602:                            && (status & TULIP_DSTS_RxOVERFLOW) == 0)
                    603: #endif
                    604:                        )) {
                    605:
                    606:                        map = LMC_GETCTX(me, bus_dmamap_t);
                    607:                        bus_dmamap_sync(sc->lmc_dmatag, map, 0, me->m_len,
                    608:                                BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
                    609:                        bus_dmamap_unload(sc->lmc_dmatag, map);
                    610:                        sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map;
                    611: #if defined(DIAGNOSTIC)
                    612:                        LMC_SETCTX(me, NULL);
                    613: #endif
                    614:
                    615:                        me->m_len = total_len - last_offset;
                    616: #if NBPFILTER > 0
                    617:                        if (sc->lmc_bpf != NULL) {
                    618:                                if (me == ms)
                    619:                                        LMC_BPF_TAP(sc, mtod(ms, caddr_t),
                    620:                                            total_len, BPF_DIRECTION_IN);
                    621:                                else
                    622:                                        LMC_BPF_MTAP(sc, ms, BPF_DIRECTION_IN);
                    623:                        }
                    624: #endif
                    625:                        sc->lmc_flags |= LMC_RXACT;
                    626:                        accept = 1;
                    627:                } else {
                    628:                        ifp->if_ierrors++;
                    629:                        if (status & TULIP_DSTS_RxOVERFLOW) {
                    630:                                sc->lmc_dot3stats.dot3StatsInternalMacReceiveErrors++;
                    631:                        }
                    632:                        map = LMC_GETCTX(me, bus_dmamap_t);
                    633:                        bus_dmamap_unload(sc->lmc_dmatag, map);
                    634:                        sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map;
                    635: #if defined(DIAGNOSTIC)
                    636:                        LMC_SETCTX(me, NULL);
                    637: #endif
                    638:                }
                    639:
                    640:                ifp->if_ipackets++;
                    641:                if (++eop == ri->ri_last)
                    642:                        eop = ri->ri_first;
                    643:                ri->ri_nextin = eop;
                    644:
                    645:        queue_mbuf:
                    646:                /*
                    647:                 * Either we are priming the TULIP with mbufs (m == NULL)
                    648:                 * or we are about to accept an mbuf for the upper layers
                    649:                 * so we need to allocate an mbuf to replace it.  If we
                    650:                 * can't replace it, send up it anyways.  This may cause
                    651:                 * us to drop packets in the future but that's better than
                    652:                 * being caught in livelock.
                    653:                 *
                    654:                 * Note that if this packet crossed multiple descriptors
                    655:                 * we don't even try to reallocate all the mbufs here.
                    656:                 * Instead we rely on the test of the beginning of
                    657:                 * the loop to refill for the extra consumed mbufs.
                    658:                 */
                    659:                if (accept || ms == NULL) {
                    660:                        struct mbuf *m0;
                    661:                        MGETHDR(m0, M_DONTWAIT, MT_DATA);
                    662:                        if (m0 != NULL) {
                    663:                                MCLGET(m0, M_DONTWAIT);
                    664:                                if ((m0->m_flags & M_EXT) == 0) {
                    665:                                        m_freem(m0);
                    666:                                        m0 = NULL;
                    667:                                }
                    668:                        }
                    669:                        if (accept) {
                    670:                                ms->m_pkthdr.len = total_len;
                    671:                                ms->m_pkthdr.rcvif = ifp;
                    672:                                sppp_input(ifp, ms);
                    673:                        }
                    674:                        ms = m0;
                    675:                }
                    676:                if (ms == NULL) {
                    677:                        /*
                    678:                         * Couldn't allocate a new buffer.  Don't bother
                    679:                         * trying to replenish the receive queue.
                    680:                         */
                    681:                        fillok = 0;
                    682:                        sc->lmc_flags |= LMC_RXBUFSLOW;
                    683:                        continue;
                    684:                }
                    685:                /*
                    686:                 * Now give the buffer(s) to the TULIP and save in our
                    687:                 * receive queue.
                    688:                 */
                    689:                do {
                    690:                        u_int32_t ctl;
                    691:                        lmc_desc_t * const nextout = ri->ri_nextout;
                    692:
                    693:                        if (sc->lmc_rxmaps_free > 0) {
                    694:                                map = sc->lmc_rxmaps[--sc->lmc_rxmaps_free];
                    695:                        } else {
                    696:                                m_freem(ms);
                    697:                                sc->lmc_flags |= LMC_RXBUFSLOW;
                    698: #if defined(LMC_DEBUG)
                    699:                                sc->lmc_dbg.dbg_rxlowbufs++;
                    700: #endif
                    701:                                break;
                    702:                        }
                    703:                        LMC_SETCTX(ms, map);
                    704:                        error = bus_dmamap_load(sc->lmc_dmatag, map,
                    705:                                mtod(ms, void *), LMC_RX_BUFLEN,
                    706:                                NULL, BUS_DMA_NOWAIT);
                    707:                        if (error) {
                    708:                                printf(LMC_PRINTF_FMT
                    709:                                        ": unable to load rx map, "
                    710:                                        "error = %d\n",
                    711:                                        LMC_PRINTF_ARGS, error);
                    712:                                panic("lmc_rx_intr");           /* XXX */
                    713:                        }
                    714:
                    715:                        ctl = letoh32(nextout->d_ctl);
                    716:                        /* For some weird reason we lose TULIP_DFLAG_ENDRING */
                    717:                        if ((nextout+1) == ri->ri_last)
                    718:                                ctl = LMC_CTL(LMC_CTL_FLGS(ctl)|
                    719:                                        TULIP_DFLAG_ENDRING, 0, 0);
                    720:                        nextout->d_addr1 = htole32(map->dm_segs[0].ds_addr);
                    721:                        if (map->dm_nsegs == 2) {
                    722:                                nextout->d_addr2 = htole32(map->dm_segs[1].ds_addr);
                    723:                                nextout->d_ctl =
                    724:                                        htole32(LMC_CTL(LMC_CTL_FLGS(ctl),
                    725:                                                map->dm_segs[0].ds_len,
                    726:                                                map->dm_segs[1].ds_len));
                    727:                        } else {
                    728:                                nextout->d_addr2 = 0;
                    729:                                nextout->d_ctl =
                    730:                                        htole32(LMC_CTL(LMC_CTL_FLGS(ctl),
                    731:                                                map->dm_segs[0].ds_len, 0));
                    732:                        }
                    733:                        LMC_RXDESC_POSTSYNC(sc, nextout, sizeof(*nextout));
                    734:                        ri->ri_nextout->d_status = htole32(TULIP_DSTS_OWNER);
                    735:                        LMC_RXDESC_POSTSYNC(sc, nextout, sizeof(u_int32_t));
                    736:                        if (++ri->ri_nextout == ri->ri_last)
                    737:                                ri->ri_nextout = ri->ri_first;
                    738:                        me = ms->m_next;
                    739:                        ms->m_next = NULL;
                    740:                        IF_ENQUEUE(&sc->lmc_rxq, ms);
                    741:                } while ((ms = me) != NULL);
                    742:
                    743:                if (sc->lmc_rxq.ifq_len >= LMC_RXQ_TARGET)
                    744:                        sc->lmc_flags &= ~LMC_RXBUFSLOW;
                    745:        }
                    746: }
                    747: 
                    748: static int
                    749: lmc_tx_intr(lmc_softc_t * const sc)
                    750: {
                    751:     lmc_ringinfo_t * const ri = &sc->lmc_txinfo;
                    752:     struct mbuf *m;
                    753:     int xmits = 0;
                    754:     int descs = 0;
                    755:     u_int32_t d_status;
                    756:
                    757:     sc->lmc_txtick++;
                    758:
                    759:     while (ri->ri_free < ri->ri_max) {
                    760:        u_int32_t flag;
                    761:
                    762:        LMC_TXDESC_POSTSYNC(sc, ri->ri_nextin, sizeof(*ri->ri_nextin));
                    763:        d_status = letoh32(((volatile lmc_desc_t *) ri->ri_nextin)->d_status);
                    764:        if (d_status & TULIP_DSTS_OWNER)
                    765:            break;
                    766:
                    767:        flag = LMC_CTL_FLGS(letoh32(ri->ri_nextin->d_ctl));
                    768:        if (flag & TULIP_DFLAG_TxLASTSEG) {
                    769:                IF_DEQUEUE(&sc->lmc_txq, m);
                    770:                if (m != NULL) {
                    771:                    bus_dmamap_t map = LMC_GETCTX(m, bus_dmamap_t);
                    772:                    LMC_TXMAP_POSTSYNC(sc, map);
                    773:                    sc->lmc_txmaps[sc->lmc_txmaps_free++] = map;
                    774: #if NBPFILTER > 0
                    775:                    if (sc->lmc_bpf != NULL)
                    776:                        LMC_BPF_MTAP(sc, m, BPF_DIRECTION_OUT);
                    777: #endif
                    778:                    m_freem(m);
                    779: #if defined(LMC_DEBUG)
                    780:                } else {
                    781:                    printf(LMC_PRINTF_FMT ": tx_intr: failed to dequeue mbuf?!?\n", LMC_PRINTF_ARGS);
                    782: #endif
                    783:                }
                    784:                    xmits++;
                    785:                    if (d_status & LMC_DSTS_ERRSUM) {
                    786:                        sc->lmc_if.if_oerrors++;
                    787:                        if (d_status & TULIP_DSTS_TxUNDERFLOW) {
                    788:                            sc->lmc_dot3stats.dot3StatsInternalTransmitUnderflows++;
                    789:                        }
                    790:                    } else {
                    791:                        if (d_status & TULIP_DSTS_TxDEFERRED) {
                    792:                            sc->lmc_dot3stats.dot3StatsDeferredTransmissions++;
                    793:                        }
                    794:                    }
                    795:        }
                    796:
                    797:        if (++ri->ri_nextin == ri->ri_last)
                    798:            ri->ri_nextin = ri->ri_first;
                    799:
                    800:        ri->ri_free++;
                    801:        descs++;
                    802:        sc->lmc_if.if_flags &= ~IFF_OACTIVE;
                    803:     }
                    804:     /*
                    805:      * If nothing left to transmit, disable the timer.
                    806:      * Else if progress, reset the timer back to 2 ticks.
                    807:      */
                    808:     sc->lmc_if.if_opackets += xmits;
                    809:
                    810:     return descs;
                    811: }
                    812: 
                    813: static void
                    814: lmc_print_abnormal_interrupt (lmc_softc_t * const sc, u_int32_t csr)
                    815: {
                    816:        printf(LMC_PRINTF_FMT ": Abnormal interrupt\n", LMC_PRINTF_ARGS);
                    817: }
                    818:
                    819: static const char * const lmc_system_errors[] = {
                    820:     "parity error",
                    821:     "master abort",
                    822:     "target abort",
                    823:     "reserved #3",
                    824:     "reserved #4",
                    825:     "reserved #5",
                    826:     "reserved #6",
                    827:     "reserved #7",
                    828: };
                    829:
                    830: static void
                    831: lmc_intr_handler(lmc_softc_t * const sc, int *progress_p)
                    832: {
                    833:     u_int32_t csr;
                    834:
                    835:     while ((csr = LMC_CSR_READ(sc, csr_status)) & sc->lmc_intrmask) {
                    836:
                    837:        *progress_p = 1;
                    838:        LMC_CSR_WRITE(sc, csr_status, csr);
                    839:
                    840:        if (csr & TULIP_STS_SYSERROR) {
                    841:            sc->lmc_last_system_error = (csr & TULIP_STS_ERRORMASK) >> TULIP_STS_ERR_SHIFT;
                    842:            if (sc->lmc_flags & LMC_NOMESSAGES) {
                    843:                sc->lmc_flags |= LMC_SYSTEMERROR;
                    844:            } else {
                    845:                printf(LMC_PRINTF_FMT ": system error: %s\n",
                    846:                       LMC_PRINTF_ARGS,
                    847:                       lmc_system_errors[sc->lmc_last_system_error]);
                    848:            }
                    849:            sc->lmc_flags |= LMC_NEEDRESET;
                    850:            sc->lmc_system_errors++;
                    851:            break;
                    852:        }
                    853:        if (csr & (TULIP_STS_RXINTR | TULIP_STS_RXNOBUF)) {
                    854:            u_int32_t misses = LMC_CSR_READ(sc, csr_missed_frames);
                    855:            if (csr & TULIP_STS_RXNOBUF)
                    856:                sc->lmc_dot3stats.dot3StatsMissedFrames += misses & 0xFFFF;
                    857:            /*
                    858:             * Pass 2.[012] of the 21140A-A[CDE] may hang and/or corrupt data
                    859:             * on receive overflows.
                    860:             */
                    861:           if ((misses & 0x0FFE0000) && (sc->lmc_features & LMC_HAVE_RXBADOVRFLW)) {
                    862:                sc->lmc_dot3stats.dot3StatsInternalMacReceiveErrors++;
                    863:                /*
                    864:                 * Stop the receiver process and spin until it's stopped.
                    865:                 * Tell rx_intr to drop the packets it dequeues.
                    866:                 */
                    867:                LMC_CSR_WRITE(sc, csr_command, sc->lmc_cmdmode & ~TULIP_CMD_RXRUN);
                    868:                while ((LMC_CSR_READ(sc, csr_status) & TULIP_STS_RXSTOPPED) == 0)
                    869:                    ;
                    870:                LMC_CSR_WRITE(sc, csr_status, TULIP_STS_RXSTOPPED);
                    871:                sc->lmc_flags |= LMC_RXIGNORE;
                    872:            }
                    873:            lmc_rx_intr(sc);
                    874:            if (sc->lmc_flags & LMC_RXIGNORE) {
                    875:                /*
                    876:                 * Restart the receiver.
                    877:                 */
                    878:                sc->lmc_flags &= ~LMC_RXIGNORE;
                    879:                LMC_CSR_WRITE(sc, csr_command, sc->lmc_cmdmode);
                    880:            }
                    881:        }
                    882:        if (csr & TULIP_STS_ABNRMLINTR) {
                    883:            u_int32_t tmp = csr & sc->lmc_intrmask
                    884:                & ~(TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR);
                    885:            if (csr & TULIP_STS_TXUNDERFLOW) {
                    886:                if ((sc->lmc_cmdmode & TULIP_CMD_THRESHOLDCTL) != TULIP_CMD_THRSHLD160) {
                    887:                    sc->lmc_cmdmode += TULIP_CMD_THRSHLD96;
                    888:                    sc->lmc_flags |= LMC_NEWTXTHRESH;
                    889:                } else if (sc->lmc_features & LMC_HAVE_STOREFWD) {
                    890:                    sc->lmc_cmdmode |= TULIP_CMD_STOREFWD;
                    891:                    sc->lmc_flags |= LMC_NEWTXTHRESH;
                    892:                }
                    893:            }
                    894:            if (sc->lmc_flags & LMC_NOMESSAGES) {
                    895:                sc->lmc_statusbits |= tmp;
                    896:            } else {
                    897:                lmc_print_abnormal_interrupt(sc, tmp);
                    898:                sc->lmc_flags |= LMC_NOMESSAGES;
                    899:            }
                    900:            LMC_CSR_WRITE(sc, csr_command, sc->lmc_cmdmode);
                    901:        }
                    902:
                    903:        if (csr & TULIP_STS_TXINTR)
                    904:                lmc_tx_intr(sc);
                    905:
                    906:        if (sc->lmc_flags & LMC_WANTTXSTART)
                    907:            lmc_ifstart(&sc->lmc_if);
                    908:     }
                    909: }
                    910:
                    911: lmc_intrfunc_t
                    912: lmc_intr_normal(void *arg)
                    913: {
                    914:        lmc_softc_t * sc = (lmc_softc_t *) arg;
                    915:        int progress = 0;
                    916:
                    917:        lmc_intr_handler(sc, &progress);
                    918:
                    919: #if !defined(LMC_VOID_INTRFUNC)
                    920:        return progress;
                    921: #endif
                    922: }
                    923: 
                    924: static struct mbuf *
                    925: lmc_mbuf_compress(struct mbuf *m)
                    926: {
                    927:        struct mbuf *m0;
                    928: #if MCLBYTES >= LMC_MTU + PPP_HEADER_LEN && !defined(BIG_PACKET)
                    929:        MGETHDR(m0, M_DONTWAIT, MT_DATA);
                    930:        if (m0 != NULL) {
                    931:                if (m->m_pkthdr.len > MHLEN) {
                    932:                        MCLGET(m0, M_DONTWAIT);
                    933:                        if ((m0->m_flags & M_EXT) == 0) {
                    934:                                m_freem(m);
                    935:                                m_freem(m0);
                    936:                                return NULL;
                    937:                        }
                    938:                }
                    939:                m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
                    940:                m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;
                    941:        }
                    942: #else
                    943:        int mlen = MHLEN;
                    944:        int len = m->m_pkthdr.len;
                    945:        struct mbuf **mp = &m0;
                    946:
                    947:        while (len > 0) {
                    948:                if (mlen == MHLEN) {
                    949:                        MGETHDR(*mp, M_DONTWAIT, MT_DATA);
                    950:                } else {
                    951:                        MGET(*mp, M_DONTWAIT, MT_DATA);
                    952:                }
                    953:                if (*mp == NULL) {
                    954:                        m_freem(m0);
                    955:                        m0 = NULL;
                    956:                        break;
                    957:                }
                    958:                if (len > MLEN) {
                    959:                        MCLGET(*mp, M_DONTWAIT);
                    960:                        if (((*mp)->m_flags & M_EXT) == 0) {
                    961:                                m_freem(m0);
                    962:                                m0 = NULL;
                    963:                                break;
                    964:                        }
                    965:                        (*mp)->m_len = (len <= MCLBYTES ? len : MCLBYTES);
                    966:                } else {
                    967:                        (*mp)->m_len = (len <= mlen ? len : mlen);
                    968:                }
                    969:                m_copydata(m, m->m_pkthdr.len - len,
                    970:                           (*mp)->m_len, mtod((*mp), caddr_t));
                    971:                len -= (*mp)->m_len;
                    972:                mp = &(*mp)->m_next;
                    973:                mlen = MLEN;
                    974:        }
                    975: #endif
                    976:        m_freem(m);
                    977:        return m0;
                    978: }
                    979: 
                    980: /*
                    981:  * queue the mbuf handed to us for the interface.  If we cannot
                    982:  * queue it, return the mbuf.  Return NULL if the mbuf was queued.
                    983:  */
                    984: static struct mbuf *
                    985: lmc_txput(lmc_softc_t * const sc, struct mbuf *m)
                    986: {
                    987:        lmc_ringinfo_t * const ri = &sc->lmc_txinfo;
                    988:        lmc_desc_t *eop, *nextout;
                    989:        int segcnt, free;
                    990:        u_int32_t d_status, ctl;
                    991:        bus_dmamap_t map;
                    992:        int error;
                    993:
                    994: #if defined(LMC_DEBUG)
                    995:        if ((sc->lmc_cmdmode & TULIP_CMD_TXRUN) == 0) {
                    996:                printf(LMC_PRINTF_FMT ": txput: tx not running\n",
                    997:                       LMC_PRINTF_ARGS);
                    998:                sc->lmc_flags |= LMC_WANTTXSTART;
                    999:                goto finish;
                   1000:        }
                   1001: #endif
                   1002:
                   1003:        /*
                   1004:         * Now we try to fill in our transmit descriptors.  This is
                   1005:         * a bit reminiscent of going on the Ark two by two
                   1006:         * since each descriptor for the TULIP can describe
                   1007:         * two buffers.  So we advance through packet filling
                   1008:         * each of the two entries at a time to fill each
                   1009:         * descriptor.  Clear the first and last segment bits
                   1010:         * in each descriptor (actually just clear everything
                   1011:         * but the end-of-ring or chain bits) to make sure
                   1012:         * we don't get messed up by previously sent packets.
                   1013:         *
                   1014:         * We may fail to put the entire packet on the ring if
                   1015:         * there is either not enough ring entries free or if the
                   1016:         * packet has more than MAX_TXSEG segments.  In the former
                   1017:         * case we will just wait for the ring to empty.  In the
                   1018:         * latter case we have to recopy.
                   1019:         */
                   1020:        d_status = 0;
                   1021:        eop = nextout = ri->ri_nextout;
                   1022:        segcnt = 0;
                   1023:        free = ri->ri_free;
                   1024:        /*
                   1025:         * Reclaim some DMA maps from if we are out.
                   1026:         */
                   1027:        if (sc->lmc_txmaps_free == 0) {
                   1028: #if defined(LMC_DEBUG)
                   1029:                sc->lmc_dbg.dbg_no_txmaps++;
                   1030: #endif
                   1031:                free += lmc_tx_intr(sc);
                   1032:        }
                   1033:        if (sc->lmc_txmaps_free > 0) {
                   1034:                map = sc->lmc_txmaps[sc->lmc_txmaps_free-1];
                   1035:        } else {
                   1036:                sc->lmc_flags |= LMC_WANTTXSTART;
                   1037: #if defined(LMC_DEBUG)
                   1038:                sc->lmc_dbg.dbg_txput_finishes[1]++;
                   1039: #endif
                   1040:                goto finish;
                   1041:        }
                   1042:        error = bus_dmamap_load_mbuf(sc->lmc_dmatag, map, m, BUS_DMA_NOWAIT);
                   1043:        if (error != 0) {
                   1044:                if (error == EFBIG) {
                   1045:                        /*
                   1046:                         * The packet exceeds the number of transmit buffer
                   1047:                         * entries that we can use for one packet, so we have
                   1048:                         * to recopy it into one mbuf and then try again.
                   1049:                         */
                   1050:                        m = lmc_mbuf_compress(m);
                   1051:                        if (m == NULL) {
                   1052: #if defined(LMC_DEBUG)
                   1053:                                sc->lmc_dbg.dbg_txput_finishes[2]++;
                   1054: #endif
                   1055:                                goto finish;
                   1056:                        }
                   1057:                        error = bus_dmamap_load_mbuf(sc->lmc_dmatag, map, m,
                   1058:                                BUS_DMA_NOWAIT);
                   1059:                }
                   1060:                if (error != 0) {
                   1061:                        printf(LMC_PRINTF_FMT ": unable to load tx map, "
                   1062:                                "error = %d\n", LMC_PRINTF_ARGS, error);
                   1063: #if defined(LMC_DEBUG)
                   1064:                        sc->lmc_dbg.dbg_txput_finishes[3]++;
                   1065: #endif
                   1066:                        goto finish;
                   1067:                }
                   1068:        }
                   1069:        if ((free -= (map->dm_nsegs + 1) / 2) <= 0
                   1070:                /*
                   1071:                 * See if there's any unclaimed space in the transmit ring.
                   1072:                 */
                   1073:                && (free += lmc_tx_intr(sc)) <= 0) {
                   1074:                /*
                   1075:                 * There's no more room but since nothing
                   1076:                 * has been committed at this point, just
                   1077:                 * show output is active, put back the
                   1078:                 * mbuf and return.
                   1079:                 */
                   1080:                sc->lmc_flags |= LMC_WANTTXSTART;
                   1081: #if defined(LMC_DEBUG)
                   1082:                sc->lmc_dbg.dbg_txput_finishes[4]++;
                   1083: #endif
                   1084:                bus_dmamap_unload(sc->lmc_dmatag, map);
                   1085:                goto finish;
                   1086:        }
                   1087:        for (; map->dm_nsegs - segcnt > 1; segcnt += 2) {
                   1088:                int flg;
                   1089:
                   1090:                eop = nextout;
                   1091:                flg            = LMC_CTL_FLGS(letoh32(eop->d_ctl));
                   1092:                flg           &= TULIP_DFLAG_ENDRING;
                   1093:                flg           |= TULIP_DFLAG_TxNOPADDING;
                   1094:                if (sc->ictl.crc_length == 16)
                   1095:                        flg |= TULIP_DFLAG_TxHASCRC;
                   1096:                eop->d_status  = htole32(d_status);
                   1097:                eop->d_addr1   = htole32(map->dm_segs[segcnt].ds_addr);
                   1098:                eop->d_addr2   = htole32(map->dm_segs[segcnt+1].ds_addr);
                   1099:                eop->d_ctl     = htole32(LMC_CTL(flg,
                   1100:                                 map->dm_segs[segcnt].ds_len,
                   1101:                                 map->dm_segs[segcnt+1].ds_len));
                   1102:                d_status = TULIP_DSTS_OWNER;
                   1103:                if (++nextout == ri->ri_last)
                   1104:                        nextout = ri->ri_first;
                   1105:        }
                   1106:        if (segcnt < map->dm_nsegs) {
                   1107:                int flg;
                   1108:
                   1109:                eop = nextout;
                   1110:                flg            = LMC_CTL_FLGS(letoh32(eop->d_ctl));
                   1111:                flg           &= TULIP_DFLAG_ENDRING;
                   1112:                flg           |= TULIP_DFLAG_TxNOPADDING;
                   1113:                if (sc->ictl.crc_length == 16)
                   1114:                        flg |= TULIP_DFLAG_TxHASCRC;
                   1115:                eop->d_status  = htole32(d_status);
                   1116:                eop->d_addr1   = htole32(map->dm_segs[segcnt].ds_addr);
                   1117:                eop->d_addr2   = 0;
                   1118:                eop->d_ctl     = htole32(LMC_CTL(flg,
                   1119:                                 map->dm_segs[segcnt].ds_len, 0));
                   1120:                if (++nextout == ri->ri_last)
                   1121:                        nextout = ri->ri_first;
                   1122:        }
                   1123:        LMC_TXMAP_PRESYNC(sc, map);
                   1124:        LMC_SETCTX(m, map);
                   1125:        map = NULL;
                   1126:        --sc->lmc_txmaps_free;          /* commit to using the dmamap */
                   1127:
                   1128:        /*
                   1129:         * The descriptors have been filled in.  Now get ready
                   1130:         * to transmit.
                   1131:         */
                   1132:        IF_ENQUEUE(&sc->lmc_txq, m);
                   1133:        m = NULL;
                   1134:
                   1135:        /*
                   1136:         * Make sure the next descriptor after this packet is owned
                   1137:         * by us since it may have been set up above if we ran out
                   1138:         * of room in the ring.
                   1139:         */
                   1140:        nextout->d_status = 0;
                   1141:        LMC_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t));
                   1142:
                   1143:        /*
                   1144:         * Mark the last and first segments, indicate we want a transmit
                   1145:         * complete interrupt, and tell it to transmit!
                   1146:         */
                   1147:        ctl = letoh32(eop->d_ctl);
                   1148:        eop->d_ctl = htole32(LMC_CTL(
                   1149:                LMC_CTL_FLGS(ctl)|TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR,
                   1150:                LMC_CTL_LEN1(ctl),
                   1151:                LMC_CTL_LEN2(ctl)));
                   1152:
                   1153:        /*
                   1154:         * Note that ri->ri_nextout is still the start of the packet
                   1155:         * and until we set the OWNER bit, we can still back out of
                   1156:         * everything we have done.
                   1157:         */
                   1158:        ctl = letoh32(ri->ri_nextout->d_ctl);
                   1159:        ri->ri_nextout->d_ctl = htole32(LMC_CTL(
                   1160:                LMC_CTL_FLGS(ctl)|TULIP_DFLAG_TxFIRSTSEG,
                   1161:                LMC_CTL_LEN1(ctl),
                   1162:                LMC_CTL_LEN2(ctl)));
                   1163:        if (eop < ri->ri_nextout) {
                   1164:                LMC_TXDESC_PRESYNC(sc, ri->ri_nextout,
                   1165:                        (caddr_t) ri->ri_last - (caddr_t) ri->ri_nextout);
                   1166:                LMC_TXDESC_PRESYNC(sc, ri->ri_first,
                   1167:                        (caddr_t) (eop + 1) - (caddr_t) ri->ri_first);
                   1168:        } else {
                   1169:                LMC_TXDESC_PRESYNC(sc, ri->ri_nextout,
                   1170:                        (caddr_t) (eop + 1) - (caddr_t) ri->ri_nextout);
                   1171:        }
                   1172:        ri->ri_nextout->d_status = htole32(TULIP_DSTS_OWNER);
                   1173:        LMC_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t));
                   1174:
                   1175:        LMC_CSR_WRITE(sc, csr_txpoll, 1);
                   1176:
                   1177:        /*
                   1178:         * This advances the ring for us.
                   1179:         */
                   1180:        ri->ri_nextout = nextout;
                   1181:        ri->ri_free = free;
                   1182:
                   1183:        /*
                   1184:         * switch back to the single queueing ifstart.
                   1185:         */
                   1186:        sc->lmc_flags &= ~LMC_WANTTXSTART;
                   1187:        sc->lmc_if.if_start = lmc_ifstart_one;
                   1188:
                   1189:        /*
                   1190:         * If we want a txstart, there must be not enough space in the
                   1191:         * transmit ring.  So we want to enable transmit done interrupts
                   1192:         * so we can immediately reclaim some space.  When the transmit
                   1193:         * interrupt is posted, the interrupt handler will call tx_intr
                   1194:         * to reclaim space and then txstart (since WANTTXSTART is set).
                   1195:         * txstart will move the packet into the transmit ring and clear
                   1196:         * WANTTXSTART thereby causing TXINTR to be cleared.
                   1197:         */
                   1198:  finish:
                   1199:        if (sc->lmc_flags & LMC_WANTTXSTART) {
                   1200:                sc->lmc_if.if_flags |= IFF_OACTIVE;
                   1201:                sc->lmc_if.if_start = lmc_ifstart;
                   1202:        }
                   1203:
                   1204:        return m;
                   1205: }
                   1206: 
                   1207:
                   1208: /*
                   1209:  * This routine is entered at splnet()
                   1210:  */
                   1211: static int
                   1212: lmc_ifioctl(struct ifnet * ifp, ioctl_cmd_t cmd, caddr_t data)
                   1213: {
                   1214:        lmc_softc_t * const sc = LMC_IFP_TO_SOFTC(ifp);
                   1215:        int s;
                   1216:        struct proc *p = curproc;
                   1217:        int error = 0;
                   1218:        struct ifreq *ifr = (struct ifreq *)data;
                   1219:        u_int32_t new_state;
                   1220:        u_int32_t old_state;
                   1221:        lmc_ctl_t ctl;
                   1222:
                   1223:        s = LMC_RAISESPL();
                   1224:
                   1225:        switch (cmd) {
                   1226:        case LMCIOCGINFO:
                   1227:                error = copyout(&sc->ictl, ifr->ifr_data, sizeof(lmc_ctl_t));
                   1228:
                   1229:                goto out;
                   1230:                break;
                   1231:
                   1232:        case LMCIOCSINFO:
                   1233:                error = suser(p, 0);
                   1234:                if (error)
                   1235:                        goto out;
                   1236:
                   1237:                error = copyin(ifr->ifr_data, &ctl, sizeof(lmc_ctl_t));
                   1238:                if (error != 0)
                   1239:                        goto out;
                   1240:
                   1241:                sc->lmc_media->set_status(sc, &ctl);
                   1242:
                   1243:                goto out;
                   1244:                break;
                   1245:
                   1246:        case SIOCSIFMTU:
                   1247:                /*
                   1248:                 * Don't allow the MTU to get larger than we can handle
                   1249:                 */
                   1250:                if (ifr->ifr_mtu > LMC_MTU) {
                   1251:                        error = EINVAL;
                   1252:                        goto out;
                   1253:                } else {
                   1254:                         ifp->if_mtu = ifr->ifr_mtu;
                   1255:                }
                   1256:                break;
                   1257:        }
                   1258:
                   1259:        /*
                   1260:         * call the sppp ioctl layer
                   1261:         */
                   1262:        error = sppp_ioctl(ifp, cmd, data);
                   1263:        if (error != 0)
                   1264:                goto out;
                   1265:
                   1266:        /*
                   1267:         * If we are transitioning from up to down or down to up, call
                   1268:         * our init routine.
                   1269:         */
                   1270:        new_state = ifp->if_flags & IFF_UP;
                   1271:        old_state = sc->lmc_flags & LMC_IFUP;
                   1272:
                   1273:        if (new_state && !old_state)
                   1274:                lmc_ifup(sc);
                   1275:        else if (!new_state && old_state)
                   1276:                lmc_ifdown(sc);
                   1277:
                   1278:  out:
                   1279:        LMC_RESTORESPL(s);
                   1280:
                   1281:        return error;
                   1282: }
                   1283:
                   1284: /*
                   1285:  * These routines gets called at device spl (from sppp_output).
                   1286:  */
                   1287:
                   1288: static ifnet_ret_t
                   1289: lmc_ifstart(struct ifnet * const ifp)
                   1290: {
                   1291:        lmc_softc_t * const sc = LMC_IFP_TO_SOFTC(ifp);
                   1292:        struct mbuf *m, *m0;
                   1293:
                   1294:        if (sc->lmc_flags & LMC_IFUP) {
                   1295:                while (sppp_isempty(ifp) == 0) {
                   1296:                        m = sppp_pick(ifp);
                   1297:                        if (m == NULL)
                   1298:                                break;
                   1299:                        if ((m = lmc_txput(sc, m)) != NULL)
                   1300:                                break;
                   1301:                        m0 = sppp_dequeue(ifp);
                   1302: #if defined(LMC_DEBUG)
                   1303:                        if (m0 != m)
                   1304:                                printf("lmc_ifstart: mbuf mismatch!\n");
                   1305: #endif
                   1306:                }
                   1307:                LMC_CSR_WRITE(sc, csr_txpoll, 1);
                   1308:        }
                   1309: }
                   1310:
                   1311: static ifnet_ret_t
                   1312: lmc_ifstart_one(struct ifnet * const ifp)
                   1313: {
                   1314:        lmc_softc_t * const sc = LMC_IFP_TO_SOFTC(ifp);
                   1315:        struct mbuf *m, *m0;
                   1316:
                   1317:        if ((sc->lmc_flags & LMC_IFUP) && (sppp_isempty(ifp) == 0)) {
                   1318:                m = sppp_pick(ifp);
                   1319:                if ((m = lmc_txput(sc, m)) != NULL)
                   1320:                        return;
                   1321:                m0 = sppp_dequeue(ifp);
                   1322: #if defined(LMC_DEBUG)
                   1323:                if (m0 != m)
                   1324:                        printf("lmc_ifstart: mbuf mismatch!\n");
                   1325: #endif
                   1326:                LMC_CSR_WRITE(sc, csr_txpoll, 1);
                   1327:        }
                   1328: }
                   1329:
                   1330: /*
                   1331:  * Set up the OS interface magic and attach to the operating system
                   1332:  * network services.
                   1333:  */
                   1334: void
                   1335: lmc_attach(lmc_softc_t * const sc)
                   1336: {
                   1337:        struct ifnet * const ifp = &sc->lmc_if;
                   1338:
                   1339:        ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
                   1340:        ifp->if_ioctl = lmc_ifioctl;
                   1341:        ifp->if_start = lmc_ifstart;
                   1342:        ifp->if_watchdog = lmc_watchdog;
                   1343:        ifp->if_timer = 1;
                   1344:        ifp->if_mtu = LMC_MTU;
                   1345:        IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
                   1346:        IFQ_SET_READY(&ifp->if_snd);
                   1347:
                   1348:        if_attach(ifp);
                   1349:        if_alloc_sadl(ifp);
                   1350:
                   1351:        sppp_attach((struct ifnet *)&sc->lmc_sppp);
                   1352:        sc->lmc_sppp.pp_flags = PP_CISCO | PP_KEEPALIVE;
                   1353:        sc->lmc_sppp.pp_framebytes = 3;
                   1354:
                   1355: #if NBPFILTER > 0
                   1356:        LMC_BPF_ATTACH(sc);
                   1357: #endif
                   1358:
                   1359:        /*
                   1360:         * turn off those LEDs...
                   1361:         */
                   1362:        sc->lmc_miireg16 |= LMC_MII16_LED_ALL;
                   1363:        /*
                   1364:         * for DS3 & DS1 adapters light the green light, led2
                   1365:         */
                   1366:        if (sc->lmc_cardtype == LMC_CARDTYPE_DS3 ||
                   1367:            sc->lmc_cardtype == LMC_CARDTYPE_T1)
                   1368:                lmc_led_on (sc, LMC_MII16_LED2);
                   1369:        else
                   1370:                lmc_led_on (sc, LMC_MII16_LED0 | LMC_MII16_LED2);
                   1371: }
                   1372:
                   1373: void
                   1374: lmc_initring(lmc_softc_t * const sc, lmc_ringinfo_t * const ri,
                   1375:               lmc_desc_t *descs, int ndescs)
                   1376: {
                   1377:        ri->ri_max = ndescs;
                   1378:        ri->ri_first = descs;
                   1379:        ri->ri_last = ri->ri_first + ri->ri_max;
                   1380:        bzero((caddr_t) ri->ri_first, sizeof(ri->ri_first[0]) * ri->ri_max);
                   1381:        ri->ri_last[-1].d_ctl = htole32(LMC_CTL(TULIP_DFLAG_ENDRING, 0, 0));
                   1382: }

CVSweb