Annotation of Net2/arch/i386/isa/if_we.c, revision 1.1.1.4

1.1       root        1: /*-
                      2:  * Copyright (c) 1990 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * Tim L. Tucker.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. 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:  *
1.1.1.4 ! root       36:  *     from: @(#)if_we.c       7.3 (Berkeley) 5/21/91
        !            37:  *     if_we.c,v 1.10 1993/05/20 10:40:48 deraadt Exp
1.1       root       38:  */
                     39: 
                     40: /*
                     41:  * Modification history
                     42:  *
                     43:  * 8/28/89 - Initial version(if_wd.c), Tim L Tucker
1.1.1.3   root       44:  *
                     45:  * 92.09.19 - Changes to allow multiple we interfaces in one box.
                     46:  *          Allowed interupt handler to look at unit other than 0
                     47:  *
                     48:  * BPF Packet Filter Support added by Marc Frajola, 12/30/92
                     49:  * Input & other routines re-written by David Greenman, 1/2/93
                     50:  * BPF trailer support added by David Greenman, 1/7/93
                     51:  *
1.1.1.4 ! root       52:  * if_we.c,v
        !            53:  * Revision 1.10  1993/05/20  10:40:48  deraadt
        !            54:  * we driver prints same ethernet address message as other drivers
        !            55:  *
        !            56:  * Revision 1.9  1993/05/18  18:19:01  cgd
        !            57:  * make kernel select interface be one-stop shopping & clean it all up.
        !            58:  *
        !            59:  * Revision 1.8  1993/05/01  19:12:45  mycroft
        !            60:  * Fix error in last change.  B-P
        !            61:  *
        !            62:  * Revision 1.7  1993/04/30  23:48:35  mycroft
        !            63:  * Move bpfattach() call into weattach().
        !            64:  *
        !            65:  * Revision 1.6  1993/04/29  09:33:21  mycroft
        !            66:  * Fix total bogosity in the receiver code.
        !            67:  *
        !            68:  * Revision 1.5  1993/04/10  15:58:56  glass
1.1.1.3   root       69:  * Fixed so they are useable when compiled with options NS.  Not that I know
                     70:  * anyone who will.....
                     71:  *
                     72:  * Revision 1.4  1993/04/08  08:26:54  deraadt
                     73:  * dmesg output at boottime now tries to print out information as
                     74:  * soon as it is available. The output looks much more like Sunos.
                     75:  *
                     76:  * Revision 1.3  1993/03/24  23:54:19  cgd
                     77:  * brought in drivers from David Greenman's ([email protected])
                     78:  * BPF package
                     79:  *
                     80:  * Revision 1.2  93/02/18  17:21:57  davidg
                     81:  * Bugs in mbuf cluster allocation fixed
                     82:  * Problem with nfs wanting mbufs aligned on longword boundries fixed
                     83:  * 
1.1       root       84:  */
                     85:  
                     86: #include "we.h"
                     87: #if    NWE > 0
                     88: /*
                     89:  * Western Digital 8003 ethernet/starlan adapter
                     90:  *
                     91:  * Supports the following interface cards:
                     92:  * WD8003E, WD8003EBT, WD8003S, WD8003SBT, WD8013EBT
                     93:  *
                     94:  * The Western Digital card is one of many AT/MCA ethernet interfaces
                     95:  * based on the National DS8390 Network Interface chip set.
                     96:  */
                     97: #include "param.h"
                     98: #include "mbuf.h"
                     99: #include "socket.h"
                    100: #include "ioctl.h"
                    101: #include "errno.h"
                    102: #include "syslog.h"
1.1.1.4 ! root      103: #include "select.h"
1.1       root      104: 
                    105: #include "net/if.h"
1.1.1.3   root      106: #include "net/if_types.h"
                    107: #include "net/if_dl.h"
1.1       root      108: #include "net/netisr.h"
                    109: 
                    110: #ifdef INET
                    111: #include "netinet/in.h"
                    112: #include "netinet/in_systm.h"
                    113: #include "netinet/in_var.h"
                    114: #include "netinet/ip.h"
                    115: #include "netinet/if_ether.h"
                    116: #endif
                    117: 
                    118: #ifdef NS
                    119: #include "netns/ns.h"
                    120: #include "netns/ns_if.h"
                    121: #endif
                    122: 
1.1.1.3   root      123: #include "bpfilter.h"
                    124: #if NBPFILTER > 0
                    125: #include "net/bpf.h"
                    126: #include "net/bpfdesc.h"
                    127: #endif
                    128: 
1.1.1.2   root      129: #include "i386/isa/isa.h"
1.1       root      130: #include "i386/isa/if_wereg.h"
                    131: #include "i386/isa/isa_device.h"
1.1.1.2   root      132: #include "i386/isa/icu.h"
1.1.1.3   root      133: #if 0
                    134: #include "i386/include/pio.h"
                    135: #endif
                    136: 
                    137: static inline char *we_ring_copy();
