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

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

1.1       nbrk        1: /*     $OpenBSD: am7990.c,v 1.41 2006/04/20 20:31:12 miod Exp $        */
                      2: /*     $NetBSD: am7990.c,v 1.22 1996/10/13 01:37:19 christos Exp $     */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
                      6:  * Copyright (c) 1992, 1993
                      7:  *     The Regents of the University of California.  All rights reserved.
                      8:  *
                      9:  * This code is derived from software contributed to Berkeley by
                     10:  * Ralph Campbell and Rick Macklem.
                     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 copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
                     36:  *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
                     37:  */
                     38:
                     39: #include "bpfilter.h"
                     40:
                     41: #include <sys/param.h>
                     42: #include <sys/systm.h>
                     43: #include <sys/mbuf.h>
                     44: #include <sys/syslog.h>
                     45: #include <sys/socket.h>
                     46: #include <sys/device.h>
                     47: #include <sys/malloc.h>
                     48: #include <sys/ioctl.h>
                     49: #include <sys/errno.h>
                     50:
                     51: #include <net/if.h>
                     52: #include <net/if_media.h>
                     53:
                     54: #ifdef INET
                     55: #include <netinet/in.h>
                     56: #include <netinet/if_ether.h>
                     57: #include <netinet/in_systm.h>
                     58: #include <netinet/in_var.h>
                     59: #include <netinet/ip.h>
                     60: #endif
                     61:
                     62: #if NBPFILTER > 0
                     63: #include <net/bpf.h>
                     64: #endif
                     65:
                     66: #include <dev/ic/am7990reg.h>
                     67: #include <dev/ic/am7990var.h>
                     68:
                     69: #ifdef LEDEBUG
                     70: void am7990_recv_print(struct am7990_softc *, int);
                     71: void am7990_xmit_print(struct am7990_softc *, int);
                     72: #endif
                     73:
                     74: integrate void am7990_rint(struct am7990_softc *);
                     75: integrate void am7990_tint(struct am7990_softc *);
                     76:
                     77: integrate int am7990_put(struct am7990_softc *, int, struct mbuf *);
                     78: integrate struct mbuf *am7990_get(struct am7990_softc *, int, int);
                     79: integrate void am7990_read(struct am7990_softc *, int, int);
                     80:
                     81: hide void am7990_shutdown(void *);
                     82:
                     83: #define        ifp     (&sc->sc_arpcom.ac_if)
                     84:
                     85: #if 0  /* XXX what do we do about this?!  --thorpej */
                     86: static inline u_int16_t ether_cmp(void *, void *);
                     87:
                     88: /*
                     89:  * Compare two Ether/802 addresses for equality, inlined and
                     90:  * unrolled for speed.  I'd love to have an inline assembler
                     91:  * version of this...   XXX: Who wanted that? mycroft?
                     92:  * I wrote one, but the following is just as efficient.
                     93:  * This expands to 10 short m68k instructions! -gwr
                     94:  * Note: use this like bcmp()
                     95:  */
                     96: static inline u_short
                     97: ether_cmp(one, two)
                     98:        void *one, *two;
                     99: {
                    100:        register u_int16_t *a = (u_short *) one;
                    101:        register u_int16_t *b = (u_short *) two;
                    102:        register u_int16_t diff;
                    103:
                    104:        diff  = *a++ - *b++;
                    105:        diff |= *a++ - *b++;
                    106:        diff |= *a++ - *b++;
                    107:
                    108:        return (diff);
                    109: }
                    110:
                    111: #define ETHER_CMP      ether_cmp
                    112: #endif /* XXX */
                    113:
                    114: #ifndef        ETHER_CMP
                    115: #define        ETHER_CMP(a, b) bcmp((a), (b), ETHER_ADDR_LEN)
                    116: #endif
                    117:
                    118: /*
                    119:  * am7990 configuration driver.  Attachments are provided by
                    120:  * machine-dependent driver front-ends.
                    121:  */
                    122: struct cfdriver le_cd = {
                    123:        NULL, "le", DV_IFNET
                    124: };
                    125:
                    126: void
                    127: am7990_config(sc)
                    128:        struct am7990_softc *sc;
                    129: {
                    130:        int mem;
                    131:
                    132:        /* Make sure the chip is stopped. */
                    133:        am7990_stop(sc);
                    134:
                    135:        /* Initialize ifnet structure. */
                    136:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    137:        ifp->if_softc = sc;
                    138:        ifp->if_start = am7990_start;
                    139:        ifp->if_ioctl = am7990_ioctl;
                    140:        ifp->if_watchdog = am7990_watchdog;
                    141:        ifp->if_flags =
                    142:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
                    143: #ifdef LANCE_REVC_BUG
                    144:        ifp->if_flags &= ~IFF_MULTICAST;
                    145: #endif
                    146:        ifp->if_baudrate = IF_Mbps(10);
                    147:        IFQ_SET_READY(&ifp->if_snd);
                    148:
                    149:        ifp->if_capabilities = IFCAP_VLAN_MTU;
                    150:
                    151:        /* Attach the interface. */
                    152:        if_attach(ifp);
                    153:        ether_ifattach(ifp);
                    154:
                    155:        if (sc->sc_memsize > 262144)
                    156:                sc->sc_memsize = 262144;
                    157:
                    158:        switch (sc->sc_memsize) {
                    159:        case 8192:
                    160:                sc->sc_nrbuf = 4;
                    161:                sc->sc_ntbuf = 1;
                    162:                break;
                    163:        case 16384:
                    164:                sc->sc_nrbuf = 8;
                    165:                sc->sc_ntbuf = 2;
                    166:                break;
                    167:        case 32768:
                    168:                sc->sc_nrbuf = 16;
                    169:                sc->sc_ntbuf = 4;
                    170:                break;
                    171:        case 65536:
                    172:                sc->sc_nrbuf = 32;
                    173:                sc->sc_ntbuf = 8;
                    174:                break;
                    175:        case 131072:
                    176:                sc->sc_nrbuf = 64;
                    177:                sc->sc_ntbuf = 16;
                    178:                break;
                    179:        case 262144:
                    180:                sc->sc_nrbuf = 128;
                    181:                sc->sc_ntbuf = 32;
                    182:                break;
                    183:        default:
                    184:                panic("am7990_config: weird memory size %lu", sc->sc_memsize);
                    185:        }
                    186:
                    187:        printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
                    188:        printf("%s: %d receive buffers, %d transmit buffers\n",
                    189:            sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);
                    190:
                    191:        sc->sc_sh = shutdownhook_establish(am7990_shutdown, sc);
                    192:        if (sc->sc_sh == NULL)
                    193:                panic("am7990_config: can't establish shutdownhook");
                    194:
                    195:        mem = 0;
                    196:        sc->sc_initaddr = mem;
                    197:        mem += sizeof(struct leinit);
                    198:        sc->sc_rmdaddr = mem;
                    199:        mem += sizeof(struct lermd) * sc->sc_nrbuf;
                    200:        sc->sc_tmdaddr = mem;
                    201:        mem += sizeof(struct letmd) * sc->sc_ntbuf;
                    202:        sc->sc_rbufaddr = mem;
                    203:        mem += ETHER_MAX_DIX_LEN * sc->sc_nrbuf;
                    204:        sc->sc_tbufaddr = mem;
                    205:        mem += ETHER_MAX_DIX_LEN * sc->sc_ntbuf;
                    206: #ifdef notyet
                    207:        if (mem > ...)
                    208:                panic(...);
                    209: #endif
                    210: }
                    211:
                    212: void
                    213: am7990_reset(sc)
                    214:        struct am7990_softc *sc;
                    215: {
                    216:        int s;
                    217:
                    218:        s = splnet();
                    219:        am7990_init(sc);
                    220:        splx(s);
                    221: }
                    222:
                    223: /*
                    224:  * Set up the initialization block and the descriptor rings.
                    225:  */
                    226: void
                    227: am7990_meminit(sc)
                    228:        register struct am7990_softc *sc;
                    229: {
                    230:        u_long a;
                    231:        int bix;
                    232:        struct leinit init;
                    233:        struct lermd rmd;
                    234:        struct letmd tmd;
                    235:
                    236: #if NBPFILTER > 0
                    237:        if (ifp->if_flags & IFF_PROMISC)
                    238:                init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
                    239:        else
                    240: #endif
                    241:                init.init_mode = LE_MODE_NORMAL;
                    242:        init.init_padr[0] =
                    243:            (sc->sc_arpcom.ac_enaddr[1] << 8) | sc->sc_arpcom.ac_enaddr[0];
                    244:        init.init_padr[1] =
                    245:            (sc->sc_arpcom.ac_enaddr[3] << 8) | sc->sc_arpcom.ac_enaddr[2];
                    246:        init.init_padr[2] =
                    247:            (sc->sc_arpcom.ac_enaddr[5] << 8) | sc->sc_arpcom.ac_enaddr[4];
                    248:        am7990_setladrf(&sc->sc_arpcom, init.init_ladrf);
                    249:
                    250:        sc->sc_last_rd = 0;
                    251:        sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
                    252:
                    253:        a = sc->sc_addr + LE_RMDADDR(sc, 0);
                    254:        init.init_rdra = a;
                    255:        init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
                    256:
                    257:        a = sc->sc_addr + LE_TMDADDR(sc, 0);
                    258:        init.init_tdra = a;
                    259:        init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
                    260:
                    261:        (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
                    262:
                    263:        /*
                    264:         * Set up receive ring descriptors.
                    265:         */
                    266:        for (bix = 0; bix < sc->sc_nrbuf; bix++) {
                    267:                a = sc->sc_addr + LE_RBUFADDR(sc, bix);
                    268:                rmd.rmd0 = a;
                    269:                rmd.rmd1_hadr = a >> 16;
                    270:                rmd.rmd1_bits = LE_R1_OWN;
                    271:                rmd.rmd2 = -ETHER_MAX_DIX_LEN | LE_XMD2_ONES;
                    272:                rmd.rmd3 = 0;
                    273:                (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
                    274:                    sizeof(rmd));
                    275:        }
                    276:
                    277:        /*
                    278:         * Set up transmit ring descriptors.
                    279:         */
                    280:        for (bix = 0; bix < sc->sc_ntbuf; bix++) {
                    281:                a = sc->sc_addr + LE_TBUFADDR(sc, bix);
                    282:                tmd.tmd0 = a;
                    283:                tmd.tmd1_hadr = a >> 16;
                    284:                tmd.tmd1_bits = 0;
                    285:                tmd.tmd2 = 0 | LE_XMD2_ONES;
                    286:                tmd.tmd3 = 0;
                    287:                (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
                    288:                    sizeof(tmd));
                    289:        }
                    290: }
                    291:
                    292: void
                    293: am7990_stop(sc)
                    294:        struct am7990_softc *sc;
                    295: {
                    296:
                    297:        (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
                    298: }
                    299:
                    300: /*
                    301:  * Initialization of interface; set up initialization block
                    302:  * and transmit/receive descriptor rings.
                    303:  */
                    304: void
                    305: am7990_init(sc)
                    306:        register struct am7990_softc *sc;
                    307: {
                    308:        register int timo;
                    309:        u_long a;
                    310:
                    311:        (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
                    312:        DELAY(100);
                    313:
                    314:        /* Newer LANCE chips have a reset register */
                    315:        if (sc->sc_hwreset)
                    316:                (*sc->sc_hwreset)(sc);
                    317:
                    318:        /* Set the correct byte swapping mode, etc. */
                    319:        (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);
                    320:
                    321:        /* Set up LANCE init block. */
                    322:        am7990_meminit(sc);
                    323:
                    324:        /* Give LANCE the physical address of its init block. */
                    325:        a = sc->sc_addr + LE_INITADDR(sc);
                    326:        (*sc->sc_wrcsr)(sc, LE_CSR1, a);
                    327:        (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16);
                    328:
                    329:        /* Try to initialize the LANCE. */
                    330:        DELAY(100);
                    331:        (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT);
                    332:
                    333:        /* Wait for initialization to finish. */
                    334:        for (timo = 100000; timo; timo--)
                    335:                if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)
                    336:                        break;
                    337:
                    338:        if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {
                    339:                /* Start the LANCE. */
                    340:                (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT |
                    341:                    LE_C0_IDON);
                    342:                ifp->if_flags |= IFF_RUNNING;
                    343:                ifp->if_flags &= ~IFF_OACTIVE;
                    344:                ifp->if_timer = 0;
                    345:                am7990_start(ifp);
                    346:        } else
                    347:                printf("%s: controller failed to initialize\n", sc->sc_dev.dv_xname);
                    348:        if (sc->sc_hwinit)
                    349:                (*sc->sc_hwinit)(sc);
                    350: }
                    351:
                    352: /*
                    353:  * Routine to copy from mbuf chain to transmit buffer in
                    354:  * network buffer memory.
                    355:  */
                    356: integrate int
                    357: am7990_put(sc, boff, m)
                    358:        struct am7990_softc *sc;
                    359:        int boff;
                    360:        register struct mbuf *m;
                    361: {
                    362:        register struct mbuf *n;
                    363:        register int len, tlen = 0;
                    364:
                    365:        for (; m; m = n) {
                    366:                len = m->m_len;
                    367:                if (len == 0) {
                    368:                        MFREE(m, n);
                    369:                        continue;
                    370:                }
                    371:                (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len);
                    372:                boff += len;
                    373:                tlen += len;
                    374:                MFREE(m, n);
                    375:        }
                    376:        if (tlen < LEMINSIZE) {
                    377:                (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen);
                    378:                tlen = LEMINSIZE;
                    379:        }
                    380:        return (tlen);
                    381: }
                    382:
                    383: /*
                    384:  * Pull data off an interface.
                    385:  * Len is length of data, with local net header stripped.
                    386:  * We copy the data into mbufs.  When full cluster sized units are present
                    387:  * we copy into clusters.
                    388:  */
                    389: integrate struct mbuf *
                    390: am7990_get(sc, boff, totlen)
                    391:        struct am7990_softc *sc;
                    392:        int boff, totlen;
                    393: {
                    394:        register struct mbuf *m;
                    395:        struct mbuf *top, **mp;
                    396:        int len, pad;
                    397:
                    398:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                    399:        if (m == 0)
                    400:                return (0);
                    401:        m->m_pkthdr.rcvif = ifp;
                    402:        m->m_pkthdr.len = totlen;
                    403:        pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
                    404:        m->m_data += pad;
                    405:        len = MHLEN - pad;
                    406:        top = 0;
                    407:        mp = &top;
                    408:
                    409:        while (totlen > 0) {
                    410:                if (top) {
                    411:                        MGET(m, M_DONTWAIT, MT_DATA);
                    412:                        if (m == 0) {
                    413:                                m_freem(top);
                    414:                                return 0;
                    415:                        }
                    416:                        len = MLEN;
                    417:                }
                    418:                if (totlen >= MINCLSIZE) {
                    419:                        MCLGET(m, M_DONTWAIT);
                    420:                        if (m->m_flags & M_EXT) {
                    421:                                len = MCLBYTES;
                    422:                                if (!top) {
                    423:                                        m->m_data += pad;
                    424:                                        len -= pad;
                    425:                                }
                    426:                        }
                    427:                }
                    428:                m->m_len = len = min(totlen, len);
                    429:                (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len);
                    430:                boff += len;
                    431:                totlen -= len;
                    432:                *mp = m;
                    433:                mp = &m->m_next;
                    434:        }
                    435:
                    436:        return (top);
                    437: }
                    438:
                    439: /*
                    440:  * Pass a packet to the higher levels.
                    441:  */
                    442: integrate void
                    443: am7990_read(sc, boff, len)
                    444:        register struct am7990_softc *sc;
                    445:        int boff, len;
                    446: {
                    447:        struct mbuf *m;
                    448: #ifdef LANCE_REVC_BUG
                    449:        struct ether_header *eh;
                    450: #endif
                    451:
                    452:        if (len <= sizeof(struct ether_header) ||
                    453:            len > ETHERMTU + ETHER_VLAN_ENCAP_LEN + sizeof(struct ether_header)) {
                    454: #ifdef LEDEBUG
                    455:                printf("%s: invalid packet size %d; dropping\n",
                    456:                    sc->sc_dev.dv_xname, len);
                    457: #endif
                    458:                ifp->if_ierrors++;
                    459:                return;
                    460:        }
                    461:
                    462:        /* Pull packet off interface. */
                    463:        m = am7990_get(sc, boff, len);
                    464:        if (m == 0) {
                    465:                ifp->if_ierrors++;
                    466:                return;
                    467:        }
                    468:
                    469:        ifp->if_ipackets++;
                    470:
                    471: #if NBPFILTER > 0
                    472:        /*
                    473:         * Check if there's a BPF listener on this interface.
                    474:         * If so, hand off the raw packet to BPF.
                    475:         */
                    476:        if (ifp->if_bpf)
                    477:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                    478: #endif
                    479:
                    480: #ifdef LANCE_REVC_BUG
                    481:        /*
                    482:         * The old LANCE (Rev. C) chips have a bug which causes
                    483:         * garbage to be inserted in front of the received packet.
                    484:         * The work-around is to ignore packets with an invalid
                    485:         * destination address (garbage will usually not match).
                    486:         * Of course, this precludes multicast support...
                    487:         */
                    488:        eh = mtod(m, struct ether_header *);
                    489:        if (ETHER_CMP(eh->ether_dhost, sc->sc_arpcom.ac_enaddr) &&
                    490:            ETHER_CMP(eh->ether_dhost, etherbroadcastaddr)) {
                    491:                m_freem(m);
                    492:                return;
                    493:        }
                    494: #endif
                    495:
                    496:        /* Pass the packet up. */
                    497:        ether_input_mbuf(ifp, m);
                    498: }
                    499:
                    500: integrate void
                    501: am7990_rint(sc)
                    502:        struct am7990_softc *sc;
                    503: {
                    504:        register int bix;
                    505:        int rp;
                    506:        struct lermd rmd;
                    507:
                    508:        bix = sc->sc_last_rd;
                    509:
                    510:        /* Process all buffers with valid data. */
                    511:        for (;;) {
                    512:                rp = LE_RMDADDR(sc, bix);
                    513:                (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
                    514:
                    515:                if (rmd.rmd1_bits & LE_R1_OWN)
                    516:                        break;
                    517:
                    518:                if (rmd.rmd1_bits & LE_R1_ERR) {
                    519:                        if (rmd.rmd1_bits & LE_R1_ENP) {
                    520: #ifdef LEDEBUG
                    521:                                if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
                    522:                                        if (rmd.rmd1_bits & LE_R1_FRAM)
                    523:                                                printf("%s: framing error\n",
                    524:                                                    sc->sc_dev.dv_xname);
                    525:                                        if (rmd.rmd1_bits & LE_R1_CRC)
                    526:                                                printf("%s: crc mismatch\n",
                    527:                                                    sc->sc_dev.dv_xname);
                    528:                                }
                    529: #endif
                    530:                        } else {
                    531:                                if (rmd.rmd1_bits & LE_R1_OFLO)
                    532:                                        printf("%s: overflow\n",
                    533:                                            sc->sc_dev.dv_xname);
                    534:                        }
                    535:                        if (rmd.rmd1_bits & LE_R1_BUFF)
                    536:                                printf("%s: receive buffer error\n",
                    537:                                    sc->sc_dev.dv_xname);
                    538:                        ifp->if_ierrors++;
                    539:                } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
                    540:                    (LE_R1_STP | LE_R1_ENP)) {
                    541:                        printf("%s: dropping chained buffer\n",
                    542:                            sc->sc_dev.dv_xname);
                    543:                        ifp->if_ierrors++;
                    544:                } else {
                    545: #ifdef LEDEBUG1
                    546:                        if (sc->sc_debug)
                    547:                                am7990_recv_print(sc, sc->sc_last_rd);
                    548: #endif
                    549:                        am7990_read(sc, LE_RBUFADDR(sc, bix),
                    550:                            (int)rmd.rmd3 - 4);
                    551:                }
                    552:
                    553:                rmd.rmd1_bits = LE_R1_OWN;
                    554:                rmd.rmd2 = -ETHER_MAX_DIX_LEN | LE_XMD2_ONES;
                    555:                rmd.rmd3 = 0;
                    556:                (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
                    557:
                    558: #ifdef LEDEBUG1
                    559:                if (sc->sc_debug)
                    560:                        printf("sc->sc_last_rd = %x, rmd: "
                    561:                               "ladr %04x, hadr %02x, flags %02x, "
                    562:                               "bcnt %04x, mcnt %04x\n",
                    563:                                sc->sc_last_rd,
                    564:                                rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits,
                    565:                                rmd.rmd2, rmd.rmd3);
                    566: #endif
                    567:
                    568:                if (++bix == sc->sc_nrbuf)
                    569:                        bix = 0;
                    570:        }
                    571:
                    572:        sc->sc_last_rd = bix;
                    573: }
                    574:
                    575: integrate void
                    576: am7990_tint(sc)
                    577:        register struct am7990_softc *sc;
                    578: {
                    579:        register int bix;
                    580:        struct letmd tmd;
                    581:
                    582:        bix = sc->sc_first_td;
                    583:
                    584:        for (;;) {
                    585:                if (sc->sc_no_td <= 0)
                    586:                        break;
                    587:
                    588:                (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
                    589:                    sizeof(tmd));
                    590:
                    591: #ifdef LEDEBUG
                    592:                if (sc->sc_debug)
                    593:                        printf("trans tmd: "
                    594:                            "ladr %04x, hadr %02x, flags %02x, "
                    595:                            "bcnt %04x, mcnt %04x\n",
                    596:                            tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
                    597:                            tmd.tmd2, tmd.tmd3);
                    598: #endif
                    599:
                    600:                if (tmd.tmd1_bits & LE_T1_OWN)
                    601:                        break;
                    602:
                    603:                ifp->if_flags &= ~IFF_OACTIVE;
                    604:
                    605:                if (tmd.tmd1_bits & LE_T1_ERR) {
                    606:                        if (tmd.tmd3 & LE_T3_BUFF)
                    607:                                printf("%s: transmit buffer error\n",
                    608:                                    sc->sc_dev.dv_xname);
                    609:                        else if (tmd.tmd3 & LE_T3_UFLO)
                    610:                                printf("%s: underflow\n", sc->sc_dev.dv_xname);
                    611:                        if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
                    612:                                am7990_reset(sc);
                    613:                                return;
                    614:                        }
                    615:                        if (tmd.tmd3 & LE_T3_LCAR) {
                    616:                                if (sc->sc_nocarrier)
                    617:                                        (*sc->sc_nocarrier)(sc);
                    618:                        }
                    619:                        if (tmd.tmd3 & LE_T3_LCOL)
                    620:                                ifp->if_collisions++;
                    621:                        if (tmd.tmd3 & LE_T3_RTRY) {
                    622:                                printf("%s: excessive collisions, tdr %d\n",
                    623:                                    sc->sc_dev.dv_xname,
                    624:                                    tmd.tmd3 & LE_T3_TDR_MASK);
                    625:                                ifp->if_collisions += 16;
                    626:                        }
                    627:                        ifp->if_oerrors++;
                    628:                } else {
                    629:                        if (tmd.tmd1_bits & LE_T1_ONE)
                    630:                                ifp->if_collisions++;
                    631:                        else if (tmd.tmd1_bits & LE_T1_MORE)
                    632:                                /* Real number is unknown. */
                    633:                                ifp->if_collisions += 2;
                    634:                        ifp->if_opackets++;
                    635:                }
                    636:
                    637:                if (++bix == sc->sc_ntbuf)
                    638:                        bix = 0;
                    639:
                    640:                --sc->sc_no_td;
                    641:        }
                    642:
                    643:        sc->sc_first_td = bix;
                    644:
                    645:        am7990_start(ifp);
                    646:
                    647:        if (sc->sc_no_td == 0)
                    648:                ifp->if_timer = 0;
                    649: }
                    650:
                    651: /*
                    652:  * Controller interrupt.
                    653:  */
                    654: int
                    655: am7990_intr(arg)
                    656:        register void *arg;
                    657: {
                    658:        register struct am7990_softc *sc = arg;
                    659:        register u_int16_t isr;
                    660:
                    661:        isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
                    662: #ifdef LEDEBUG
                    663:        if (sc->sc_debug){
                    664:                printf("%s: am7990_intr entering with isr=%04x\n",
                    665:                    sc->sc_dev.dv_xname, isr);
                    666:                printf(" isr: 0x%b\n", isr, LE_C0_BITS);
                    667:        }
                    668: #endif
                    669:        if ((isr & LE_C0_INTR) == 0)
                    670:                return (0);
                    671:
                    672:        /*
                    673:         * After receiving an interrupt, we need to toggle the interrupt
                    674:         * enable bit in order to keep receiving them (some chips works
                    675:         * without this, some do not)
                    676:         */
                    677:        (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~LE_C0_INEA);
                    678:        (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
                    679:
                    680:        if (isr & LE_C0_ERR) {
                    681:                if (isr & LE_C0_BABL) {
                    682: #ifdef LEDEBUG
                    683:                        printf("%s: babble\n", sc->sc_dev.dv_xname);
                    684: #endif
                    685:                        ifp->if_oerrors++;
                    686:                }
                    687: #if 0
                    688:                if (isr & LE_C0_CERR) {
                    689:                        printf("%s: collision error\n", sc->sc_dev.dv_xname);
                    690:                        ifp->if_collisions++;
                    691:                }
                    692: #endif
                    693:                if (isr & LE_C0_MISS) {
                    694: #ifdef LEDEBUG
                    695:                        printf("%s: missed packet\n", sc->sc_dev.dv_xname);
                    696: #endif
                    697:                        ifp->if_ierrors++;
                    698:                }
                    699:                if (isr & LE_C0_MERR) {
                    700:                        printf("%s: memory error\n", sc->sc_dev.dv_xname);
                    701:                        am7990_reset(sc);
                    702:                        return (1);
                    703:                }
                    704:        }
                    705:
                    706:        if ((isr & LE_C0_RXON) == 0) {
                    707:                printf("%s: receiver disabled\n", sc->sc_dev.dv_xname);
                    708:                ifp->if_ierrors++;
                    709:                am7990_reset(sc);
                    710:                return (1);
                    711:        }
                    712:        if ((isr & LE_C0_TXON) == 0) {
                    713:                printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname);
                    714:                ifp->if_oerrors++;
                    715:                am7990_reset(sc);
                    716:                return (1);
                    717:        }
                    718:
                    719:        if (isr & LE_C0_RINT)
                    720:                am7990_rint(sc);
                    721:        if (isr & LE_C0_TINT)
                    722:                am7990_tint(sc);
                    723:
                    724:        return (1);
                    725: }
                    726:
                    727: #undef ifp
                    728:
                    729: void
                    730: am7990_watchdog(ifp)
                    731:        struct ifnet *ifp;
                    732: {
                    733:        struct am7990_softc *sc = ifp->if_softc;
                    734:
                    735:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
                    736:        ++ifp->if_oerrors;
                    737:
                    738:        am7990_reset(sc);
                    739: }
                    740:
                    741: /*
                    742:  * Setup output on interface.
                    743:  * Get another datagram to send off of the interface queue, and map it to the
                    744:  * interface before starting the output.
                    745:  * Called only at splnet or interrupt level.
                    746:  */
                    747: void
                    748: am7990_start(ifp)
                    749:        register struct ifnet *ifp;
                    750: {
                    751:        register struct am7990_softc *sc = ifp->if_softc;
                    752:        register int bix;
                    753:        register struct mbuf *m;
                    754:        struct letmd tmd;
                    755:        int rp;
                    756:        int len;
                    757:
                    758:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                    759:                return;
                    760:
                    761:        bix = sc->sc_last_td;
                    762:
                    763:        for (;;) {
                    764:                rp = LE_TMDADDR(sc, bix);
                    765:                (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
                    766:
                    767:                if (tmd.tmd1_bits & LE_T1_OWN) {
                    768:                        ifp->if_flags |= IFF_OACTIVE;
                    769:                        printf("missing buffer, no_td = %d, last_td = %d\n",
                    770:                            sc->sc_no_td, sc->sc_last_td);
                    771:                }
                    772:
                    773:                IFQ_DEQUEUE(&ifp->if_snd, m);
                    774:                if (m == 0)
                    775:                        break;
                    776:
                    777: #if NBPFILTER > 0
                    778:                /*
                    779:                 * If BPF is listening on this interface, let it see the packet
                    780:                 * before we commit it to the wire.
                    781:                 */
                    782:                if (ifp->if_bpf)
                    783:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
                    784: #endif
                    785:
                    786:                /*
                    787:                 * Copy the mbuf chain into the transmit buffer.
                    788:                 */
                    789:                len = am7990_put(sc, LE_TBUFADDR(sc, bix), m);
                    790:
                    791: #ifdef LEDEBUG
                    792:                if (len > ETHERMTU + sizeof(struct ether_header))
                    793:                        printf("packet length %d\n", len);
                    794: #endif
                    795:
                    796:                ifp->if_timer = 5;
                    797:
                    798:                /*
                    799:                 * Init transmit registers, and set transmit start flag.
                    800:                 */
                    801:                tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
                    802:                tmd.tmd2 = -len | LE_XMD2_ONES;
                    803:                tmd.tmd3 = 0;
                    804:
                    805:                (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
                    806:
                    807: #ifdef LEDEBUG
                    808:                if (sc->sc_debug)
                    809:                        am7990_xmit_print(sc, sc->sc_last_td);
                    810: #endif
                    811:
                    812:                (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
                    813:
                    814:                if (++bix == sc->sc_ntbuf)
                    815:                        bix = 0;
                    816:
                    817:                if (++sc->sc_no_td == sc->sc_ntbuf) {
                    818: #ifdef LEDEBUG
                    819:                        printf("\nequal!\n");
                    820: #endif
                    821:                        ifp->if_flags |= IFF_OACTIVE;
                    822:                        break;
                    823:                }
                    824:
                    825:        }
                    826:
                    827:        sc->sc_last_td = bix;
                    828: }
                    829:
                    830: /*
                    831:  * Process an ioctl request.
                    832:  */
                    833: int
                    834: am7990_ioctl(ifp, cmd, data)
                    835:        register struct ifnet *ifp;
                    836:        u_long cmd;
                    837:        caddr_t data;
                    838: {
                    839:        register struct am7990_softc *sc = ifp->if_softc;
                    840:        struct ifaddr *ifa = (struct ifaddr *)data;
                    841:        struct ifreq *ifr = (struct ifreq *)data;
                    842:        int s, error = 0;
                    843:
                    844:        s = splnet();
                    845:
                    846:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
                    847:                splx(s);
                    848:                return error;
                    849:        }
                    850:
                    851:        switch (cmd) {
                    852:
                    853:        case SIOCSIFADDR:
                    854:                ifp->if_flags |= IFF_UP;
                    855:
                    856:                switch (ifa->ifa_addr->sa_family) {
                    857: #ifdef INET
                    858:                case AF_INET:
                    859:                        am7990_init(sc);
                    860:                        arp_ifinit(&sc->sc_arpcom, ifa);
                    861:                        break;
                    862: #endif
                    863:                default:
                    864:                        am7990_init(sc);
                    865:                        break;
                    866:                }
                    867:                break;
                    868:
                    869:        case SIOCSIFFLAGS:
                    870:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    871:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                    872:                        /*
                    873:                         * If interface is marked down and it is running, then
                    874:                         * stop it.
                    875:                         */
                    876:                        am7990_stop(sc);
                    877:                        ifp->if_flags &= ~IFF_RUNNING;
                    878:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                    879:                           (ifp->if_flags & IFF_RUNNING) == 0) {
                    880:                        /*
                    881:                         * If interface is marked up and it is stopped, then
                    882:                         * start it.
                    883:                         */
                    884:                        am7990_init(sc);
                    885:                } else {
                    886:                        /*
                    887:                         * Reset the interface to pick up changes in any other
                    888:                         * flags that affect hardware registers.
                    889:                         */
                    890:                        /*am7990_stop(sc);*/
                    891:                        am7990_init(sc);
                    892:                }
                    893: #ifdef LEDEBUG
                    894:                if (ifp->if_flags & IFF_DEBUG)
                    895:                        sc->sc_debug = 1;
                    896:                else
                    897:                        sc->sc_debug = 0;
                    898: #endif
                    899:                break;
                    900:
                    901:        case SIOCADDMULTI:
                    902:        case SIOCDELMULTI:
                    903:                error = (cmd == SIOCADDMULTI) ?
                    904:                    ether_addmulti(ifr, &sc->sc_arpcom) :
                    905:                    ether_delmulti(ifr, &sc->sc_arpcom);
                    906:
                    907:                if (error == ENETRESET) {
                    908:                        /*
                    909:                         * Multicast list has changed; set the hardware filter
                    910:                         * accordingly.
                    911:                         */
                    912:                        if (ifp->if_flags & IFF_RUNNING)
                    913:                                am7990_reset(sc);
                    914:                        error = 0;
                    915:                }
                    916:                break;
                    917:
                    918:        case SIOCGIFMEDIA:
                    919:        case SIOCSIFMEDIA:
                    920:                if (sc->sc_hasifmedia)
                    921:                        error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
                    922:                else
                    923:                        error = EINVAL;
                    924:                break;
                    925:
                    926:        default:
                    927:                error = EINVAL;
                    928:                break;
                    929:        }
                    930:
                    931:        splx(s);
                    932:        return (error);
                    933: }
                    934:
                    935: hide void
                    936: am7990_shutdown(arg)
                    937:        void *arg;
                    938: {
                    939:
                    940:        am7990_stop((struct am7990_softc *)arg);
                    941: }
                    942:
                    943: #ifdef LEDEBUG
                    944: void
                    945: am7990_recv_print(sc, no)
                    946:        struct am7990_softc *sc;
                    947:        int no;
                    948: {
                    949:        struct lermd rmd;
                    950:        u_int16_t len;
                    951:        struct ether_header eh;
                    952:
                    953:        (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
                    954:        len = rmd.rmd3;
                    955:        printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
                    956:            len);
                    957:        printf("%s: status %04x\n", sc->sc_dev.dv_xname,
                    958:            (*sc->sc_rdcsr)(sc, LE_CSR0));
                    959:        printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
                    960:            sc->sc_dev.dv_xname,
                    961:            rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
                    962:        if (len >= sizeof(eh)) {
                    963:                (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
                    964:                printf("%s: dst %s", sc->sc_dev.dv_xname,
                    965:                        ether_sprintf(eh.ether_dhost));
                    966:                printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
                    967:                        ntohs(eh.ether_type));
                    968:        }
                    969: }
                    970:
                    971: void
                    972: am7990_xmit_print(sc, no)
                    973:        struct am7990_softc *sc;
                    974:        int no;
                    975: {
                    976:        struct letmd tmd;
                    977:        u_int16_t len;
                    978:        struct ether_header eh;
                    979:
                    980:        (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
                    981:        len = -tmd.tmd2;
                    982:        printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
                    983:            len);
                    984:        printf("%s: status %04x\n", sc->sc_dev.dv_xname,
                    985:            (*sc->sc_rdcsr)(sc, LE_CSR0));
                    986:        printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
                    987:            sc->sc_dev.dv_xname,
                    988:            tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
                    989:        if (len >= sizeof(eh)) {
                    990:                (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
                    991:                printf("%s: dst %s", sc->sc_dev.dv_xname,
                    992:                        ether_sprintf(eh.ether_dhost));
                    993:                printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
                    994:                    ntohs(eh.ether_type));
                    995:        }
                    996: }
                    997: #endif /* LEDEBUG */
                    998:
                    999: /*
                   1000:  * Set up the logical address filter.
                   1001:  */
                   1002: void
                   1003: am7990_setladrf(ac, af)
                   1004:        struct arpcom *ac;
                   1005:        u_int16_t *af;
                   1006: {
                   1007:        struct ifnet *ifp = &ac->ac_if;
                   1008:        struct ether_multi *enm;
                   1009:        register u_int32_t crc;
                   1010:        struct ether_multistep step;
                   1011:
                   1012:        /*
                   1013:         * Set up multicast address filter by passing all multicast addresses
                   1014:         * through a crc generator, and then using the high order 6 bits as an
                   1015:         * index into the 64 bit logical address filter.  The high order bit
                   1016:         * selects the word, while the rest of the bits select the bit within
                   1017:         * the word.
                   1018:         */
                   1019:
                   1020:        if (ifp->if_flags & IFF_PROMISC)
                   1021:                goto allmulti;
                   1022:
                   1023:        af[0] = af[1] = af[2] = af[3] = 0x0000;
                   1024:        ETHER_FIRST_MULTI(step, ac, enm);
                   1025:        while (enm != NULL) {
                   1026:                if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
                   1027:                        /*
                   1028:                         * We must listen to a range of multicast addresses.
                   1029:                         * For now, just accept all multicasts, rather than
                   1030:                         * trying to set only those filter bits needed to match
                   1031:                         * the range.  (At this time, the only use of address
                   1032:                         * ranges is for IP multicast routing, for which the
                   1033:                         * range is big enough to require all bits set.)
                   1034:                         */
                   1035:                        goto allmulti;
                   1036:                }
                   1037:
                   1038:                crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
                   1039:
                   1040:                /* Set the corresponding bit in the filter. */
                   1041:                af[crc >> 4] |= 1 << (crc & 0xf);
                   1042:
                   1043:                ETHER_NEXT_MULTI(step, enm);
                   1044:        }
                   1045:        ifp->if_flags &= ~IFF_ALLMULTI;
                   1046:        return;
                   1047:
                   1048: allmulti:
                   1049:        ifp->if_flags |= IFF_ALLMULTI;
                   1050:        af[0] = af[1] = af[2] = af[3] = 0xffff;
                   1051: }
                   1052:
                   1053:
                   1054: /*
                   1055:  * Routines for accessing the transmit and receive buffers.
                   1056:  * The various CPU and adapter configurations supported by this
                   1057:  * driver require three different access methods for buffers
                   1058:  * and descriptors:
                   1059:  *     (1) contig (contiguous data; no padding),
                   1060:  *     (2) gap2 (two bytes of data followed by two bytes of padding),
                   1061:  *     (3) gap16 (16 bytes of data followed by 16 bytes of padding).
                   1062:  */
                   1063:
                   1064: /*
                   1065:  * contig: contiguous data with no padding.
                   1066:  *
                   1067:  * Buffers may have any alignment.
                   1068:  */
                   1069:
                   1070: void
                   1071: am7990_copytobuf_contig(sc, from, boff, len)
                   1072:        struct am7990_softc *sc;
                   1073:        void *from;
                   1074:        int boff, len;
                   1075: {
                   1076:        volatile caddr_t buf = sc->sc_mem;
                   1077:
                   1078:        /*
                   1079:         * Just call bcopy() to do the work.
                   1080:         */
                   1081:        bcopy(from, buf + boff, len);
                   1082: }
                   1083:
                   1084: void
                   1085: am7990_copyfrombuf_contig(sc, to, boff, len)
                   1086:        struct am7990_softc *sc;
                   1087:        void *to;
                   1088:        int boff, len;
                   1089: {
                   1090:        volatile caddr_t buf = sc->sc_mem;
                   1091:
                   1092:        /*
                   1093:         * Just call bcopy() to do the work.
                   1094:         */
                   1095:        bcopy(buf + boff, to, len);
                   1096: }
                   1097:
                   1098: void
                   1099: am7990_zerobuf_contig(sc, boff, len)
                   1100:        struct am7990_softc *sc;
                   1101:        int boff, len;
                   1102: {
                   1103:        volatile caddr_t buf = sc->sc_mem;
                   1104:
                   1105:        /*
                   1106:         * Just let bzero() do the work
                   1107:         */
                   1108:        bzero(buf + boff, len);
                   1109: }
                   1110:
                   1111: #if 0
                   1112: /*
                   1113:  * Examples only; duplicate these and tweak (if necessary) in
                   1114:  * machine-specific front-ends.
                   1115:  */
                   1116:
                   1117: /*
                   1118:  * gap2: two bytes of data followed by two bytes of pad.
                   1119:  *
                   1120:  * Buffers must be 4-byte aligned.  The code doesn't worry about
                   1121:  * doing an extra byte.
                   1122:  */
                   1123:
                   1124: void
                   1125: am7990_copytobuf_gap2(sc, fromv, boff, len)
                   1126:        struct am7990_softc *sc;
                   1127:        void *fromv;
                   1128:        int boff;
                   1129:        register int len;
                   1130: {
                   1131:        volatile caddr_t buf = sc->sc_mem;
                   1132:        register caddr_t from = fromv;
                   1133:        register volatile u_int16_t *bptr;
                   1134:
                   1135:        if (boff & 0x1) {
                   1136:                /* handle unaligned first byte */
                   1137:                bptr = ((volatile u_int16_t *)buf) + (boff - 1);
                   1138:                *bptr = (*from++ << 8) | (*bptr & 0xff);
                   1139:                bptr += 2;
                   1140:                len--;
                   1141:        } else
                   1142:                bptr = ((volatile u_int16_t *)buf) + boff;
                   1143:        while (len > 1) {
                   1144:                *bptr = (from[1] << 8) | (from[0] & 0xff);
                   1145:                bptr += 2;
                   1146:                from += 2;
                   1147:                len -= 2;
                   1148:        }
                   1149:        if (len == 1)
                   1150:                *bptr = (u_int16_t)*from;
                   1151: }
                   1152:
                   1153: void
                   1154: am7990_copyfrombuf_gap2(sc, tov, boff, len)
                   1155:        struct am7990_softc *sc;
                   1156:        void *tov;
                   1157:        int boff, len;
                   1158: {
                   1159:        volatile caddr_t buf = sc->sc_mem;
                   1160:        register caddr_t to = tov;
                   1161:        register volatile u_int16_t *bptr;
                   1162:        register u_int16_t tmp;
                   1163:
                   1164:        if (boff & 0x1) {
                   1165:                /* handle unaligned first byte */
                   1166:                bptr = ((volatile u_int16_t *)buf) + (boff - 1);
                   1167:                *to++ = (*bptr >> 8) & 0xff;
                   1168:                bptr += 2;
                   1169:                len--;
                   1170:        } else
                   1171:                bptr = ((volatile u_int16_t *)buf) + boff;
                   1172:        while (len > 1) {
                   1173:                tmp = *bptr;
                   1174:                *to++ = tmp & 0xff;
                   1175:                *to++ = (tmp >> 8) & 0xff;
                   1176:                bptr += 2;
                   1177:                len -= 2;
                   1178:        }
                   1179:        if (len == 1)
                   1180:                *to = *bptr & 0xff;
                   1181: }
                   1182:
                   1183: void
                   1184: am7990_zerobuf_gap2(sc, boff, len)
                   1185:        struct am7990_softc *sc;
                   1186:        int boff, len;
                   1187: {
                   1188:        volatile caddr_t buf = sc->sc_mem;
                   1189:        register volatile u_int16_t *bptr;
                   1190:
                   1191:        if ((unsigned)boff & 0x1) {
                   1192:                bptr = ((volatile u_int16_t *)buf) + (boff - 1);
                   1193:                *bptr &= 0xff;
                   1194:                bptr += 2;
                   1195:                len--;
                   1196:        } else
                   1197:                bptr = ((volatile u_int16_t *)buf) + boff;
                   1198:        while (len > 0) {
                   1199:                *bptr = 0;
                   1200:                bptr += 2;
                   1201:                len -= 2;
                   1202:        }
                   1203: }
                   1204:
                   1205: /*
                   1206:  * gap16: 16 bytes of data followed by 16 bytes of pad.
                   1207:  *
                   1208:  * Buffers must be 32-byte aligned.
                   1209:  */
                   1210:
                   1211: void
                   1212: am7990_copytobuf_gap16(sc, fromv, boff, len)
                   1213:        struct am7990_softc *sc;
                   1214:        void *fromv;
                   1215:        int boff;
                   1216:        register int len;
                   1217: {
                   1218:        volatile caddr_t buf = sc->sc_mem;
                   1219:        register caddr_t from = fromv;
                   1220:        register caddr_t bptr;
                   1221:        register int xfer;
                   1222:
                   1223:        bptr = buf + ((boff << 1) & ~0x1f);
                   1224:        boff &= 0xf;
                   1225:        xfer = min(len, 16 - boff);
                   1226:        while (len > 0) {
                   1227:                bcopy(from, bptr + boff, xfer);
                   1228:                from += xfer;
                   1229:                bptr += 32;
                   1230:                boff = 0;
                   1231:                len -= xfer;
                   1232:                xfer = min(len, 16);
                   1233:        }
                   1234: }
                   1235:
                   1236: void
                   1237: am7990_copyfrombuf_gap16(sc, tov, boff, len)
                   1238:        struct am7990_softc *sc;
                   1239:        void *tov;
                   1240:        int boff, len;
                   1241: {
                   1242:        volatile caddr_t buf = sc->sc_mem;
                   1243:        register caddr_t to = tov;
                   1244:        register caddr_t bptr;
                   1245:        register int xfer;
                   1246:
                   1247:        bptr = buf + ((boff << 1) & ~0x1f);
                   1248:        boff &= 0xf;
                   1249:        xfer = min(len, 16 - boff);
                   1250:        while (len > 0) {
                   1251:                bcopy(bptr + boff, to, xfer);
                   1252:                to += xfer;
                   1253:                bptr += 32;
                   1254:                boff = 0;
                   1255:                len -= xfer;
                   1256:                xfer = min(len, 16);
                   1257:        }
                   1258: }
                   1259:
                   1260: void
                   1261: am7990_zerobuf_gap16(sc, boff, len)
                   1262:        struct am7990_softc *sc;
                   1263:        int boff, len;
                   1264: {
                   1265:        volatile caddr_t buf = sc->sc_mem;
                   1266:        register caddr_t bptr;
                   1267:        register int xfer;
                   1268:
                   1269:        bptr = buf + ((boff << 1) & ~0x1f);
                   1270:        boff &= 0xf;
                   1271:        xfer = min(len, 16 - boff);
                   1272:        while (len > 0) {
                   1273:                bzero(bptr + boff, xfer);
                   1274:                bptr += 32;
                   1275:                boff = 0;
                   1276:                len -= xfer;
                   1277:                xfer = min(len, 16);
                   1278:        }
                   1279: }
                   1280: #endif /* Example only */

CVSweb