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

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

1.1       nbrk        1: /*     $OpenBSD: dp8390.c,v 1.39 2007/05/07 18:53:04 deraadt Exp $     */
                      2: /*     $NetBSD: dp8390.c,v 1.13 1998/07/05 06:49:11 jonathan Exp $     */
                      3:
                      4: /*
                      5:  * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
                      6:  * adapters.
                      7:  *
                      8:  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
                      9:  *
                     10:  * Copyright (C) 1993, David Greenman.  This software may be used, modified,
                     11:  * copied, distributed, and sold, in both source and binary form provided that
                     12:  * the above copyright and these terms are retained.  Under no circumstances is
                     13:  * the author responsible for the proper functioning of this software, nor does
                     14:  * the author assume any responsibility for damages incurred with its use.
                     15:  */
                     16:
                     17: #include "bpfilter.h"
                     18:
                     19: #include <sys/param.h>
                     20: #include <sys/systm.h>
                     21: #include <sys/device.h>
                     22: #include <sys/errno.h>
                     23: #include <sys/ioctl.h>
                     24: #include <sys/mbuf.h>
                     25: #include <sys/socket.h>
                     26: #include <sys/syslog.h>
                     27:
                     28: #include <net/if.h>
                     29: #include <net/if_dl.h>
                     30: #include <net/if_types.h>
                     31: #include <net/if_media.h>
                     32:
                     33: #ifdef INET
                     34: #include <netinet/in.h>
                     35: #include <netinet/in_systm.h>
                     36: #include <netinet/in_var.h>
                     37: #include <netinet/ip.h>
                     38: #include <netinet/if_ether.h>
                     39: #endif
                     40:
                     41: #if NBPFILTER > 0
                     42: #include <net/bpf.h>
                     43: #endif
                     44:
                     45: #include <machine/bus.h>
                     46:
                     47: #include <dev/ic/dp8390reg.h>
                     48: #include <dev/ic/dp8390var.h>
                     49:
                     50: #ifdef DEBUG
                     51: #define __inline__     /* XXX for debugging porpoises */
                     52: #endif
                     53:
                     54: static __inline__ void dp8390_xmit(struct dp8390_softc *);
                     55:
                     56: static __inline__ void dp8390_read_hdr(struct dp8390_softc *,
                     57:                            int, struct dp8390_ring *);
                     58: static __inline__ int  dp8390_ring_copy(struct dp8390_softc *,
                     59:                            int, caddr_t, u_short);
                     60: static __inline__ int  dp8390_write_mbuf(struct dp8390_softc *,
                     61:                            struct mbuf *, int);
                     62:
                     63: static int             dp8390_test_mem(struct dp8390_softc *);
                     64:
                     65: int    dp8390_enable(struct dp8390_softc *);
                     66: void   dp8390_disable(struct dp8390_softc *);
                     67:
                     68: #ifdef DEBUG
                     69: int    dp8390_debug = 0;
                     70: #endif
                     71:
                     72: /*
                     73:  * Standard media init routine for the dp8390.
                     74:  */
                     75: void
                     76: dp8390_media_init(struct dp8390_softc *sc)
                     77: {
                     78:        ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus);
                     79:        ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
                     80:        ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
                     81: }
                     82:
                     83: /*
                     84:  * Do bus-independent setup.
                     85:  */
                     86: int
                     87: dp8390_config(struct dp8390_softc *sc)
                     88: {
                     89:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                     90:        int rv;
                     91:
                     92:        rv = 1;
                     93:
                     94:        if (!sc->test_mem)
                     95:                sc->test_mem = dp8390_test_mem;
                     96:
                     97:        /* Allocate one xmit buffer if < 16k, two buffers otherwise. */
                     98:        if ((sc->mem_size < 16384) ||
                     99:            (sc->sc_flags & DP8390_NO_MULTI_BUFFERING))
                    100:                sc->txb_cnt = 1;
                    101:        else if (sc->mem_size < 8192 * 3)
                    102:                sc->txb_cnt = 2;
                    103:        else
                    104:                sc->txb_cnt = 3;
                    105:
                    106:        sc->tx_page_start = sc->mem_start >> ED_PAGE_SHIFT;
                    107:        sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
                    108:        sc->rec_page_stop = sc->tx_page_start + (sc->mem_size >> ED_PAGE_SHIFT);
                    109:        sc->mem_ring = sc->mem_start + (sc->rec_page_start << ED_PAGE_SHIFT);
                    110:        sc->mem_end = sc->mem_start + sc->mem_size;
                    111:
                    112:        /* Now zero memory and verify that it is clear. */
                    113:        if ((*sc->test_mem)(sc))
                    114:                goto out;
                    115:
                    116:        /* Set interface to stopped condition (reset). */
                    117:        dp8390_stop(sc);
                    118:
                    119:        /* Initialize ifnet structure. */
                    120:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    121:        ifp->if_softc = sc;
                    122:        ifp->if_start = dp8390_start;
                    123:        ifp->if_ioctl = dp8390_ioctl;
                    124:        if (!ifp->if_watchdog)
                    125:                ifp->if_watchdog = dp8390_watchdog;
                    126:        ifp->if_flags =
                    127:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
                    128:        IFQ_SET_READY(&ifp->if_snd);
                    129:
                    130:        ifp->if_capabilities = IFCAP_VLAN_MTU;
                    131:
                    132:        /* Print additional info when attached. */
                    133:        printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
                    134:
                    135:        /* Initialize media goo. */
                    136:        (*sc->sc_media_init)(sc);
                    137:
                    138:        /* Attach the interface. */
                    139:        if_attach(ifp);
                    140:        ether_ifattach(ifp);
                    141:
                    142:        rv = 0;
                    143: out:
                    144:        return (rv);
                    145: }
                    146:
                    147: /*
                    148:  * Media change callback.
                    149:  */
                    150: int
                    151: dp8390_mediachange(struct ifnet *ifp)
                    152: {
                    153:        struct dp8390_softc *sc = ifp->if_softc;
                    154:
                    155:        if (sc->sc_mediachange)
                    156:                return ((*sc->sc_mediachange)(sc));
                    157:
                    158:        return (0);
                    159: }
                    160:
                    161: /*
                    162:  * Media status callback.
                    163:  */
                    164: void
                    165: dp8390_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
                    166: {
                    167:        struct dp8390_softc *sc = ifp->if_softc;
                    168:
                    169:        if (sc->sc_enabled == 0) {
                    170:                ifmr->ifm_active = IFM_ETHER | IFM_NONE;
                    171:                ifmr->ifm_status = 0;
                    172:                return;
                    173:        }
                    174:
                    175:        if (sc->sc_mediastatus)
                    176:                (*sc->sc_mediastatus)(sc, ifmr);
                    177: }
                    178:
                    179: /*
                    180:  * Reset interface.
                    181:  */
                    182: void
                    183: dp8390_reset(struct dp8390_softc *sc)
                    184: {
                    185:        int     s;
                    186:
                    187:        s = splnet();
                    188:        dp8390_stop(sc);
                    189:        dp8390_init(sc);
                    190:        splx(s);
                    191: }
                    192:
                    193: /*
                    194:  * Take interface offline.
                    195:  */
                    196: void
                    197: dp8390_stop(struct dp8390_softc *sc)
                    198: {
                    199:        bus_space_tag_t regt = sc->sc_regt;
                    200:        bus_space_handle_t regh = sc->sc_regh;
                    201:        int n = 5000;
                    202:
                    203:        /* Stop everything on the interface, and select page 0 registers. */
                    204:        NIC_BARRIER(regt, regh);
                    205:        NIC_PUT(regt, regh, ED_P0_CR,
                    206:            sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
                    207:        NIC_BARRIER(regt, regh);
                    208:
                    209:        /*
                    210:         * Wait for interface to enter stopped state, but limit # of checks to
                    211:         * 'n' (about 5ms).  It shouldn't even take 5us on modern DS8390's, but
                    212:         * just in case it's an old one.
                    213:         */
                    214:        while (((NIC_GET(regt, regh,
                    215:            ED_P0_ISR) & ED_ISR_RST) == 0) && --n)
                    216:                DELAY(1);
                    217:
                    218:        if (sc->stop_card != NULL)
                    219:                (*sc->stop_card)(sc);
                    220: }
                    221:
                    222: /*
                    223:  * Device timeout/watchdog routine.  Entered if the device neglects to generate
                    224:  * an interrupt after a transmit has been started on it.
                    225:  */
                    226:
                    227: void
                    228: dp8390_watchdog(struct ifnet *ifp)
                    229: {
                    230:        struct dp8390_softc *sc = ifp->if_softc;
                    231:
                    232:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
                    233:        ++sc->sc_arpcom.ac_if.if_oerrors;
                    234:
                    235:        dp8390_reset(sc);
                    236: }
                    237:
                    238: /*
                    239:  * Initialize device.
                    240:  */
                    241: void
                    242: dp8390_init(struct dp8390_softc *sc)
                    243: {
                    244:        bus_space_tag_t regt = sc->sc_regt;
                    245:        bus_space_handle_t regh = sc->sc_regh;
                    246:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    247:        u_int8_t mcaf[8];
                    248:        int i;
                    249:
                    250:        /*
                    251:         * Initialize the NIC in the exact order outlined in the NS manual.
                    252:         * This init procedure is "mandatory"...don't change what or when
                    253:         * things happen.
                    254:         */
                    255:
                    256:        /* Reset transmitter flags. */
                    257:        ifp->if_timer = 0;
                    258:
                    259:        sc->txb_inuse = 0;
                    260:        sc->txb_new = 0;
                    261:        sc->txb_next_tx = 0;
                    262:
                    263:        /* Set interface for page 0, remote DMA complete, stopped. */
                    264:        NIC_BARRIER(regt, regh);
                    265:        NIC_PUT(regt, regh, ED_P0_CR,
                    266:            sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
                    267:        NIC_BARRIER(regt, regh);
                    268:
                    269:        if (sc->dcr_reg & ED_DCR_LS) {
                    270:                NIC_PUT(regt, regh, ED_P0_DCR, sc->dcr_reg);
                    271:        } else {
                    272:                /*
                    273:                 * Set FIFO threshold to 8, No auto-init Remote DMA, byte
                    274:                 * order=80x86, byte-wide DMA xfers,
                    275:                 */
                    276:                NIC_PUT(regt, regh, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
                    277:        }
                    278:
                    279:        /* Clear remote byte count registers. */
                    280:        NIC_PUT(regt, regh, ED_P0_RBCR0, 0);
                    281:        NIC_PUT(regt, regh, ED_P0_RBCR1, 0);
                    282:
                    283:        /* Tell RCR to do nothing for now. */
                    284:        NIC_PUT(regt, regh, ED_P0_RCR, ED_RCR_MON | sc->rcr_proto);
                    285:
                    286:        /* Place NIC in internal loopback mode. */
                    287:        NIC_PUT(regt, regh, ED_P0_TCR, ED_TCR_LB0);
                    288:
                    289:        /* Set lower bits of byte addressable framing to 0. */
                    290:        if (sc->is790)
                    291:                NIC_PUT(regt, regh, 0x09, 0);
                    292:
                    293:        /* Initialize receive buffer ring. */
                    294:        NIC_PUT(regt, regh, ED_P0_BNRY, sc->rec_page_start);
                    295:        NIC_PUT(regt, regh, ED_P0_PSTART, sc->rec_page_start);
                    296:        NIC_PUT(regt, regh, ED_P0_PSTOP, sc->rec_page_stop);
                    297:
                    298:        /*
                    299:         * Enable the following interrupts: receive/transmit complete,
                    300:         * receive/transmit error, and Receiver OverWrite.
                    301:         *
                    302:         * Counter overflow and Remote DMA complete are *not* enabled.
                    303:         */
                    304:        NIC_PUT(regt, regh, ED_P0_IMR,
                    305:            ED_IMR_PRXE | ED_IMR_PTXE | ED_IMR_RXEE | ED_IMR_TXEE |
                    306:            ED_IMR_OVWE);
                    307:
                    308:        /*
                    309:         * Clear all interrupts.  A '1' in each bit position clears the
                    310:         * corresponding flag.
                    311:         */
                    312:        NIC_PUT(regt, regh, ED_P0_ISR, 0xff);
                    313:
                    314:        /* Program command register for page 1. */
                    315:        NIC_BARRIER(regt, regh);
                    316:        NIC_PUT(regt, regh, ED_P0_CR,
                    317:            sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STP);
                    318:        NIC_BARRIER(regt, regh);
                    319:
                    320:        /* Copy out our station address. */
                    321:        for (i = 0; i < ETHER_ADDR_LEN; ++i)
                    322:                NIC_PUT(regt, regh, ED_P1_PAR0 + i,
                    323:                    sc->sc_arpcom.ac_enaddr[i]);
                    324:
                    325:        /* Set multicast filter on chip. */
                    326:        dp8390_getmcaf(&sc->sc_arpcom, mcaf);
                    327:        for (i = 0; i < 8; i++)
                    328:                NIC_PUT(regt, regh, ED_P1_MAR0 + i, mcaf[i]);
                    329:
                    330:        /*
                    331:         * Set current page pointer to one page after the boundary pointer, as
                    332:         * recommended in the National manual.
                    333:         */
                    334:        sc->next_packet = sc->rec_page_start + 1;
                    335:        NIC_PUT(regt, regh, ED_P1_CURR, sc->next_packet);
                    336:
                    337:        /* Program command register for page 0. */
                    338:        NIC_BARRIER(regt, regh);
                    339:        NIC_PUT(regt, regh, ED_P1_CR,
                    340:            sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
                    341:        NIC_BARRIER(regt, regh);
                    342:
                    343:        /* Accept broadcast and multicast packets by default. */
                    344:        i = ED_RCR_AB | ED_RCR_AM | sc->rcr_proto;
                    345:        if (ifp->if_flags & IFF_PROMISC) {
                    346:                /*
                    347:                 * Set promiscuous mode.  Multicast filter was set earlier so
                    348:                 * that we should receive all multicast packets.
                    349:                 */
                    350:                i |= ED_RCR_PRO | ED_RCR_AR | ED_RCR_SEP;
                    351:        }
                    352:        NIC_PUT(regt, regh, ED_P0_RCR, i);
                    353:
                    354:        /* Take interface out of loopback. */
                    355:        NIC_PUT(regt, regh, ED_P0_TCR, 0);
                    356:
                    357:        /* Do any card-specific initialization, if applicable. */
                    358:        if (sc->init_card)
                    359:                (*sc->init_card)(sc);
                    360:
                    361:        /* Fire up the interface. */
                    362:        NIC_BARRIER(regt, regh);
                    363:        NIC_PUT(regt, regh, ED_P0_CR,
                    364:            sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
                    365:
                    366:        /* Set 'running' flag, and clear output active flag. */
                    367:        ifp->if_flags |= IFF_RUNNING;
                    368:        ifp->if_flags &= ~IFF_OACTIVE;
                    369:
                    370:        /* ...and attempt to start output. */
                    371:        dp8390_start(ifp);
                    372: }
                    373:
                    374: /*
                    375:  * This routine actually starts the transmission on the interface.
                    376:  */
                    377: static __inline__ void
                    378: dp8390_xmit(struct dp8390_softc *sc)
                    379: {
                    380:        bus_space_tag_t regt = sc->sc_regt;
                    381:        bus_space_handle_t regh = sc->sc_regh;
                    382:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    383:        u_short len;
                    384:
                    385: #ifdef DIAGNOSTIC
                    386:        if ((sc->txb_next_tx + sc->txb_inuse) % sc->txb_cnt != sc->txb_new)
                    387:                panic("dp8390_xmit: desync, next_tx=%d inuse=%d cnt=%d new=%d",
                    388:                    sc->txb_next_tx, sc->txb_inuse, sc->txb_cnt, sc->txb_new);
                    389:
                    390:        if (sc->txb_inuse == 0)
                    391:                panic("dp8390_xmit: no packets to xmit");
                    392: #endif
                    393:
                    394:        len = sc->txb_len[sc->txb_next_tx];
                    395:
                    396:        /* Set NIC for page 0 register access. */
                    397:        NIC_BARRIER(regt, regh);
                    398:        NIC_PUT(regt, regh, ED_P0_CR,
                    399:            sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
                    400:        NIC_BARRIER(regt, regh);
                    401:
                    402:        /* Set TX buffer start page. */
                    403:        NIC_PUT(regt, regh, ED_P0_TPSR, sc->tx_page_start +
                    404:            sc->txb_next_tx * ED_TXBUF_SIZE);
                    405:
                    406:        /* Set TX length. */
                    407:        NIC_PUT(regt, regh, ED_P0_TBCR0, len);
                    408:        NIC_PUT(regt, regh, ED_P0_TBCR1, len >> 8);
                    409:
                    410:        /* Set page 0, remote DMA complete, transmit packet, and *start*. */
                    411:        NIC_BARRIER(regt, regh);
                    412:        NIC_PUT(regt, regh, ED_P0_CR,
                    413:            sc->cr_proto | ED_CR_PAGE_0 | ED_CR_TXP | ED_CR_STA);
                    414:
                    415:        /* Point to next transmit buffer slot and wrap if necessary. */
                    416:        if (++sc->txb_next_tx == sc->txb_cnt)
                    417:                sc->txb_next_tx = 0;
                    418:
                    419:        /* Set a timer just in case we never hear from the board again. */
                    420:        ifp->if_timer = 2;
                    421: }
                    422:
                    423: /*
                    424:  * Start output on interface.
                    425:  * We make two assumptions here:
                    426:  *  1) that the current priority is set to splnet _before_ this code
                    427:  *     is called *and* is returned to the appropriate priority after
                    428:  *     return
                    429:  *  2) that the IFF_OACTIVE flag is checked before this code is called
                    430:  *     (i.e. that the output part of the interface is idle)
                    431:  */
                    432: void
                    433: dp8390_start(struct ifnet *ifp)
                    434: {
                    435:        struct dp8390_softc *sc = ifp->if_softc;
                    436:        struct mbuf *m0;
                    437:        int buffer;
                    438:        int len;
                    439:
                    440:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                    441:                return;
                    442:
                    443: outloop:
                    444:        /* See if there is room to put another packet in the buffer. */
                    445:        if (sc->txb_inuse == sc->txb_cnt) {
                    446:                /* No room.  Indicate this to the outside world and exit. */
                    447:                ifp->if_flags |= IFF_OACTIVE;
                    448:                return;
                    449:        }
                    450:        IFQ_DEQUEUE(&ifp->if_snd, m0);
                    451:        if (m0 == 0)
                    452:                return;
                    453:
                    454:        /* We need to use m->m_pkthdr.len, so require the header */
                    455:        if ((m0->m_flags & M_PKTHDR) == 0)
                    456:                panic("dp8390_start: no header mbuf");
                    457:
                    458: #if NBPFILTER > 0
                    459:        /* Tap off here if there is a BPF listener. */
                    460:        if (ifp->if_bpf)
                    461:                bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
                    462: #endif
                    463:
                    464:        /* txb_new points to next open buffer slot. */
                    465:        buffer = sc->mem_start +
                    466:            ((sc->txb_new * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
                    467:
                    468:        if (sc->write_mbuf)
                    469:                len = (*sc->write_mbuf)(sc, m0, buffer);
                    470:        else
                    471:                len = dp8390_write_mbuf(sc, m0, buffer);
                    472:
                    473:        m_freem(m0);
                    474:        sc->txb_len[sc->txb_new] = max(len, ETHER_MIN_LEN - ETHER_CRC_LEN);
                    475:
                    476:        /* Point to next buffer slot and wrap if necessary. */
                    477:        if (++sc->txb_new == sc->txb_cnt)
                    478:                sc->txb_new = 0;
                    479:
                    480:        /* Start the first packet transmitting. */
                    481:        if (sc->txb_inuse++ == 0)
                    482:                dp8390_xmit(sc);
                    483:
                    484:        /* Loop back to the top to possibly buffer more packets. */
                    485:        goto outloop;
                    486: }
                    487:
                    488: /*
                    489:  * Ethernet interface receiver interrupt.
                    490:  */
                    491: void
                    492: dp8390_rint(struct dp8390_softc *sc)
                    493: {
                    494:        bus_space_tag_t regt = sc->sc_regt;
                    495:        bus_space_handle_t regh = sc->sc_regh;
                    496:        struct dp8390_ring packet_hdr;
                    497:        int packet_ptr;
                    498:        u_short len;
                    499:        u_char boundary, current;
                    500:        u_char nlen;
                    501:
                    502: loop:
                    503:        /* Set NIC to page 1 registers to get 'current' pointer. */
                    504:        NIC_BARRIER(regt, regh);
                    505:        NIC_PUT(regt, regh, ED_P0_CR,
                    506:            sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STA);
                    507:        NIC_BARRIER(regt, regh);
                    508:
                    509:        /*
                    510:         * 'sc->next_packet' is the logical beginning of the ring-buffer - i.e.
                    511:         * it points to where new data has been buffered.  The 'CURR' (current)
                    512:         * register points to the logical end of the ring-buffer - i.e. it
                    513:         * points to where additional new data will be added.  We loop here
                    514:         * until the logical beginning equals the logical end (or in other
                    515:         * words, until the ring-buffer is empty).
                    516:         */
                    517:        current = NIC_GET(regt, regh, ED_P1_CURR);
                    518:        if (sc->next_packet == current)
                    519:                return;
                    520:
                    521:        /* Set NIC to page 0 registers to update boundary register. */
                    522:        NIC_BARRIER(regt, regh);
                    523:        NIC_PUT(regt, regh, ED_P1_CR,
                    524:            sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
                    525:        NIC_BARRIER(regt, regh);
                    526:
                    527:        do {
                    528:                /* Get pointer to this buffer's header structure. */
                    529:                packet_ptr = sc->mem_ring +
                    530:                    ((sc->next_packet - sc->rec_page_start) << ED_PAGE_SHIFT);
                    531:
                    532:                if (sc->read_hdr)
                    533:                        (*sc->read_hdr)(sc, packet_ptr, &packet_hdr);
                    534:                else
                    535:                        dp8390_read_hdr(sc, packet_ptr, &packet_hdr);
                    536:                len = packet_hdr.count;
                    537:
                    538:                /*
                    539:                 * Try do deal with old, buggy chips that sometimes duplicate
                    540:                 * the low byte of the length into the high byte.  We do this
                    541:                 * by simply ignoring the high byte of the length and always
                    542:                 * recalculating it.
                    543:                 *
                    544:                 * NOTE: sc->next_packet is pointing at the current packet.
                    545:                 */
                    546:                if (packet_hdr.next_packet >= sc->next_packet)
                    547:                        nlen = (packet_hdr.next_packet - sc->next_packet);
                    548:                else
                    549:                        nlen = ((packet_hdr.next_packet - sc->rec_page_start) +
                    550:                            (sc->rec_page_stop - sc->next_packet));
                    551:                --nlen;
                    552:                if ((len & ED_PAGE_MASK) + sizeof(packet_hdr) > ED_PAGE_SIZE)
                    553:                        --nlen;
                    554:                len = (len & ED_PAGE_MASK) | (nlen << ED_PAGE_SHIFT);
                    555: #ifdef DIAGNOSTIC
                    556:                if (len != packet_hdr.count) {
                    557:                        printf("%s: length does not match "
                    558:                            "next packet pointer\n", sc->sc_dev.dv_xname);
                    559:                        printf("%s: len %04x nlen %04x start %02x "
                    560:                            "first %02x curr %02x next %02x stop %02x\n",
                    561:                            sc->sc_dev.dv_xname, packet_hdr.count, len,
                    562:                            sc->rec_page_start, sc->next_packet, current,
                    563:                            packet_hdr.next_packet, sc->rec_page_stop);
                    564:                }
                    565: #endif
                    566:
                    567:                /*
                    568:                 * Be fairly liberal about what we allow as a "reasonable"
                    569:                 * length so that a [crufty] packet will make it to BPF (and
                    570:                 * can thus be analyzed).  Note that all that is really
                    571:                 * important is that we have a length that will fit into one
                    572:                 * mbuf cluster or less; the upper layer protocols can then
                    573:                 * figure out the length from their own length field(s).
                    574:                 */
                    575:                if (len <= MCLBYTES &&
                    576:                    packet_hdr.next_packet >= sc->rec_page_start &&
                    577:                    packet_hdr.next_packet < sc->rec_page_stop) {
                    578:                        /* Go get packet. */
                    579:                        dp8390_read(sc,
                    580:                            packet_ptr + sizeof(struct dp8390_ring),
                    581:                            len - sizeof(struct dp8390_ring));
                    582:                } else {
                    583:                        /* Really BAD.  The ring pointers are corrupted. */
                    584:                        log(LOG_ERR, "%s: NIC memory corrupt - "
                    585:                            "invalid packet length %d\n",
                    586:                            sc->sc_dev.dv_xname, len);
                    587:                        ++sc->sc_arpcom.ac_if.if_ierrors;
                    588:                        dp8390_reset(sc);
                    589:                        return;
                    590:                }
                    591:
                    592:                /* Update next packet pointer. */
                    593:                sc->next_packet = packet_hdr.next_packet;
                    594:
                    595:                /*
                    596:                 * Update NIC boundary pointer - being careful to keep it one
                    597:                 * buffer behind (as recommended by NS databook).
                    598:                 */
                    599:                boundary = sc->next_packet - 1;
                    600:                if (boundary < sc->rec_page_start)
                    601:                        boundary = sc->rec_page_stop - 1;
                    602:                NIC_PUT(regt, regh, ED_P0_BNRY, boundary);
                    603:        } while (sc->next_packet != current);
                    604:
                    605:        goto loop;
                    606: }
                    607:
                    608: /* Ethernet interface interrupt processor. */
                    609: int
                    610: dp8390_intr(void *arg)
                    611: {
                    612:        struct dp8390_softc *sc = (struct dp8390_softc *)arg;
                    613:        bus_space_tag_t regt = sc->sc_regt;
                    614:        bus_space_handle_t regh = sc->sc_regh;
                    615:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    616:        u_char isr;
                    617:
                    618:        if (sc->sc_enabled == 0)
                    619:                return (0);
                    620:
                    621:        /* Set NIC to page 0 registers. */
                    622:        NIC_BARRIER(regt, regh);
                    623:        NIC_PUT(regt, regh, ED_P0_CR,
                    624:            sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
                    625:        NIC_BARRIER(regt, regh);
                    626:
                    627:        isr = NIC_GET(regt, regh, ED_P0_ISR);
                    628:        if (!isr)
                    629:                return (0);
                    630:
                    631:        /* Loop until there are no more new interrupts. */
                    632:        for (;;) {
                    633:                /*
                    634:                 * Reset all the bits that we are 'acknowledging' by writing a
                    635:                 * '1' to each bit position that was set.
                    636:                 * (Writing a '1' *clears* the bit.)
                    637:                 */
                    638:                NIC_PUT(regt, regh, ED_P0_ISR, isr);
                    639:
                    640:                /* Work around for AX88190 bug */
                    641:                if ((sc->sc_flags & DP8390_DO_AX88190_WORKAROUND) != 0)
                    642:                        while ((NIC_GET(regt, regh, ED_P0_ISR) & isr) != 0) {
                    643:                                NIC_PUT(regt, regh, ED_P0_ISR, 0);
                    644:                                NIC_PUT(regt, regh, ED_P0_ISR, isr);
                    645:                        }
                    646:
                    647:                /*
                    648:                 * Handle transmitter interrupts.  Handle these first because
                    649:                 * the receiver will reset the board under some conditions.
                    650:                 *
                    651:                 * If the chip was reset while a packet was transmitting, it
                    652:                 * may still deliver a TX interrupt.  In this case, just ignore
                    653:                 * the interrupt.
                    654:                 */
                    655:                if (isr & (ED_ISR_PTX | ED_ISR_TXE) &&
                    656:                    sc->txb_inuse != 0) {
                    657:                        u_char collisions =
                    658:                            NIC_GET(regt, regh, ED_P0_NCR) & 0x0f;
                    659:
                    660:                        /*
                    661:                         * Check for transmit error.  If a TX completed with an
                    662:                         * error, we end up throwing the packet away.  Really
                    663:                         * the only error that is possible is excessive
                    664:                         * collisions, and in this case it is best to allow the
                    665:                         * automatic mechanisms of TCP to backoff the flow.  Of
                    666:                         * course, with UDP we're screwed, but this is expected
                    667:                         * when a network is heavily loaded.
                    668:                         */
                    669:                        if (isr & ED_ISR_TXE) {
                    670:                                /*
                    671:                                 * Excessive collisions (16).
                    672:                                 */
                    673:                                if ((NIC_GET(regt, regh, ED_P0_TSR)
                    674:                                    & ED_TSR_ABT) && (collisions == 0)) {
                    675:                                        /*
                    676:                                         * When collisions total 16, the P0_NCR
                    677:                                         * will indicate 0, and the TSR_ABT is
                    678:                                         * set.
                    679:                                         */
                    680:                                        collisions = 16;
                    681:                                }
                    682:
                    683:                                /* Update output errors counter. */
                    684:                                ++ifp->if_oerrors;
                    685:                        } else {
                    686:                                /*
                    687:                                 * Throw away the non-error status bits.
                    688:                                 *
                    689:                                 * XXX
                    690:                                 * It may be useful to detect loss of carrier
                    691:                                 * and late collisions here.
                    692:                                 */
                    693:                                (void)NIC_GET(regt, regh, ED_P0_TSR);
                    694:
                    695:                                /*
                    696:                                 * Update total number of successfully
                    697:                                 * transmitted packets.
                    698:                                 */
                    699:                                ++ifp->if_opackets;
                    700:                        }
                    701:
                    702:                        /* Clear watchdog timer. */
                    703:                        ifp->if_timer = 0;
                    704:                        ifp->if_flags &= ~IFF_OACTIVE;
                    705:
                    706:                        /*
                    707:                         * Add in total number of collisions on last
                    708:                         * transmission.
                    709:                         */
                    710:                        ifp->if_collisions += collisions;
                    711:
                    712:                        /*
                    713:                         * Decrement buffer in-use count if not zero (can only
                    714:                         * be zero if a transmitter interrupt occurred while not
                    715:                         * actually transmitting).
                    716:                         * If data is ready to transmit, start it transmitting,
                    717:                         * otherwise defer until after handling receiver.
                    718:                         */
                    719:                        if (--sc->txb_inuse != 0)
                    720:                                dp8390_xmit(sc);
                    721:                }
                    722:
                    723:                /* Handle receiver interrupts. */
                    724:                if (isr & (ED_ISR_PRX | ED_ISR_RXE | ED_ISR_OVW)) {
                    725:                        /*
                    726:                         * Overwrite warning.  In order to make sure that a
                    727:                         * lockup of the local DMA hasn't occurred, we reset
                    728:                         * and re-init the NIC.  The NSC manual suggests only a
                    729:                         * partial reset/re-init is necessary - but some chips
                    730:                         * seem to want more.  The DMA lockup has been seen
                    731:                         * only with early rev chips - Methinks this bug was
                    732:                         * fixed in later revs.  -DG
                    733:                         */
                    734:                        if (isr & ED_ISR_OVW) {
                    735:                                ++ifp->if_ierrors;
                    736: #ifdef DEBUG
                    737:                                log(LOG_WARNING, "%s: warning - receiver "
                    738:                                    "ring buffer overrun\n",
                    739:                                    sc->sc_dev.dv_xname);
                    740: #endif
                    741:                                /* Stop/reset/re-init NIC. */
                    742:                                dp8390_reset(sc);
                    743:                        } else {
                    744:                                /*
                    745:                                 * Receiver Error.  One or more of: CRC error,
                    746:                                 * frame alignment error FIFO overrun, or
                    747:                                 * missed packet.
                    748:                                 */
                    749:                                if (isr & ED_ISR_RXE) {
                    750:                                        ++ifp->if_ierrors;
                    751: #ifdef DEBUG
                    752:                                        if (dp8390_debug) {
                    753:                                                printf("%s: receive error %x\n",
                    754:                                                    sc->sc_dev.dv_xname,
                    755:                                                    NIC_GET(regt, regh,
                    756:                                                        ED_P0_RSR));
                    757:                                        }
                    758: #endif
                    759:                                }
                    760:
                    761:                                /*
                    762:                                 * Go get the packet(s)
                    763:                                 * XXX - Doing this on an error is dubious
                    764:                                 * because there shouldn't be any data to get
                    765:                                 * (we've configured the interface to not
                    766:                                 * accept packets with errors).
                    767:                                 */
                    768:                                if (sc->recv_int)
                    769:                                        (*sc->recv_int)(sc);
                    770:                                else
                    771:                                        dp8390_rint(sc);
                    772:                        }
                    773:                }
                    774:
                    775:                /*
                    776:                 * If it looks like the transmitter can take more data, attempt
                    777:                 * to start output on the interface.  This is done after
                    778:                 * handling the receiver to give the receiver priority.
                    779:                 */
                    780:                dp8390_start(ifp);
                    781:
                    782:                /*
                    783:                 * Return NIC CR to standard state: page 0, remote DMA
                    784:                 * complete, start (toggling the TXP bit off, even if was just
                    785:                 * set in the transmit routine, is *okay* - it is 'edge'
                    786:                 * triggered from low to high).
                    787:                 */
                    788:                NIC_BARRIER(regt, regh);
                    789:                NIC_PUT(regt, regh, ED_P0_CR,
                    790:                    sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
                    791:                NIC_BARRIER(regt, regh);
                    792:
                    793:                /*
                    794:                 * If the Network Talley Counters overflow, read them to reset
                    795:                 * them.  It appears that old 8390's won't clear the ISR flag
                    796:                 * otherwise - resulting in an infinite loop.
                    797:                 */
                    798:                if (isr & ED_ISR_CNT) {
                    799:                        (void)NIC_GET(regt, regh, ED_P0_CNTR0);
                    800:                        (void)NIC_GET(regt, regh, ED_P0_CNTR1);
                    801:                        (void)NIC_GET(regt, regh, ED_P0_CNTR2);
                    802:                }
                    803:
                    804:                isr = NIC_GET(regt, regh, ED_P0_ISR);
                    805:                if (!isr)
                    806:                        return (1);
                    807:        }
                    808: }
                    809:
                    810: /*
                    811:  * Process an ioctl request.  This code needs some work - it looks pretty ugly.
                    812:  */
                    813: int
                    814: dp8390_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                    815: {
                    816:        struct dp8390_softc *sc = ifp->if_softc;
                    817:        struct ifaddr *ifa = (struct ifaddr *) data;
                    818:        struct ifreq *ifr = (struct ifreq *) data;
                    819:        int s, error = 0;
                    820:
                    821:        s = splnet();
                    822:
                    823:        switch (cmd) {
                    824:
                    825:        case SIOCSIFADDR:
                    826:                if ((error = dp8390_enable(sc)) != 0)
                    827:                        break;
                    828:                ifp->if_flags |= IFF_UP;
                    829:
                    830:                switch (ifa->ifa_addr->sa_family) {
                    831: #ifdef INET
                    832:                case AF_INET:
                    833:                        dp8390_init(sc);
                    834:                        arp_ifinit(&sc->sc_arpcom, ifa);
                    835:                        break;
                    836: #endif
                    837:                default:
                    838:                        dp8390_init(sc);
                    839:                        break;
                    840:                }
                    841:                break;
                    842:
                    843:        case SIOCSIFMTU:
                    844:                if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
                    845:                        error = EINVAL;
                    846:                } else if (ifp->if_mtu != ifr->ifr_mtu) {
                    847:                        ifp->if_mtu = ifr->ifr_mtu;
                    848:                }
                    849:                break;
                    850:
                    851:        case SIOCSIFFLAGS:
                    852:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    853:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                    854:                        /*
                    855:                         * If interface is marked down and it is running, then
                    856:                         * stop it.
                    857:                         */
                    858:                        dp8390_stop(sc);
                    859:                        ifp->if_flags &= ~IFF_RUNNING;
                    860:                        dp8390_disable(sc);
                    861:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                    862:                    (ifp->if_flags & IFF_RUNNING) == 0) {
                    863:                        /*
                    864:                         * If interface is marked up and it is stopped, then
                    865:                         * start it.
                    866:                         */
                    867:                        if ((error = dp8390_enable(sc)) != 0)
                    868:                                break;
                    869:                        dp8390_init(sc);
                    870:                } else if ((ifp->if_flags & IFF_UP) != 0) {
                    871:                        /*
                    872:                         * Reset the interface to pick up changes in any other
                    873:                         * flags that affect hardware registers.
                    874:                         */
                    875:                        dp8390_stop(sc);
                    876:                        dp8390_init(sc);
                    877:                }
                    878:                break;
                    879:
                    880:        case SIOCADDMULTI:
                    881:        case SIOCDELMULTI:
                    882:                if (sc->sc_enabled == 0) {
                    883:                        error = EIO;
                    884:                        break;
                    885:                }
                    886:
                    887:                /* Update our multicast list. */
                    888:                error = (cmd == SIOCADDMULTI) ?
                    889:                    ether_addmulti(ifr, &sc->sc_arpcom) :
                    890:                    ether_delmulti(ifr, &sc->sc_arpcom);
                    891:
                    892:                if (error == ENETRESET) {
                    893:                        /*
                    894:                         * Multicast list has changed; set the hardware filter
                    895:                         * accordingly.
                    896:                         */
                    897:                        if (ifp->if_flags & IFF_RUNNING) {
                    898:                                dp8390_stop(sc);        /* XXX for ds_setmcaf? */
                    899:                                dp8390_init(sc);
                    900:                        }
                    901:                        error = 0;
                    902:                }
                    903:                break;
                    904:
                    905:        case SIOCGIFMEDIA:
                    906:        case SIOCSIFMEDIA:
                    907:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
                    908:                break;
                    909:
                    910:        default:
                    911:                error = EINVAL;
                    912:                break;
                    913:        }
                    914:
                    915:        splx(s);
                    916:        return (error);
                    917: }
                    918:
                    919: /*
                    920:  * Retrieve packet from buffer memory and send to the next level up via
                    921:  * ether_input().  If there is a BPF listener, give a copy to BPF, too.
                    922:  */
                    923: void
                    924: dp8390_read(struct dp8390_softc *sc, int buf, u_short len)
                    925: {
                    926:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    927:        struct mbuf *m;
                    928:
                    929:        /* Pull packet off interface. */
                    930:        m = dp8390_get(sc, buf, len);
                    931:        if (m == 0) {
                    932:                ifp->if_ierrors++;
                    933:                return;
                    934:        }
                    935:
                    936:        ifp->if_ipackets++;
                    937:
                    938: #if NBPFILTER > 0
                    939:        /*
                    940:         * Check if there's a BPF listener on this interface.
                    941:         * If so, hand off the raw packet to bpf.
                    942:         */
                    943:        if (ifp->if_bpf)
                    944:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                    945: #endif
                    946:
                    947:        ether_input_mbuf(ifp, m);
                    948: }
                    949:
                    950:
                    951: /*
                    952:  * Supporting routines.
                    953:  */
                    954:
                    955: /*
                    956:  * Compute the multicast address filter from the list of multicast addresses we
                    957:  * need to listen to.
                    958:  */
                    959: void
                    960: dp8390_getmcaf(struct arpcom *ac, u_int8_t *af)
                    961: {
                    962:        struct ifnet *ifp = &ac->ac_if;
                    963:        struct ether_multi *enm;
                    964:        u_int32_t crc;
                    965:        int i;
                    966:        struct ether_multistep step;
                    967:
                    968:        /*
                    969:         * Set up multicast address filter by passing all multicast addresses
                    970:         * through a crc generator, and then using the high order 6 bits as an
                    971:         * index into the 64 bit logical address filter.  The high order bit
                    972:         * selects the word, while the rest of the bits select the bit within
                    973:         * the word.
                    974:         */
                    975:
                    976:        if (ifp->if_flags & IFF_PROMISC) {
                    977:                ifp->if_flags |= IFF_ALLMULTI;
                    978:                for (i = 0; i < 8; i++)
                    979:                        af[i] = 0xff;
                    980:                return;
                    981:        }
                    982:        for (i = 0; i < 8; i++)
                    983:                af[i] = 0;
                    984:        ETHER_FIRST_MULTI(step, ac, enm);
                    985:        while (enm != NULL) {
                    986:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
                    987:                    sizeof(enm->enm_addrlo)) != 0) {
                    988:                        /*
                    989:                         * We must listen to a range of multicast addresses.
                    990:                         * For now, just accept all multicasts, rather than
                    991:                         * trying to set only those filter bits needed to match
                    992:                         * the range.  (At this time, the only use of address
                    993:                         * ranges is for IP multicast routing, for which the
                    994:                         * range is big enough to require all bits set.)
                    995:                         */
                    996:                        ifp->if_flags |= IFF_ALLMULTI;
                    997:                        for (i = 0; i < 8; i++)
                    998:                                af[i] = 0xff;
                    999:                        return;
                   1000:                }
                   1001:
                   1002:                /* Just want the 6 most significant bits. */
                   1003:                crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
                   1004:
                   1005:                /* Turn on the corresponding bit in the filter. */
                   1006:                af[crc >> 3] |= 1 << (crc & 0x7);
                   1007:
                   1008:                ETHER_NEXT_MULTI(step, enm);
                   1009:        }
                   1010:        ifp->if_flags &= ~IFF_ALLMULTI;
                   1011: }
                   1012:
                   1013: /*
                   1014:  * Copy data from receive buffer to a new mbuf chain allocating mbufs
                   1015:  * as needed.  Return pointer to first mbuf in chain.
                   1016:  * sc = dp8390 info (softc)
                   1017:  * src = pointer in dp8390 ring buffer
                   1018:  * total_len = amount of data to copy
                   1019:  */
                   1020: struct mbuf *
                   1021: dp8390_get(struct dp8390_softc *sc, int src, u_short total_len)
                   1022: {
                   1023:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                   1024:        struct mbuf *m, *m0, *newm;
                   1025:        u_short len;
                   1026:
                   1027:        MGETHDR(m0, M_DONTWAIT, MT_DATA);
                   1028:        if (m0 == NULL)
                   1029:                return (0);
                   1030:        m0->m_pkthdr.rcvif = ifp;
                   1031:        m0->m_pkthdr.len = total_len;
                   1032:        len = MHLEN;
                   1033:        m = m0;
                   1034:
                   1035:        while (total_len > 0) {
                   1036:                if (total_len >= MINCLSIZE) {
                   1037:                        MCLGET(m, M_DONTWAIT);
                   1038:                        if (!(m->m_flags & M_EXT))
                   1039:                                goto bad;
                   1040:                        len = MCLBYTES;
                   1041:                }
                   1042:
                   1043:                /*
                   1044:                 * Make sure the data after the Ethernet header is aligned.
                   1045:                 */
                   1046:                if (m == m0) {
                   1047:                        caddr_t newdata = (caddr_t)
                   1048:                            ALIGN(m->m_data + sizeof(struct ether_header)) -
                   1049:                            sizeof(struct ether_header);
                   1050:                        len -= newdata - m->m_data;
                   1051:                        m->m_data = newdata;
                   1052:                }
                   1053:
                   1054:                m->m_len = len = min(total_len, len);
                   1055:                if (sc->ring_copy)
                   1056:                        src = (*sc->ring_copy)(sc, src, mtod(m, caddr_t), len);
                   1057:                else
                   1058:                        src = dp8390_ring_copy(sc, src, mtod(m, caddr_t), len);
                   1059:
                   1060:                total_len -= len;
                   1061:                if (total_len > 0) {
                   1062:                        MGET(newm, M_DONTWAIT, MT_DATA);
                   1063:                        if (newm == NULL)
                   1064:                                goto bad;
                   1065:                        len = MLEN;
                   1066:                        m = m->m_next = newm;
                   1067:                }
                   1068:        }
                   1069:
                   1070:        return (m0);
                   1071:
                   1072: bad:
                   1073:        m_freem(m0);
                   1074:        return (0);
                   1075: }
                   1076:
                   1077:
                   1078: /*
                   1079:  * Default driver support functions.
                   1080:  *
                   1081:  * NOTE: all support functions assume 8-bit shared memory.
                   1082:  */
                   1083: /*
                   1084:  * Zero NIC buffer memory and verify that it is clear.
                   1085:  */
                   1086: static int
                   1087: dp8390_test_mem(struct dp8390_softc *sc)
                   1088: {
                   1089:        bus_space_tag_t buft = sc->sc_buft;
                   1090:        bus_space_handle_t bufh = sc->sc_bufh;
                   1091:        int i;
                   1092:
                   1093:        bus_space_set_region_1(buft, bufh, sc->mem_start, 0, sc->mem_size);
                   1094:
                   1095:        for (i = 0; i < sc->mem_size; ++i) {
                   1096:                if (bus_space_read_1(buft, bufh, sc->mem_start + i)) {
                   1097:                        printf(": failed to clear NIC buffer at offset %x - "
                   1098:                            "check configuration\n", (sc->mem_start + i));
                   1099:                        return 1;
                   1100:                }
                   1101:        }
                   1102:
                   1103:        return 0;
                   1104: }
                   1105:
                   1106: /*
                   1107:  * Read a packet header from the ring, given the source offset.
                   1108:  */
                   1109: static __inline__ void
                   1110: dp8390_read_hdr(struct dp8390_softc *sc, int src, struct dp8390_ring *hdrp)
                   1111: {
                   1112:        bus_space_tag_t buft = sc->sc_buft;
                   1113:        bus_space_handle_t bufh = sc->sc_bufh;
                   1114:
                   1115:        /*
                   1116:         * The byte count includes a 4 byte header that was added by
                   1117:         * the NIC.
                   1118:         */
                   1119:        hdrp->rsr = bus_space_read_1(buft, bufh, src);
                   1120:        hdrp->next_packet = bus_space_read_1(buft, bufh, src + 1);
                   1121:        hdrp->count = bus_space_read_1(buft, bufh, src + 2) |
                   1122:            (bus_space_read_1(buft, bufh, src + 3) << 8);
                   1123: }
                   1124:
                   1125: /*
                   1126:  * Copy `amount' bytes from a packet in the ring buffer to a linear
                   1127:  * destination buffer, given a source offset and destination address.
                   1128:  * Takes into account ring-wrap.
                   1129:  */
                   1130: static __inline__ int
                   1131: dp8390_ring_copy(struct dp8390_softc *sc, int src, caddr_t dst, u_short amount)
                   1132: {
                   1133:        bus_space_tag_t buft = sc->sc_buft;
                   1134:        bus_space_handle_t bufh = sc->sc_bufh;
                   1135:        u_short tmp_amount;
                   1136:
                   1137:        /* Does copy wrap to lower addr in ring buffer? */
                   1138:        if (src + amount > sc->mem_end) {
                   1139:                tmp_amount = sc->mem_end - src;
                   1140:
                   1141:                /* Copy amount up to end of NIC memory. */
                   1142:                bus_space_read_region_1(buft, bufh, src, dst, tmp_amount);
                   1143:
                   1144:                amount -= tmp_amount;
                   1145:                src = sc->mem_ring;
                   1146:                dst += tmp_amount;
                   1147:        }
                   1148:        bus_space_read_region_1(buft, bufh, src, dst, amount);
                   1149:
                   1150:        return (src + amount);
                   1151: }
                   1152:
                   1153: /*
                   1154:  * Copy a packet from an mbuf to the transmit buffer on the card.
                   1155:  *
                   1156:  * Currently uses an extra buffer/extra memory copy, unless the whole
                   1157:  * packet fits in one mbuf.
                   1158:  */
                   1159: static __inline__ int
                   1160: dp8390_write_mbuf(struct dp8390_softc *sc, struct mbuf *m, int buf)
                   1161: {
                   1162:        bus_space_tag_t buft = sc->sc_buft;
                   1163:        bus_space_handle_t bufh = sc->sc_bufh;
                   1164:        u_char *data;
                   1165:        int len, totlen = 0;
                   1166:
                   1167:        for (; m ; m = m->m_next) {
                   1168:                data = mtod(m, u_char *);
                   1169:                len = m->m_len;
                   1170:                if (len > 0) {
                   1171:                        bus_space_write_region_1(buft, bufh, buf, data, len);
                   1172:                        totlen += len;
                   1173:                        buf += len;
                   1174:                }
                   1175:        }
                   1176:
                   1177:        return (totlen);
                   1178: }
                   1179:
                   1180: /*
                   1181:  * Enable power on the interface.
                   1182:  */
                   1183: int
                   1184: dp8390_enable(struct dp8390_softc *sc)
                   1185: {
                   1186:
                   1187:        if (sc->sc_enabled == 0 && sc->sc_enable != NULL) {
                   1188:                if ((*sc->sc_enable)(sc) != 0) {
                   1189:                        printf("%s: device enable failed\n",
                   1190:                            sc->sc_dev.dv_xname);
                   1191:                        return (EIO);
                   1192:                }
                   1193:        }
                   1194:
                   1195:        sc->sc_enabled = 1;
                   1196:        return (0);
                   1197: }
                   1198:
                   1199: /*
                   1200:  * Disable power on the interface.
                   1201:  */
                   1202: void
                   1203: dp8390_disable(struct dp8390_softc *sc)
                   1204: {
                   1205:        if (sc->sc_enabled != 0 && sc->sc_disable != NULL) {
                   1206:                (*sc->sc_disable)(sc);
                   1207:                sc->sc_enabled = 0;
                   1208:        }
                   1209: }
                   1210:
                   1211: int
                   1212: dp8390_detach(struct dp8390_softc *sc, int flags)
                   1213: {
                   1214:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                   1215:
                   1216:        /* dp8390_disable() checks sc->sc_enabled */
                   1217:        dp8390_disable(sc);
                   1218:
                   1219:        if (sc->sc_media_fini != NULL)
                   1220:                (*sc->sc_media_fini)(sc);
                   1221:
                   1222:        /* Delete all reamining media. */
                   1223:        ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
                   1224:
                   1225:        ether_ifdetach(ifp);
                   1226:        if_detach(ifp);
                   1227:
                   1228:        return (0);
                   1229: }

CVSweb