1.1       root      138:  
                    139: /*
                    140:  * This constant should really be 60 because the we adds 4 bytes of crc.
1.1.1.2   root      141:  * However when set to 60 our packets are ignored by deunas , 3coms are
1.1       root      142:  * okay ??????????????????????????????????????????
                    143:  */
                    144: #define ETHER_MIN_LEN 64
                    145: #define        ETHER_ADDR_LEN 6
                    146: #define ETHER_HDR_SIZE 14
                    147:  
                    148: /*
                    149:  * Ethernet software status per interface.
                    150:  *
                    151:  * Each interface is referenced by a network interface structure,
                    152:  * qe_if, which the routing code uses to locate the interface.
                    153:  * This structure contains the output queue for the interface, its address, ...
                    154:  */
                    155: struct we_softc {
                    156:        struct  arpcom we_ac;           /* Ethernet common part         */
                    157: #define        we_if   we_ac.ac_if             /* network-visible interface    */
                    158: #define        we_addr we_ac.ac_enaddr         /* hardware Ethernet address    */
1.1.1.3   root      159: #define        ns_addrp we_ac.ac_enaddr                /* hardware Ethernet address    */
1.1       root      160:        u_char  we_flags;               /* software state               */
                    161: #define        WDF_RUNNING     0x01
                    162: #define WDF_TXBUSY     0x02
                    163: 
                    164:        u_char  we_type;                /* interface type code          */
                    165:        u_short we_vector;              /* interrupt vector             */
                    166:        short   we_io_ctl_addr;         /* i/o bus address, control     */
                    167:        short   we_io_nic_addr;         /* i/o bus address, DS8390      */
                    168: 
                    169:        caddr_t we_vmem_addr;           /* card RAM virtual memory base */
                    170:        u_long  we_vmem_size;           /* card RAM bytes               */
                    171:        caddr_t we_vmem_ring;           /* receive ring RAM vaddress    */
                    172:        caddr_t we_vmem_end;            /* receive ring RAM end */
1.1.1.3   root      173:        caddr_t we_bpf;                 /* Magic Cookie for BPF */
1.1.1.4 ! root      174: 
        !           175: #ifdef WEDEBUG
        !           176:        int fae, crc, mpa;
        !           177: #endif
1.1       root      178: } we_softc[NWE];
                    179: 
                    180: int    weprobe(), weattach(), weintr(), westart();
                    181: int    weinit(), ether_output(), weioctl(), wereset(), wewatchdog();
                    182: 
                    183: struct isa_driver wedriver = {
                    184:        weprobe, weattach, "we",
                    185: };
                    186:  
1.1.1.2   root      187: static unsigned short wemask[] =
                    188:        { IRQ9, IRQ3, IRQ5, IRQ7, IRQ10, IRQ11, IRQ15, IRQ4 };
                    189:        
1.1       root      190: /*
1.1.1.2   root      191:  * Probe the WD8003 to see if its there
1.1       root      192:  */
                    193: weprobe(is)
                    194:        struct isa_device *is;
                    195: {
                    196:        register int i;
                    197:        register struct we_softc *sc = &we_softc[is->id_unit];
                    198:        union we_mem_sel wem;
                    199:        u_char sum;
1.1.1.3   root      200: #ifdef WD8013                                          /* 20 Sep 92*/
                    201:        union we_laar laar;
                    202: 
                    203:        laar.laar_byte = 0;
                    204: #endif /* WD8013*/
                    205: 
                    206:        wem.ms_byte = 0;                                /* 20 Sep 92*/
1.1       root      207:  
1.1.1.2   root      208:        /* reset card to force it into a known state. */
                    209:        outb(is->id_iobase, 0x80);
                    210:        DELAY(100);
                    211:        outb(is->id_iobase, 0x00);
                    212:        /* wait in the case this card is reading it's EEROM */
                    213:        DELAY(5000);
                    214: 
1.1.1.3   root      215: #ifdef WD8013                                          /* 20 Sep 92*/
                    216:        /* allow the NIC to access the shared RAM 16 bits at a time */
                    217: 
                    218:        laar.addr_l19 = 1;
                    219:        laar.lan_16_en = 1;
                    220:        laar.mem_16_en = 1;
                    221:        outb(is->id_iobase+5, laar.laar_byte);  /* Write a 0xc1 */
                    222: #endif /* WD8013*/
                    223: 
1.1       root      224:        /*
                    225:         * Here we check the card ROM, if the checksum passes, and the
                    226:         * type code and ethernet address check out, then we know we have
                    227:         * a wd8003 card.
                    228:         *
                    229:         * Autoconfiguration: No warning message is printed on error.
                    230:         */
                    231:        for (sum = 0, i = 0; i < 8; ++i)
                    232:            sum += inb(is->id_iobase + WD_ROM_OFFSET + i);
1.1.1.3   root      233:        if (sum != WD_CHECKSUM) {               /* 09 Sep 92*/
                    234: #ifdef WECOMPAT
                    235:            printf( "we: probe: checksum failed... installing anyway\n");
                    236:            printf( "we: Danpex EW-2016 or other 8013 clone card?\n");
                    237: #else  /* !WECOMPAT*/
1.1       root      238:             return (0);
1.1.1.3   root      239: #endif /* !WECOMPAT*/
                    240:        }
1.1       root      241:        sc->we_type = inb(is->id_iobase + WD_ROM_OFFSET + 6);
1.1.1.2   root      242: #ifdef nope
                    243:        if ((sc->we_type & WD_REVMASK) != 2             /* WD8003E or WD8003S */
                    244:                && (sc->we_type & WD_REVMASK) != 4      /* WD8003EBT */
                    245:                && (sc->we_type & WD_REVMASK) != 6)        /* WD8003ELB? */
1.1       root      246:             return (0);
1.1.1.2   root      247: #endif
                    248: /*printf("type %x ", sc->we_type);*/
                    249:        if (sc->we_type & WD_SOFTCONFIG) {
                    250:                int iv = inb(is->id_iobase + 1) & 4 |
                    251:                        ((inb(is->id_iobase+4) & 0x60) >> 5);
                    252: /*printf("iv %d ", iv);*/
                    253:                if (wemask[iv] != is->id_irq)
                    254:                        return(0);
                    255:                outb(is->id_iobase+4, inb(is->id_iobase+4) | 0x80);
                    256:        }
1.1       root      257: 
                    258:        /*
                    259:         * Setup card RAM area and i/o addresses
                    260:         * Kernel Virtual to segment C0000-DFFFF?????
                    261:         */
                    262:        sc->we_io_ctl_addr = is->id_iobase;
                    263:        sc->we_io_nic_addr = sc->we_io_ctl_addr + WD_NIC_OFFSET;
                    264:        sc->we_vector = is->id_irq;
                    265:        sc->we_vmem_addr = (caddr_t)is->id_maddr;
                    266:        sc->we_vmem_size = is->id_msize;
                    267:        sc->we_vmem_ring = sc->we_vmem_addr + (WD_PAGE_SIZE * WD_TXBUF_SIZE);
                    268:        sc->we_vmem_end = sc->we_vmem_addr + is->id_msize;
                    269: 
                    270:        /*
                    271:         * Save board ROM station address
                    272:         */
                    273:        for (i = 0; i < ETHER_ADDR_LEN; ++i)
                    274:            sc->we_addr[i] = inb(sc->we_io_ctl_addr + WD_ROM_OFFSET + i);
                    275: 
                    276:        /*
                    277:         * Mapin interface memory, setup memory select register
                    278:         */
1.1.1.2   root      279:         wem.ms_addr = kvtop(sc->we_vmem_addr) >> 13;
1.1       root      280:        wem.ms_enable = 1;
                    281:        wem.ms_reset = 0;
                    282:        outb(sc->we_io_ctl_addr, wem.ms_byte);
                    283: 
                    284:        /*
                    285:         * clear interface memory, then sum to make sure its valid
                    286:         */
                    287:        for (i = 0; i < sc->we_vmem_size; ++i)
                    288:            sc->we_vmem_addr[i] = 0x0;
                    289:        for (sum = 0, i = 0; i < sc->we_vmem_size; ++i)
                    290:            sum += sc->we_vmem_addr[i];
                    291:        if (sum != 0x0) {
                    292:             printf("we%d: wd8003 dual port RAM address error\n", is->id_unit);
                    293:            return (0);
                    294:        }
                    295: 
                    296:        return (WD_IO_PORTS);
                    297: }
                    298:  
                    299: /*
                    300:  * Interface exists: make available by filling in network interface
                    301:  * record.  System will initialize the interface when it is ready
                    302:  * to accept packets.
                    303:  */
                    304: weattach(is)
                    305:        struct isa_device *is;
                    306: {
                    307:        register struct we_softc *sc = &we_softc[is->id_unit];
                    308:        register struct ifnet *ifp = &sc->we_if;
                    309:        union we_command wecmd;
1.1.1.3   root      310:        struct ifaddr *ifa;
                    311:        struct sockaddr_dl *sdl;
1.1       root      312:  
                    313:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
                    314:        wecmd.cs_stp = 1;
                    315:        wecmd.cs_sta = 0;
                    316:        wecmd.cs_ps = 0;
                    317:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
                    318:        /*
                    319:         * Initialize ifnet structure
                    320:         */
                    321:        ifp->if_unit = is->id_unit;
                    322:        ifp->if_name = "we" ;
                    323:        ifp->if_mtu = ETHERMTU;
                    324:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS ;
                    325:        ifp->if_init = weinit;
                    326:        ifp->if_output = ether_output;
                    327:        ifp->if_start = westart;
                    328:        ifp->if_ioctl = weioctl;
                    329:        ifp->if_reset = wereset;
                    330:        ifp->if_watchdog = wewatchdog;
                    331:        if_attach(ifp);
1.1.1.3   root      332:        /* Search down the ifa address list looking for the AF_LINK type entry */
                    333:        ifa = ifp->if_addrlist;
                    334:        while ((ifa != 0) &&
                    335:               (ifa->ifa_addr != 0) &&
                    336:               (ifa->ifa_addr->sa_family != AF_LINK))
                    337:                {
                    338:                ifa = ifa->ifa_next;
                    339:                }
                    340:        /* If we find an AF_LINK type entry, we well fill in the hardware addr */
                    341:        if ((ifa != 0) &&
                    342:            (ifa->ifa_addr != 0))
                    343:                {
                    344:                /* Fill in the link level address for this interface */
                    345:                sdl = (struct sockaddr_dl *)ifa->ifa_addr;
                    346:                sdl->sdl_type = IFT_ETHER;
                    347:                sdl->sdl_alen = ETHER_ADDR_LEN;
                    348:                sdl->sdl_slen = 0;
                    349:                bcopy(sc->we_addr, LLADDR(sdl), ETHER_ADDR_LEN);
                    350:                }
                    351: 
1.1.1.4 ! root      352: #ifdef WEDEBUG
        !           353:        sc->fae = sc->crc = sc->mpa = 0;
1.1.1.3   root      354: #endif
1.1       root      355:  
                    356:        /*
                    357:         * Banner...
                    358:         */
1.1.1.4 ! root      359:        printf("we%d: %s address %s\n", is->id_unit,
        !           360:                (sc->we_type & WD_ETHERNET) ? "ethernet" : "starlan",
1.1       root      361:                ether_sprintf(sc->we_addr));
1.1.1.4 ! root      362: 
        !           363: #if NBPFILTER > 0
        !           364:        bpfattach(&sc->we_bpf, ifp, DLT_EN10MB,
        !           365:                  sizeof(struct ether_header));
        !           366: #endif
1.1       root      367: }
                    368:  
                    369: /*
                    370:  * Reset of interface.
                    371:  */
                    372: wereset(unit, uban)
                    373:        int unit, uban;
                    374: {
                    375:        if (unit >= NWE)
                    376:                return;
                    377:        printf("we%d: reset\n", unit);
                    378: /*     we_softc[unit].we_flags &= ~WDF_RUNNING; */
                    379:        weinit(unit);
                    380: }
                    381:  
                    382: /*
                    383:  * Take interface offline.
                    384:  */
                    385: westop(unit)
                    386:        int unit;
                    387: {
                    388:        register struct we_softc *sc = &we_softc[unit];
                    389:        union we_command wecmd;
                    390:        int s;
                    391:  
                    392:        /*
                    393:         * Shutdown DS8390
                    394:         */
                    395:        s = splimp();
                    396:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
                    397:        wecmd.cs_stp = 1;
                    398:        wecmd.cs_sta = 0;
                    399:        wecmd.cs_ps = 0;
                    400:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
                    401:        (void) splx(s);
                    402: }
                    403: 
                    404: wewatchdog(unit) {
                    405: 
1.1.1.3   root      406:        weintr(unit);
                    407:        /*log(LOG_WARNING,"we%d: soft reset\n", unit);
1.1       root      408:        westop(unit);
1.1.1.3   root      409:        weinit(unit);*/
1.1       root      410: }
                    411: 
                    412: /*
                    413:  * Initialization of interface (really just DS8390). 
                    414:  */
                    415: weinit(unit)
                    416:        int unit;
                    417: {
                    418:        register struct we_softc *sc = &we_softc[unit];
                    419:        register struct ifnet *ifp = &sc->we_if;
                    420:        union we_command wecmd;
                    421:        int i, s;
1.1.1.3   root      422: 
1.1       root      423:        /* address not known */
                    424:        if (ifp->if_addrlist == (struct ifaddr *)0)
                    425:                return;
                    426: 
                    427:        /* already running */
                    428:        /*if (ifp->if_flags & IFF_RUNNING) return; */
                    429: 
                    430:        /*
                    431:         * Initialize DS8390 in order given in NSC NIC manual.
                    432:         * this is stock code...please see the National manual for details.
                    433:         */
                    434:        s = splhigh();
                    435:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
                    436:        wecmd.cs_stp = 1;
                    437:        wecmd.cs_sta = 0;
                    438:        wecmd.cs_ps = 0;
                    439:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
1.1.1.3   root      440: #ifdef WD8013                                          /* 20 Sep 92*/
                    441:        /* enable 16 bit access if 8013 card */
                    442:        outb(sc->we_io_nic_addr + WD_P0_DCR, WD_D_CONFIG16);
                    443: #else  /* !WD8013*/
1.1       root      444:        outb(sc->we_io_nic_addr + WD_P0_DCR, WD_D_CONFIG);
1.1.1.3   root      445: #endif /* !WD8013*/
1.1       root      446:        outb(sc->we_io_nic_addr + WD_P0_RBCR0, 0);
                    447:        outb(sc->we_io_nic_addr + WD_P0_RBCR1, 0);
                    448:        outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_MON);
                    449:        outb(sc->we_io_nic_addr + WD_P0_TCR, WD_T_CONFIG);
                    450:        outb(sc->we_io_nic_addr + WD_P0_TPSR, 0);
                    451:        outb(sc->we_io_nic_addr + WD_P0_PSTART, WD_TXBUF_SIZE);
                    452:        outb(sc->we_io_nic_addr + WD_P0_PSTOP,
                    453:                sc->we_vmem_size / WD_PAGE_SIZE);
                    454:        outb(sc->we_io_nic_addr + WD_P0_BNRY, WD_TXBUF_SIZE);
                    455:        outb(sc->we_io_nic_addr + WD_P0_ISR, 0xff);
                    456:        outb(sc->we_io_nic_addr + WD_P0_IMR, WD_I_CONFIG);
                    457:        wecmd.cs_ps = 1;
                    458:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
                    459:        for (i = 0; i < ETHER_ADDR_LEN; ++i)
                    460:            outb(sc->we_io_nic_addr + WD_P1_PAR0 + i, sc->we_addr[i]);
                    461:        for (i = 0; i < ETHER_ADDR_LEN; ++i)    /* == broadcast addr */
                    462:            outb(sc->we_io_nic_addr + WD_P1_MAR0 + i, 0xff);
1.1.1.4 ! root      463:        outb(sc->we_io_nic_addr + WD_P1_CURR, WD_TXBUF_SIZE + 1);
1.1       root      464:        wecmd.cs_ps = 0;
                    465:        wecmd.cs_stp = 0;
                    466:        wecmd.cs_sta = 1;
                    467:        wecmd.cs_rd = 0x4;
                    468:        outb(sc->we_io_nic_addr + WD_P1_COMMAND, wecmd.cs_byte);
1.1.1.3   root      469: #if NBPFILTER > 0
                    470:        if (sc->we_if.if_flags & IFF_PROMISC) {
                    471:                outb(sc->we_io_nic_addr + WD_P0_RCR,
                    472:                         WD_R_PRO | WD_R_SEP | WD_R_AR | WD_R_CONFIG);
                    473:        } else
                    474: #endif
                    475:                outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_CONFIG);
1.1       root      476: 
                    477:        /*
                    478:         * Take the interface out of reset, program the vector, 
                    479:         * enable interrupts, and tell the world we are up.
                    480:         */
                    481:        ifp->if_flags |= IFF_RUNNING;
                    482:        sc->we_flags &= ~WDF_TXBUSY;
                    483:        (void) splx(s);
                    484:        westart(ifp);
                    485: }
                    486:  
                    487: /*
                    488:  * Start output on interface.
                    489:  */
                    490: westart(ifp)
                    491:        struct ifnet *ifp;
                    492: {
                    493:        register struct we_softc *sc = &we_softc[ifp->if_unit];
                    494:        struct mbuf *m0, *m;
                    495:        register caddr_t buffer;
                    496:        int len, s;
                    497:        union we_command wecmd;
1.1.1.3   root      498: 
1.1       root      499:        /*
                    500:         * The DS8390 has only one transmit buffer, if it is busy we
                    501:         * must wait until the transmit interrupt completes.
                    502:         */
                    503:        s = splhigh();
1.1.1.3   root      504: 
1.1       root      505:        if (sc->we_flags & WDF_TXBUSY) {
                    506:                (void) splx(s);
                    507:                return;
                    508:        }
                    509:        IF_DEQUEUE(&sc->we_if.if_snd, m);
                    510:        if (m == 0) {
                    511:                (void) splx(s);
                    512:                return;
                    513:        }
                    514:        sc->we_flags |= WDF_TXBUSY; 
1.1.1.3   root      515: 
1.1       root      516:        (void) splx(s);
                    517: 
1.1.1.3   root      518: #if NBPFILTER > 0
                    519:        if (sc->we_bpf) {
                    520:                u_short etype;
                    521:                int off, datasize, resid;
                    522:                struct ether_header *eh;
                    523:                struct trailer_header {
                    524:                        u_short ether_type;
                    525:                        u_short ether_residual;
                    526:                } trailer_header;
                    527:                char ether_packet[ETHERMTU+100];
                    528:                char *ep;
                    529: 
                    530:                ep = ether_packet;
                    531: 
                    532:                /*
                    533:                 * We handle trailers below:
                    534:                 * Copy ether header first, then residual data,
                    535:                 * then data. Put all this in a temporary buffer
                    536:                 * 'ether_packet' and send off to bpf. Since the
                    537:                 * system has generated this packet, we assume
                    538:                 * that all of the offsets in the packet are
                    539:                 * correct; if they're not, the system will almost
                    540:                 * certainly crash in m_copydata.
                    541:                 * We make no assumptions about how the data is
                    542:                 * arranged in the mbuf chain (i.e. how much
                    543:                 * data is in each mbuf, if mbuf clusters are
                    544:                 * used, etc.), which is why we use m_copydata
                    545:                 * to get the ether header rather than assume
                    546:                 * that this is located in the first mbuf.
                    547:                 */
                    548:                /* copy ether header */
                    549:                m_copydata(m, 0, sizeof(struct ether_header), ep);
                    550:                eh = (struct ether_header *) ep;
                    551:                ep += sizeof(struct ether_header);
                    552:                etype = ntohs(eh->ether_type);
                    553:                if (etype >= ETHERTYPE_TRAIL &&
                    554:                    etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
                    555:                        datasize = ((etype - ETHERTYPE_TRAIL) << 9);
                    556:                        off = datasize + sizeof(struct ether_header);
                    557: 
                    558:                        /* copy trailer_header into a data structure */
                    559:                        m_copydata(m, off, sizeof(struct trailer_header),
                    560:                                &trailer_header.ether_type);
                    561: 
                    562:                        /* copy residual data */
                    563:                        m_copydata(m, off+sizeof(struct trailer_header),
                    564:                                resid = ntohs(trailer_header.ether_residual) -
                    565:                                sizeof(struct trailer_header), ep);
                    566:                        ep += resid;
                    567: 
                    568:                        /* copy data */
                    569:                        m_copydata(m, sizeof(struct ether_header), datasize, ep);
                    570:                        ep += datasize;
                    571: 
                    572:                        /* restore original ether packet type */
                    573:                        eh->ether_type = trailer_header.ether_type;
                    574: 
                    575:                        bpf_tap(sc->we_bpf, ether_packet, ep - ether_packet);
                    576:                } else
                    577:                        bpf_mtap(sc->we_bpf, m);
                    578:        }
                    579: #endif
                    580: 
1.1       root      581:        /*
                    582:         * Copy the mbuf chain into the transmit buffer
                    583:         */
                    584:        buffer = sc->we_vmem_addr;
                    585:        len = 0;
                    586:        for (m0 = m; m != 0; m = m->m_next) {
                    587:                bcopy(mtod(m, caddr_t), buffer, m->m_len);
                    588:                buffer += m->m_len;
                    589:                len += m->m_len;
                    590:        }
                    591: 
                    592:        m_freem(m0);
                    593: 
                    594:        /*
                    595:         * Init transmit length registers, and set transmit start flag.
                    596:         */
                    597:        s = splhigh();
                    598:        len = MAX(len, ETHER_MIN_LEN);
                    599:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
                    600:        wecmd.cs_ps = 0;
                    601:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
                    602:        outb(sc->we_io_nic_addr + WD_P0_TBCR0, len & 0xff);
                    603:        outb(sc->we_io_nic_addr + WD_P0_TBCR1, len >> 8);
                    604:        wecmd.cs_txp = 1;
                    605:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
1.1.1.3   root      606:        sc->we_if.if_timer = 3;
1.1       root      607:        (void) splx(s);
                    608: }
                    609:  
                    610: /*
                    611:  * Ethernet interface interrupt processor
                    612:  */
                    613: weintr(unit)
                    614:        int unit;
                    615: {
                    616:        register struct we_softc *sc = &we_softc[unit];
                    617:        union we_command wecmd;
                    618:        union we_interrupt weisr;
                    619: 
                    620:  
                    621:        /* disable onboard interrupts, then get interrupt status */
                    622:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
                    623:        wecmd.cs_ps = 0;
                    624:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
                    625:        weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR);
                    626: loop:
                    627:        outb(sc->we_io_nic_addr + WD_P0_ISR, weisr.is_byte);
                    628: 
                    629:        /* transmit error */
                    630:        if (weisr.is_txe) {
                    631:                /* need to read these registers to clear status */
                    632:                sc->we_if.if_collisions +=
                    633:                    inb(sc->we_io_nic_addr + WD_P0_TBCR0);
                    634:                ++sc->we_if.if_oerrors;
                    635:        }
                    636: 
                    637:        /* receiver error */
                    638:        if (weisr.is_rxe) {
1.1.1.4 ! root      639:                ++sc->we_if.if_ierrors;
1.1       root      640:                /* need to read these registers to clear status */
1.1.1.4 ! root      641: #ifndef WEDEBUG
1.1       root      642:                (void) inb(sc->we_io_nic_addr + 0xD);
                    643:                (void) inb(sc->we_io_nic_addr + 0xE);
                    644:                (void) inb(sc->we_io_nic_addr + 0xF);
1.1.1.4 ! root      645: #else
        !           646:                sc->fae += inb(sc->we_io_nic_addr + 0xD);
        !           647:                sc->crc += inb(sc->we_io_nic_addr + 0xE);
        !           648:                sc->mpa += inb(sc->we_io_nic_addr + 0xF);
        !           649:                printf ("we%d: ierr %d fae %d crc %d mpa\n",
        !           650:                        unit, sc->fae, sc->crc, sc->mpa);
        !           651: #endif
1.1       root      652:        }
                    653: 
                    654:        /* normal transmit complete */
                    655:        if (weisr.is_ptx || weisr.is_txe)
                    656:                wetint (unit);
                    657: 
                    658:        /* normal receive notification */
                    659:        if (weisr.is_prx || weisr.is_rxe)
                    660:                werint (unit);
                    661: 
                    662:        /* try to start transmit */
                    663:        westart(&sc->we_if);
                    664: 
                    665:        /* re-enable onboard interrupts */
                    666:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
                    667:        wecmd.cs_ps = 0;
                    668:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
                    669:        outb(sc->we_io_nic_addr + WD_P0_IMR, 0xff/*WD_I_CONFIG*/);
                    670:        weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR);
                    671:        if (weisr.is_byte) goto loop;
                    672: }
                    673:  
                    674: /*
                    675:  * Ethernet interface transmit interrupt.
                    676:  */
                    677: wetint(unit)
                    678:        int unit;
                    679: {
                    680:        register struct we_softc *sc = &we_softc[unit];
                    681: 
                    682:        /*
                    683:         * Do some statistics (assume page zero of NIC mapped in)
                    684:         */
                    685:        sc->we_flags &= ~WDF_TXBUSY; 
                    686:        sc->we_if.if_timer = 0;
                    687:        ++sc->we_if.if_opackets;
                    688:        sc->we_if.if_collisions += inb(sc->we_io_nic_addr + WD_P0_TBCR0);
                    689: }
                    690:  
                    691: /*
                    692:  * Ethernet interface receiver interrupt.
                    693:  */
                    694: werint(unit)
                    695:        int unit;
                    696: {
                    697:        register struct we_softc *sc = &we_softc[unit];
                    698:        u_char bnry, curr;
                    699:        long len;
                    700:        union we_command wecmd;
                    701:        struct we_ring *wer;
                    702:  
                    703:        /*
                    704:         * Traverse the receive ring looking for packets to pass back.
                    705:         * The search is complete when we find a descriptor not in use.
                    706:         */
                    707:        wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
                    708:        wecmd.cs_ps = 0;
                    709:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
                    710:        bnry = inb(sc->we_io_nic_addr + WD_P0_BNRY);
1.1.1.4 ! root      711:        if (++bnry >= sc->we_vmem_size / WD_PAGE_SIZE)
        !           712:                bnry = WD_TXBUF_SIZE;
1.1       root      713:        wecmd.cs_ps = 1;
                    714:        outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
                    715:        curr = inb(sc->we_io_nic_addr + WD_P1_CURR);
                    716: 
                    717:        while (bnry != curr)
                    718:        {
                    719:                /* get pointer to this buffer header structure */
                    720:                wer = (struct we_ring *)(sc->we_vmem_addr + (bnry << 8));
                    721: 
                    722:                /* count includes CRC */
                    723:                len = wer->we_count - 4;
1.1.1.3   root      724:                if (len > 30 && len <= ETHERMTU+100)
1.1       root      725:                        weread(sc, (caddr_t)(wer + 1), len);
1.1.1.3   root      726:                else printf("we%d: reject - bad length %d", unit, len);
1.1       root      727: 
                    728: outofbufs:
                    729:                wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND);
                    730:                wecmd.cs_ps = 0;
                    731:                outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
                    732: 
1.1.1.4 ! root      733:                if (len > 30 && len <= ETHERMTU+100)
        !           734:                        bnry = wer->we_next_packet;
        !           735:                else bnry = curr;
        !           736: 
        !           737:                /* watch out for NIC overflow, reset Boundry if invalid */
        !           738:                if ((bnry - 1) < WD_TXBUF_SIZE) {
        !           739:                        outb(sc->we_io_nic_addr + WD_P0_BNRY,
        !           740:                                (sc->we_vmem_size / WD_PAGE_SIZE) - 1);
1.1       root      741:                        bnry = WD_TXBUF_SIZE;
1.1.1.4 ! root      742:                } else
        !           743:                        outb(sc->we_io_nic_addr + WD_P0_BNRY, bnry-1);
1.1       root      744: 
                    745:                /* refresh our copy of CURR */
                    746:                wecmd.cs_ps = 1;
                    747:                outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte);
                    748:                curr = inb(sc->we_io_nic_addr + WD_P1_CURR);
                    749:        }
                    750: }
                    751: 
                    752: /*
                    753:  * Process an ioctl request.
                    754:  */
                    755: weioctl(ifp, cmd, data)
                    756:        register struct ifnet *ifp;
                    757:        int cmd;
                    758:        caddr_t data;
                    759: {
                    760:        register struct ifaddr *ifa = (struct ifaddr *)data;
                    761:        struct we_softc *sc = &we_softc[ifp->if_unit];
                    762:        struct ifreq *ifr = (struct ifreq *)data;
                    763:        int s = splimp(), error = 0;
                    764: 
                    765: 
                    766:        switch (cmd) {
                    767: 
                    768:        case SIOCSIFADDR:
                    769:                ifp->if_flags |= IFF_UP;
                    770: 
                    771:                switch (ifa->ifa_addr->sa_family) {
                    772: #ifdef INET
                    773:                case AF_INET:
                    774:                        weinit(ifp->if_unit);   /* before arpwhohas */
                    775:                        ((struct arpcom *)ifp)->ac_ipaddr =
                    776:                                IA_SIN(ifa)->sin_addr;
                    777:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
                    778:                        break;
                    779: #endif
                    780: #ifdef NS
                    781:                case AF_NS:
                    782:                    {
                    783:                        register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
                    784: 
                    785:                        if (ns_nullhost(*ina))
1.1.1.3   root      786:                                ina->x_host = *(union ns_host *)(sc->ns_addrp);
1.1       root      787:                        else {
                    788:                                /* 
1.1.1.2   root      789:                                 * The manual says we cant change the address 
1.1       root      790:                                 * while the receiver is armed,
                    791:                                 * so reset everything
                    792:                                 */
                    793:                                ifp->if_flags &= ~IFF_RUNNING; 
                    794:                                bcopy((caddr_t)ina->x_host.c_host,
1.1.1.3   root      795:                                    (caddr_t)sc->ns_addrp, sizeof(sc->ns_addrp));
1.1       root      796:                        }
                    797:                        weinit(ifp->if_unit); /* does ne_setaddr() */
                    798:                        break;
                    799:                    }
                    800: #endif
                    801:                default:
                    802:                        weinit(ifp->if_unit);
                    803:                        break;
                    804:                }
                    805:                break;
                    806: 
                    807:        case SIOCSIFFLAGS:
                    808:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    809:                    ifp->if_flags & IFF_RUNNING) {
                    810:                        ifp->if_flags &= ~IFF_RUNNING;
                    811:                        westop(ifp->if_unit);
                    812:                } else if (ifp->if_flags & IFF_UP &&
                    813:                    (ifp->if_flags & IFF_RUNNING) == 0)
                    814:                        weinit(ifp->if_unit);
1.1.1.3   root      815: #if NBPFILTER > 0
                    816:                if (sc->we_if.if_flags & IFF_PROMISC) {
                    817:                        outb(sc->we_io_nic_addr + WD_P0_RCR,
                    818:                                 WD_R_PRO | WD_R_SEP | WD_R_AR | WD_R_CONFIG);
                    819:                } else
                    820: #endif
                    821:                        outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_CONFIG);
1.1       root      822:                break;
                    823: 
                    824: #ifdef notdef
                    825:        case SIOCGHWADDR:
                    826:                bcopy((caddr_t)sc->sc_addr, (caddr_t) &ifr->ifr_data,
                    827:                        sizeof(sc->sc_addr));
                    828:                break;
                    829: #endif
                    830: 
                    831:        default:
                    832:                error = EINVAL;
                    833:        }
                    834:        splx(s);
                    835:        return (error);
                    836: }
                    837: /*
                    838:  * set ethernet address for unit
                    839:  */
                    840: wesetaddr(physaddr, unit)
                    841:        u_char *physaddr;
                    842:        int unit;
                    843: {
                    844:        register struct we_softc *sc = &we_softc[unit];
                    845:        register int i;
                    846: 
                    847:        /*
                    848:         * Rewrite ethernet address, and then force restart of NIC
                    849:         */
                    850:        for (i = 0; i < ETHER_ADDR_LEN; i++)
                    851:                sc->we_addr[i] = physaddr[i];
                    852:        sc->we_flags &= ~WDF_RUNNING;
                    853:        weinit(unit);
                    854: }
                    855:  
1.1.1.3   root      856: #define        ringoffset(sc, eh, off, type) \
                    857:        ((type)( ((caddr_t)(eh)+(off) >= (sc)->we_vmem_end) ? \
                    858:                (((caddr_t)(eh)+(off))) - (sc)->we_vmem_end \
1.1       root      859:                + (sc)->we_vmem_ring: \
1.1.1.3   root      860:                ((caddr_t)(eh)+(off)) ))
1.1       root      861: /*
                    862:  * Pass a packet to the higher levels.
                    863:  * We deal with the trailer protocol here.
                    864:  */
                    865: weread(sc, buf, len)
                    866:        register struct we_softc *sc;
                    867:        char *buf;
                    868:        int len;
                    869: {
1.1.1.3   root      870:        caddr_t we_ring_copy();
                    871:        struct ether_header *eh;
                    872:        struct mbuf *m, *head, *we_ring_to_mbuf();
1.1       root      873:        int off, resid;
1.1.1.3   root      874:        u_short etype;
                    875:        struct trailer_header {
                    876:                u_short trail_type;
                    877:                u_short trail_residual;
                    878:        } trailer_header;
                    879: 
                    880:        ++sc->we_if.if_ipackets;
                    881: 
                    882:        /* Allocate a header mbuf */
                    883:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                    884:        if (m == 0)
                    885:                goto bad;
                    886:        m->m_pkthdr.rcvif = &sc->we_if;
                    887:        m->m_pkthdr.len = len;
                    888:        m->m_len = 0;
                    889:        head = m;
1.1       root      890: 
                    891:        eh = (struct ether_header *)buf;
                    892: 
1.1.1.3   root      893: #define EROUND ((sizeof(struct ether_header) + 3) & ~3)
                    894: #define EOFF   (EROUND - sizeof(struct ether_header))
                    895: 
                    896:        /*
                    897:         * The following assumes there is room for
                    898:         * the ether header in the header mbuf
                    899:         */
                    900:        head->m_data += EOFF;
                    901:        bcopy(buf, mtod(head, caddr_t), sizeof(struct ether_header));
                    902:        buf += sizeof(struct ether_header);
                    903:        head->m_len += sizeof(struct ether_header);
1.1       root      904:        len -= sizeof(struct ether_header);
1.1.1.3   root      905: 
                    906:        etype = ntohs((u_short)eh->ether_type);
1.1       root      907: 
                    908:        /*
1.1.1.3   root      909:         * Deal with trailer protocol:
                    910:         * If trailer protocol, calculate the datasize as 'off',
                    911:         * which is also the offset to the trailer header.
                    912:         * Set resid to the amount of packet data following the
                    913:         * trailer header.
                    914:         * Finally, copy residual data into mbuf chain.
1.1       root      915:         */
1.1.1.3   root      916:        if (etype >= ETHERTYPE_TRAIL &&
                    917:            etype < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
                    918: 
                    919:                off = (etype - ETHERTYPE_TRAIL) << 9;
                    920:                if ((off + sizeof(struct trailer_header)) > len)
                    921:                        goto bad;       /* insanity */
                    922: 
                    923:                eh->ether_type = *ringoffset(sc, buf, off, u_short *);
                    924:                resid = ntohs(*ringoffset(sc, buf, off+2, u_short *));
                    925: 
                    926:                if ((off + resid) > len) goto bad;      /* insanity */
                    927: 
                    928:                resid -= sizeof(struct trailer_header);
                    929:                if (resid < 0) goto bad;        /* insanity */
                    930: 
                    931:                m = we_ring_to_mbuf(sc, ringoffset(sc, buf, off+4, char *), head, resid);
                    932:                if (m == 0) goto bad;
                    933: 
                    934:                len = off;
                    935:                head->m_pkthdr.len -= 4; /* subtract trailer header */
                    936:        }
                    937: 
                    938:        /*
                    939:         * Pull packet off interface. Or if this was a trailer packet,
                    940:         * the data portion is appended.
                    941:         */
                    942:        m = we_ring_to_mbuf(sc, buf, m, len);
                    943:        if (m == 0) goto bad;
                    944: 
                    945: #if NBPFILTER > 0
                    946:        /*
                    947:         * Check if there's a bpf filter listening on this interface.
                    948:         * If so, hand off the raw packet to bpf. 
                    949:         */
                    950:        if (sc->we_bpf) {
                    951:                bpf_mtap(sc->we_bpf, head);
                    952:        }
                    953: 
                    954:        /*
                    955:         * Note that the interface cannot be in promiscuous mode if
                    956:         * there are no bpf listeners.  And if we are in promiscuous
                    957:         * mode, we have to check if this packet is really ours.
                    958:         *
                    959:         * XXX This test does not support multicasts.
                    960:         */
                    961:        if ((sc->we_if.if_flags & IFF_PROMISC) &&
                    962:                bcmp(eh->ether_dhost, sc->we_addr,
                    963:                        sizeof(eh->ether_dhost)) != 0 &&
                    964:                bcmp(eh->ether_dhost, etherbroadcastaddr,
                    965:                        sizeof(eh->ether_dhost)) != 0) {
                    966: 
                    967:                m_freem(head);
                    968:                return;
                    969:        }
                    970: #endif
                    971: 
                    972:        /*
                    973:         * Fix up data start offset in mbuf to point past ether header
                    974:         */
                    975:        m_adj(head, sizeof(struct ether_header));
                    976: 
                    977:        /*
                    978:         * silly ether_input routine needs 'type' in host byte order
                    979:         */
                    980:        eh->ether_type = ntohs(eh->ether_type);
                    981: 
                    982:        ether_input(&sc->we_if, eh, head);
                    983:        return;
                    984: 
                    985: bad:   if (head)
                    986:                m_freem(head);
                    987:        return;
1.1       root      988: }
                    989: 
                    990: /*
                    991:  * Supporting routines
                    992:  */
                    993: 
                    994: /*
1.1.1.3   root      995:  * Copy data from receive buffer to end of mbuf chain
                    996:  * allocate additional mbufs as needed. return pointer
                    997:  * to last mbuf in chain.
                    998:  * sc = we info
                    999:  * src = pointer in we ring buffer
                   1000:  * dst = pointer to last mbuf in mbuf chain to copy to
                   1001:  * amount = amount of data to copy
1.1       root     1002:  */
                   1003: struct mbuf *
1.1.1.3   root     1004: we_ring_to_mbuf(sc,src,dst,total_len)
1.1       root     1005:        struct we_softc *sc;
1.1.1.3   root     1006:        char *src;
                   1007:        struct mbuf *dst;
                   1008:        int total_len;
1.1       root     1009: {
1.1.1.3   root     1010:        register struct mbuf *m = dst;
1.1       root     1011: 
1.1.1.3   root     1012:        while (total_len > 0) {
                   1013:                register int amount = min(total_len, M_TRAILINGSPACE(m));
1.1       root     1014: 
1.1.1.3   root     1015:                if (amount == 0) { /* no more data in this mbuf, alloc another */
                   1016:                        /*
                   1017:                         * if there is enough data for an mbuf cluster, attempt
                   1018:                         * to allocate one of those, otherwise, a regular mbuf
                   1019:                         * will do.
                   1020:                         */ 
                   1021:                        dst = m;
1.1       root     1022:                        MGET(m, M_DONTWAIT, MT_DATA);
1.1.1.3   root     1023:                        if (m == 0)
1.1       root     1024:                                return (0);
                   1025: 
1.1.1.3   root     1026:                        if (total_len >= MINCLSIZE)
                   1027:                                MCLGET(m, M_DONTWAIT);
                   1028: 
                   1029:                        m->m_len = 0;
                   1030:                        dst->m_next = m;
                   1031:                        amount = min(total_len, M_TRAILINGSPACE(m));
1.1       root     1032:                }
1.1.1.3   root     1033: 
                   1034:                src = we_ring_copy(sc, src, mtod(m, caddr_t) + m->m_len, amount);
                   1035: 
                   1036:                m->m_len += amount;
                   1037:                total_len -= amount;
                   1038: 
1.1       root     1039:        }
1.1.1.3   root     1040:        return (m);
                   1041: }
                   1042: 
                   1043: static inline char *
                   1044: we_ring_copy(sc,src,dst,amount)
                   1045:        struct we_softc *sc;
                   1046:        char    *src;
                   1047:        char    *dst;
                   1048:        int     amount;
                   1049: {
                   1050:        int     tmp_amount;
                   1051: 
                   1052:        /* does copy wrap to lower addr in ring buffer? */
                   1053:        if (src + amount > sc->we_vmem_end) {
                   1054:                tmp_amount = sc->we_vmem_end - src;
                   1055:                bcopy(src,dst,tmp_amount); /* copy amount up to end */
                   1056:                amount -= tmp_amount;
                   1057:                src = sc->we_vmem_ring;
                   1058:                dst += tmp_amount;
                   1059:        }
                   1060: 
                   1061:        bcopy(src, dst, amount);
                   1062: 
                   1063:        return(src + amount);
1.1       root     1064: }
                   1065: #endif
1.1.1.3   root     1066: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.