Annotation of Gnu-Mach/i386/i386at/if_pc586.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  * 
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            23:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: /* 
        !            27:  *     Olivetti PC586 Mach Ethernet driver v1.0
        !            28:  *     Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989
        !            29:  *     All rights reserved.
        !            30:  *
        !            31:  */ 
        !            32: 
        !            33: /*
        !            34:   Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
        !            35: Cupertino, California.
        !            36: 
        !            37:                All Rights Reserved
        !            38: 
        !            39:   Permission to use, copy, modify, and distribute this software and
        !            40: its documentation for any purpose and without fee is hereby
        !            41: granted, provided that the above copyright notice appears in all
        !            42: copies and that both the copyright notice and this permission notice
        !            43: appear in supporting documentation, and that the name of Olivetti
        !            44: not be used in advertising or publicity pertaining to distribution
        !            45: of the software without specific, written prior permission.
        !            46: 
        !            47:   OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
        !            48: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
        !            49: IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
        !            50: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
        !            51: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
        !            52: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
        !            53: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            54: */
        !            55: 
        !            56: /*
        !            57:   Copyright 1988, 1989 by Intel Corporation, Santa Clara, California.
        !            58: 
        !            59:                All Rights Reserved
        !            60: 
        !            61: Permission to use, copy, modify, and distribute this software and
        !            62: its documentation for any purpose and without fee is hereby
        !            63: granted, provided that the above copyright notice appears in all
        !            64: copies and that both the copyright notice and this permission notice
        !            65: appear in supporting documentation, and that the name of Intel
        !            66: not be used in advertising or publicity pertaining to distribution
        !            67: of the software without specific, written prior permission.
        !            68: 
        !            69: INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
        !            70: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
        !            71: IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
        !            72: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
        !            73: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
        !            74: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
        !            75: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            76: */
        !            77: 
        !            78: /*
        !            79:  * NOTE:
        !            80:  *             by rvb:
        !            81:  *  1. The best book on the 82586 is:
        !            82:  *             LAN Components User's Manual by Intel
        !            83:  *     The copy I found was dated 1984.  This really tells you
        !            84:  *     what the state machines are doing
        !            85:  *  2. In the current design, we only do one write at a time,
        !            86:  *     though the hardware is capable of chaining and possibly
        !            87:  *     even batching.  The problem is that we only make one
        !            88:  *     transmit buffer available in sram space.
        !            89:  *  3. 
        !            90:  *  n. Board Memory Map
        !            91:        RFA/FD  0   -   227     0x228 bytes
        !            92:                 226 = 0x19 * 0x16 bytes
        !            93:        RBD      228 - 3813     0x35ec bytes
        !            94:                35e8 = 0x19 *   0x228 bytes
        !            95:                                == 0x0a bytes (bd) + 2 bytes + 21c bytes
        !            96:        CU      3814 - 3913     0x100 bytes
        !            97:        TBD     3914 - 39a3     0x90 bytes 
        !            98:                  90 = No 18 * 0x08 bytes 
        !            99:        TBUF    39a4 - 3fdd     0x63a bytes (= 1594(10))
        !           100:        SCB     3fde - 3fed     0x10 bytes
        !           101:        ISCP    3fee - 3ff5     0x08 bytes
        !           102:        SCP     3ff6 - 3fff     0x0a bytes
        !           103:  *             
        !           104:  */
        !           105: 
        !           106: /*
        !           107:  * NOTE:
        !           108:  *
        !           109:  *     Currently this driver doesn't support trailer protocols for
        !           110:  *     packets.  Once that is added, please remove this comment.
        !           111:  *
        !           112:  *     Also, some lacking material includes the DLI code.  If you
        !           113:  *     are compiling this driver with DLI set, lookout, that code
        !           114:  *     has not been looked at.
        !           115:  *
        !           116:  */
        !           117: 
        !           118: #define DEBUG
        !           119: #define IF_CNTRS       MACH
        !           120: #define        NDLI    0
        !           121: 
        !           122: #include       <pc586.h>
        !           123: 
        !           124: #ifdef MACH_KERNEL
        !           125: #include       <kern/time_out.h>
        !           126: #include       <device/device_types.h>
        !           127: #include       <device/errno.h>
        !           128: #include       <device/io_req.h>
        !           129: #include       <device/if_hdr.h>
        !           130: #include       <device/if_ether.h>
        !           131: #include       <device/net_status.h>
        !           132: #include       <device/net_io.h>
        !           133: #else  MACH_KERNEL
        !           134: #include       <sys/param.h>
        !           135: #include       <mach/machine/vm_param.h>
        !           136: #include       <sys/systm.h>
        !           137: #include       <sys/mbuf.h>
        !           138: #include       <sys/buf.h>
        !           139: #include       <sys/protosw.h>
        !           140: #include       <sys/socket.h>
        !           141: #include       <sys/vmmac.h>
        !           142: #include       <sys/ioctl.h>
        !           143: #include       <sys/errno.h>
        !           144: #include       <sys/syslog.h>
        !           145: 
        !           146: #include       <net/if.h>
        !           147: #include       <net/netisr.h>
        !           148: #include       <net/route.h>
        !           149: 
        !           150: #ifdef INET
        !           151: #include       <netinet/in.h>
        !           152: #include       <netinet/in_systm.h>
        !           153: #include       <netinet/in_var.h>
        !           154: #include       <netinet/ip.h>
        !           155: #include       <netinet/if_ether.h>
        !           156: #endif
        !           157: 
        !           158: #ifdef NS
        !           159: #include       <netns/ns.h>
        !           160: #include       <netns/ns_if.h>
        !           161: #endif
        !           162: 
        !           163: #if    DLI
        !           164: #include       <net/dli_var.h>
        !           165: struct dli_var de_dlv[NDE];
        !           166: #endif DLI
        !           167: #endif MACH_KERNEL
        !           168: 
        !           169: #include       <i386/ipl.h>
        !           170: #include       <mach/vm_param.h>
        !           171: #include       <vm/vm_kern.h>
        !           172: #include       <chips/busses.h>
        !           173: #include       <i386at/if_pc586.h>
        !           174: 
        !           175: #define        SPLNET  spl6
        !           176: #if    __STDC__
        !           177: #define CMD(x, y, unit) *(u_short *)(pc_softc[unit].prom + OFFSET_ ## x) = (u_short) (y)
        !           178: #else  __STDC__
        !           179: #define CMD(x, y, unit) *(u_short *)(pc_softc[unit].prom + OFFSET_/**/x) = (u_short) (y)
        !           180: #endif __STDC__
        !           181: 
        !           182: #define pc586chatt(unit)  CMD(CHANATT, 0x0001, unit)
        !           183: #define pc586inton(unit)  CMD(INTENAB, CMD_1,  unit)
        !           184: #define pc586intoff(unit) CMD(INTENAB, CMD_0,  unit)
        !           185: 
        !           186: int    pc586probe();
        !           187: void   pc586attach();
        !           188: int    pc586intr(), pc586init(), pc586output(), pc586ioctl(), pc586reset();
        !           189: int    pc586watch(), pc586rcv(), pc586xmt(), pc586bldcu();
        !           190: int    pc586diag(), pc586config();
        !           191: char   *pc586bldru();
        !           192: char   *ram_to_ptr();
        !           193: u_short        ptr_to_ram();
        !           194: 
        !           195: static vm_offset_t pc586_std[NPC586] = { 0 };
        !           196: static struct bus_device *pc586_info[NPC586];
        !           197: struct bus_driver      pcdriver = 
        !           198:        {pc586probe, 0, pc586attach, 0, pc586_std, "pc", pc586_info, 0, 0, 0};
        !           199: 
        !           200: char   t_packet[ETHERMTU + sizeof(struct ether_header) + sizeof(long)];
        !           201: int    xmt_watch = 0;
        !           202: 
        !           203: typedef struct { 
        !           204: #ifdef MACH_KERNEL
        !           205:        struct  ifnet   ds_if;          /* generic interface header */
        !           206:        u_char  ds_addr[6];             /* Ethernet hardware address */
        !           207: #else  MACH_KERNEL
        !           208:        struct  arpcom  pc586_ac;
        !           209: #define        ds_if   pc586_ac.ac_if
        !           210: #define        ds_addr pc586_ac.ac_enaddr
        !           211: #endif MACH_KERNEL
        !           212:        int     flags;
        !           213:         int     seated;
        !           214:         int     timer;
        !           215:         int     open;
        !           216:         fd_t    *begin_fd;
        !           217:        fd_t    *end_fd;
        !           218:        rbd_t   *end_rbd;
        !           219:        char    *prom;
        !           220:        char    *sram;
        !           221:        int     tbusy;
        !           222:        short   mode;
        !           223: } pc_softc_t;
        !           224: pc_softc_t     pc_softc[NPC586];
        !           225: 
        !           226: struct pc586_cntrs {
        !           227:        struct {
        !           228:                u_int xmt, xmti;
        !           229:                u_int defer;
        !           230:                u_int busy;
        !           231:                u_int sleaze, intrinsic, intrinsic_count;
        !           232:                u_int chain;
        !           233:        } xmt; 
        !           234:        struct {
        !           235:                u_int rcv;
        !           236:                u_int ovw;
        !           237:                u_int crc;
        !           238:                u_int frame;
        !           239:                u_int rscerrs, ovrnerrs;
        !           240:                u_int partial, bad_chain, fill;
        !           241:        } rcv;
        !           242:        u_int watch;
        !           243: } pc586_cntrs[NPC586];
        !           244: 
        !           245: 
        !           246: #ifdef IF_CNTRS
        !           247: int pc586_narp = 1, pc586_arp = 0;
        !           248: int pc586_ein[32], pc586_eout[32]; 
        !           249: int pc586_lin[128/8], pc586_lout[128/8]; 
        !           250: static
        !           251: log_2(no)
        !           252: unsigned long no;
        !           253: {
        !           254:        return ({ unsigned long _temp__;
        !           255:                asm("bsr %1, %0; jne 0f; xorl %0, %0; 0:" :
        !           256:                    "=r" (_temp__) : "a" (no));
        !           257:                _temp__;});
        !           258: }
        !           259: #endif IF_CNTRS
        !           260: 
        !           261: /*
        !           262:  * pc586probe:
        !           263:  *
        !           264:  *     This function "probes" or checks for the pc586 board on the bus to see
        !           265:  *     if it is there.  As far as I can tell, the best break between this
        !           266:  *     routine and the attach code is to simply determine whether the board
        !           267:  *     is configured in properly.  Currently my approach to this is to write
        !           268:  *     and read a word from the SRAM on the board being probed.  If the word
        !           269:  *     comes back properly then we assume the board is there.  The config
        !           270:  *     code expects to see a successful return from the probe routine before
        !           271:  *     attach will be called.
        !           272:  *
        !           273:  * input       : address device is mapped to, and unit # being checked
        !           274:  * output      : a '1' is returned if the board exists, and a 0 otherwise
        !           275:  *
        !           276:  */
        !           277: pc586probe(port, dev)
        !           278: struct bus_device      *dev;
        !           279: {
        !           280:        caddr_t         addr = (caddr_t)dev->address;
        !           281:        int             unit = dev->unit;
        !           282:        int             len = round_page(0x4000);
        !           283:        int             sram_len = round_page(0x4000);
        !           284:        extern          vm_offset_t phys_last_addr;
        !           285:        int             i;
        !           286:        volatile char   *b_prom;
        !           287:        volatile char   *b_sram;
        !           288:        volatile u_short*t_ps;
        !           289: 
        !           290:        if ((unit < 0) || (unit > NPC586)) {
        !           291:                printf("pc%d: board out of range [0..%d]\n",
        !           292:                        unit, NPC586);
        !           293:                return(0);
        !           294:        }
        !           295:        if ((addr > (caddr_t)0x100000) && (addr < (caddr_t)phys_last_addr))
        !           296:                return 0;
        !           297: 
        !           298:        if (kmem_alloc_pageable(kernel_map, (vm_offset_t *) &b_prom, len)
        !           299:                                                        != KERN_SUCCESS) {
        !           300:                printf("pc%d: can not allocate memory for prom.\n", unit);
        !           301:                return 0;
        !           302:        }
        !           303:        if (kmem_alloc_pageable(kernel_map, (vm_offset_t *) &b_sram, sram_len)
        !           304:                                                        != KERN_SUCCESS) {
        !           305:                printf("pc%d: can not allocate memory for sram.\n", unit);
        !           306:                return 0;
        !           307:        }
        !           308:        (void)pmap_map(b_prom, (vm_offset_t)addr, 
        !           309:                        (vm_offset_t)addr+len, 
        !           310:                        VM_PROT_READ | VM_PROT_WRITE);
        !           311:        if ((int)addr > 0x100000)                       /* stupid hardware */
        !           312:                addr += EXTENDED_ADDR;
        !           313:        addr += 0x4000;                                 /* sram space */
        !           314:        (void)pmap_map(b_sram, (vm_offset_t)addr, 
        !           315:                        (vm_offset_t)addr+sram_len, 
        !           316:                        VM_PROT_READ | VM_PROT_WRITE);
        !           317: 
        !           318:        *(b_prom + OFFSET_RESET) = 1;
        !           319:        { int i; for (i = 0; i < 1000; i++);    /* 4 clocks at 6Mhz */}
        !           320:        *(b_prom + OFFSET_RESET) = 0;
        !           321:        t_ps = (u_short *)(b_sram + OFFSET_SCB);
        !           322:        *(t_ps) = (u_short)0x5a5a;
        !           323:        if (*(t_ps) != (u_short)0x5a5a) {
        !           324:                kmem_free(kernel_map, b_prom, len);
        !           325:                kmem_free(kernel_map, b_sram, sram_len);
        !           326:                return(0);
        !           327:        }
        !           328:         t_ps = (u_short *)(b_prom +  + OFFSET_PROM);
        !           329: #define ETHER0 0x00
        !           330: #define ETHER1 0xaa
        !           331: #define ETHER2 0x00
        !           332:        if ((t_ps[0]&0xff) == ETHER0 &&
        !           333:            (t_ps[1]&0xff) == ETHER1 &&
        !           334:            (t_ps[2]&0xff) == ETHER2)
        !           335:                pc_softc[unit].seated = TRUE;
        !           336: #undef ETHER0
        !           337: #undef ETHER1
        !           338: #undef ETHER2
        !           339: #define ETHER0 0x00
        !           340: #define ETHER1 0x00
        !           341: #define ETHER2 0x1c
        !           342:        if ((t_ps[0]&0xff) == ETHER0 ||
        !           343:            (t_ps[1]&0xff) == ETHER1 ||
        !           344:            (t_ps[2]&0xff) == ETHER2)
        !           345:                pc_softc[unit].seated = TRUE;
        !           346: #undef ETHER0
        !           347: #undef ETHER1
        !           348: #undef ETHER2
        !           349:        if (pc_softc[unit].seated != TRUE) {
        !           350:                kmem_free(kernel_map, b_prom, len);
        !           351:                kmem_free(kernel_map, b_sram, sram_len);
        !           352:                return(0);
        !           353:        }
        !           354:        (volatile char *)pc_softc[unit].prom = (volatile char *)b_prom;
        !           355:        (volatile char *)pc_softc[unit].sram = (volatile char *)b_sram;
        !           356:        return(1);
        !           357: }
        !           358: 
        !           359: /*
        !           360:  * pc586attach:
        !           361:  *
        !           362:  *     This function attaches a PC586 board to the "system".  The rest of
        !           363:  *     runtime structures are initialized here (this routine is called after
        !           364:  *     a successful probe of the board).  Once the ethernet address is read
        !           365:  *     and stored, the board's ifnet structure is attached and readied.
        !           366:  *
        !           367:  * input       : bus_device structure setup in autoconfig
        !           368:  * output      : board structs and ifnet is setup
        !           369:  *
        !           370:  */
        !           371: void pc586attach(dev)
        !           372:        struct bus_device       *dev;
        !           373: {
        !           374:        struct  ifnet   *ifp;
        !           375:        u_char          *addr_p;
        !           376:        u_short         *b_addr;
        !           377:        u_char          unit = (u_char)dev->unit;       
        !           378:        pc_softc_t      *sp = &pc_softc[unit];
        !           379:        volatile scb_t  *scb_p;
        !           380: 
        !           381:        take_dev_irq(dev);
        !           382:        printf(", port = %x, spl = %d, pic = %d. ",
        !           383:                dev->address, dev->sysdep, dev->sysdep1);
        !           384: 
        !           385:        sp->timer = -1;
        !           386:        sp->flags = 0;
        !           387:        sp->mode = 0;
        !           388:        sp->open = 0;
        !           389:        CMD(RESET, CMD_1, unit);
        !           390:        { int i; for (i = 0; i < 1000; i++);    /* 4 clocks at 6Mhz */}
        !           391:        CMD(RESET, CMD_0, unit);
        !           392:        b_addr = (u_short *)(sp->prom + OFFSET_PROM);
        !           393:        addr_p = (u_char *)sp->ds_addr;
        !           394:        addr_p[0] = b_addr[0];
        !           395:        addr_p[1] = b_addr[1];
        !           396:        addr_p[2] = b_addr[2];
        !           397:        addr_p[3] = b_addr[3];
        !           398:        addr_p[4] = b_addr[4];
        !           399:        addr_p[5] = b_addr[5];
        !           400:        printf("ethernet id [%x:%x:%x:%x:%x:%x]",
        !           401:                addr_p[0], addr_p[1], addr_p[2],
        !           402:                addr_p[3], addr_p[4], addr_p[5]);
        !           403: 
        !           404:        scb_p = (volatile scb_t *)(sp->sram + OFFSET_SCB);
        !           405:        scb_p->scb_crcerrs = 0;                 /* initialize counters */
        !           406:        scb_p->scb_alnerrs = 0;
        !           407:        scb_p->scb_rscerrs = 0;
        !           408:        scb_p->scb_ovrnerrs = 0;
        !           409: 
        !           410:        ifp = &(sp->ds_if);
        !           411:        ifp->if_unit = unit;
        !           412:        ifp->if_mtu = ETHERMTU;
        !           413:        ifp->if_flags = IFF_BROADCAST;
        !           414: #ifdef MACH_KERNEL
        !           415:        ifp->if_header_size = sizeof(struct ether_header);
        !           416:        ifp->if_header_format = HDR_ETHERNET;
        !           417:        ifp->if_address_size = 6;
        !           418:        ifp->if_address = (char *)&sp->ds_addr[0];
        !           419:        if_init_queues(ifp);
        !           420: #else  MACH_KERNEL
        !           421:        ifp->if_name = "pc";
        !           422:        ifp->if_init = pc586init;
        !           423:        ifp->if_output = pc586output;
        !           424:        ifp->if_ioctl = pc586ioctl;
        !           425:        ifp->if_reset = pc586reset;
        !           426:        ifp->if_next = NULL;
        !           427:        if_attach(ifp);
        !           428: #endif MACH_KERNEL
        !           429: }
        !           430: 
        !           431: /*
        !           432:  * pc586reset:
        !           433:  *
        !           434:  *     This routine is in part an entry point for the "if" code.  Since most 
        !           435:  *     of the actual initialization has already (we hope already) been done
        !           436:  *     by calling pc586attach().
        !           437:  *
        !           438:  * input       : unit number or board number to reset
        !           439:  * output      : board is reset
        !           440:  *
        !           441:  */
        !           442: pc586reset(unit)
        !           443: int    unit;
        !           444: {
        !           445:        pc_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
        !           446:        pc_softc[unit].flags &= ~(DSF_LOCK|DSF_RUNNING);
        !           447:        return(pc586init(unit));
        !           448: 
        !           449: }
        !           450: 
        !           451: /*
        !           452:  * pc586init:
        !           453:  *
        !           454:  *     Another routine that interfaces the "if" layer to this driver.  
        !           455:  *     Simply resets the structures that are used by "upper layers".  
        !           456:  *     As well as calling pc586hwrst that does reset the pc586 board.
        !           457:  *
        !           458:  * input       : board number
        !           459:  * output      : structures (if structs) and board are reset
        !           460:  *
        !           461:  */    
        !           462: pc586init(unit)
        !           463: int    unit;
        !           464: {
        !           465:        struct  ifnet   *ifp;
        !           466:        int             stat;
        !           467:        spl_t           oldpri;
        !           468: 
        !           469:        ifp = &(pc_softc[unit].ds_if);
        !           470: #ifdef MACH_KERNEL
        !           471: #else  MACH_KERNEL
        !           472:        if (ifp->if_addrlist == (struct ifaddr *)0) {
        !           473:                return;
        !           474:        }
        !           475: #endif MACH_KERNEL
        !           476:        oldpri = SPLNET();
        !           477:        if ((stat = pc586hwrst(unit)) == TRUE) {
        !           478: #ifdef MACH_KERNEL
        !           479: #undef HZ
        !           480: #define HZ hz
        !           481: #endif MACH_KERNEL
        !           482:                timeout(pc586watch, &(ifp->if_unit), 5*HZ);
        !           483:                pc_softc[unit].timer = 5;
        !           484: 
        !           485:                pc_softc[unit].ds_if.if_flags |= IFF_RUNNING;
        !           486:                pc_softc[unit].flags |= DSF_RUNNING;
        !           487:                pc_softc[unit].tbusy = 0;
        !           488:                pc586start(unit);
        !           489: #if    DLI
        !           490:                dli_init();
        !           491: #endif DLI
        !           492:        } else
        !           493:                printf("pc%d init(): trouble resetting board.\n", unit);
        !           494:        splx(oldpri);
        !           495:        return(stat);
        !           496: }
        !           497: 
        !           498: #ifdef MACH_KERNEL
        !           499: /*ARGSUSED*/
        !           500: pc586open(dev, flag)
        !           501:        dev_t   dev;
        !           502:        int     flag;
        !           503: {
        !           504:        register int    unit;
        !           505:        pc_softc_t      *sp;
        !           506: 
        !           507:        unit = minor(dev);      /* XXX */
        !           508:        if (unit < 0 || unit >= NPC586 || !pc_softc[unit].seated)
        !           509:            return (ENXIO);
        !           510: 
        !           511:        pc_softc[unit].ds_if.if_flags |= IFF_UP;
        !           512:        pc586init(unit);
        !           513:        return (0);
        !           514: }
        !           515: #endif MACH_KERNEL
        !           516: 
        !           517: /*
        !           518:  * pc586start:
        !           519:  *
        !           520:  *     This is yet another interface routine that simply tries to output a
        !           521:  *     in an mbuf after a reset.
        !           522:  *
        !           523:  * input       : board number
        !           524:  * output      : stuff sent to board if any there
        !           525:  *
        !           526:  */
        !           527: pc586start(unit)
        !           528: int    unit;
        !           529: {
        !           530: #ifdef MACH_KERNEL
        !           531:        io_req_t        m;
        !           532: #else  MACH_KERNEL
        !           533:        struct  mbuf            *m;
        !           534: #endif MACH_KERNEL
        !           535:        struct  ifnet           *ifp;
        !           536:        register pc_softc_t     *is = &pc_softc[unit];
        !           537:        volatile scb_t          *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB);
        !           538: 
        !           539:        if (is->tbusy) {
        !           540:                if (!(scb_p->scb_status & 0x0700)) { /* ! IDLE */
        !           541:                        is->tbusy = 0;
        !           542:                        pc586_cntrs[unit].xmt.busy++;
        !           543:                        /*
        !           544:                         * This is probably just a race.  The xmt'r is just
        !           545:                         * became idle but WE have masked interrupts so ...
        !           546:                         */
        !           547:                        if (xmt_watch) printf("!!");
        !           548:                } else
        !           549:                        return;
        !           550:        }
        !           551: 
        !           552:        ifp = &(pc_softc[unit].ds_if);
        !           553:        IF_DEQUEUE(&ifp->if_snd, m);
        !           554: #ifdef MACH_KERNEL
        !           555:        if (m != 0)
        !           556: #else  MACH_KERNEL
        !           557:        if (m != (struct mbuf *)0) 
        !           558: #endif MACH_KERNEL
        !           559:        {
        !           560:                is->tbusy++;
        !           561:                pc586_cntrs[unit].xmt.xmt++;
        !           562:                pc586xmt(unit, m);
        !           563:        }
        !           564:        return;
        !           565: }
        !           566: 
        !           567: /*
        !           568:  * pc586read:
        !           569:  *
        !           570:  *     This routine does the actual copy of data (including ethernet header
        !           571:  *     structure) from the pc586 to an mbuf chain that will be passed up
        !           572:  *     to the "if" (network interface) layer.  NOTE:  we currently
        !           573:  *     don't handle trailer protocols, so if that is needed, it will
        !           574:  *     (at least in part) be added here.  For simplicities sake, this
        !           575:  *     routine copies the receive buffers from the board into a local (stack)
        !           576:  *     buffer until the frame has been copied from the board.  Once in
        !           577:  *     the local buffer, the contents are copied to an mbuf chain that
        !           578:  *     is then enqueued onto the appropriate "if" queue.
        !           579:  *
        !           580:  * input       : board number, and an frame descriptor pointer
        !           581:  * output      : the packet is put into an mbuf chain, and passed up
        !           582:  * assumes     : if any errors occur, packet is "dropped on the floor"
        !           583:  *
        !           584:  */
        !           585: pc586read(unit, fd_p)
        !           586: int    unit;
        !           587: fd_t   *fd_p;
        !           588: {
        !           589:        register pc_softc_t     *is = &pc_softc[unit];
        !           590:        register struct ifnet   *ifp = &is->ds_if;
        !           591:        struct  ether_header    eh;
        !           592: #ifdef MACH_KERNEL
        !           593:        ipc_kmsg_t      new_kmsg;
        !           594:        struct ether_header *ehp;
        !           595:        struct packet_header *pkt;
        !           596:        char    *dp;
        !           597: #else  MACH_KERNEL
        !           598:        struct  mbuf            *m, *tm;
        !           599: #endif MACH_KERNEL
        !           600:        rbd_t                   *rbd_p;
        !           601:        u_char                  *buffer_p;
        !           602:        u_char                  *mb_p;
        !           603:        u_short                 mlen, len, clen;
        !           604:        u_short                 bytes_in_msg, bytes_in_mbuf, bytes;
        !           605: 
        !           606: 
        !           607:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
        !           608:                printf("pc%d read(): board is not running.\n", ifp->if_unit);
        !           609:                pc586intoff(ifp->if_unit);
        !           610:        }
        !           611:        pc586_cntrs[unit].rcv.rcv++;
        !           612: #ifdef MACH_KERNEL
        !           613:        new_kmsg = net_kmsg_get();
        !           614:        if (new_kmsg == IKM_NULL) {
        !           615:            /*
        !           616:             * Drop the received packet.
        !           617:             */
        !           618:            is->ds_if.if_rcvdrops++;
        !           619: 
        !           620:            /*
        !           621:             * not only do we want to return, we need to drop the packet on
        !           622:             * the floor to clear the interrupt.
        !           623:             */
        !           624:            return 1;
        !           625:        }
        !           626:        ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]);
        !           627:        pkt = (struct packet_header *)(&net_kmsg(new_kmsg)->packet[0]);
        !           628: 
        !           629:        /*
        !           630:         * Get ether header.
        !           631:         */
        !           632:        ehp->ether_type = fd_p->length;
        !           633:        len = sizeof(struct ether_header);
        !           634:        bcopy16(fd_p->source, ehp->ether_shost, ETHER_ADD_SIZE);
        !           635:        bcopy16(fd_p->destination, ehp->ether_dhost, ETHER_ADD_SIZE);
        !           636: 
        !           637:        /*
        !           638:         * Get packet body.
        !           639:         */
        !           640:        dp = (char *)(pkt + 1);
        !           641: 
        !           642:        rbd_p = (rbd_t *)ram_to_ptr(fd_p->rbd_offset, unit);
        !           643:        if (rbd_p == 0) {
        !           644:            printf("pc%d read(): Invalid buffer\n", unit);
        !           645:            if (pc586hwrst(unit) != TRUE) {
        !           646:                printf("pc%d read(): hwrst trouble.\n", unit);
        !           647:            }
        !           648:            net_kmsg_put(new_kmsg);
        !           649:            return 0;
        !           650:        }
        !           651: 
        !           652:        do {
        !           653:            buffer_p = (u_char *)(pc_softc[unit].sram + rbd_p->buffer_addr);
        !           654:            bytes_in_msg = rbd_p->status & RBD_SW_COUNT;
        !           655:            bcopy16((u_short *)buffer_p,
        !           656:                       (u_short *)dp,
        !           657:                       (bytes_in_msg + 1) & ~1);        /* but we know it's even */
        !           658:            len += bytes_in_msg;
        !           659:            dp += bytes_in_msg;
        !           660:            if (rbd_p->status & RBD_SW_EOF)
        !           661:                break;
        !           662:            rbd_p = (rbd_t *)ram_to_ptr(rbd_p->next_rbd_offset, unit);
        !           663:        } while ((int) rbd_p);
        !           664: 
        !           665:        pkt->type = ehp->ether_type;
        !           666:        pkt->length =
        !           667:                len - sizeof(struct ether_header)
        !           668:                    + sizeof(struct packet_header);
        !           669: 
        !           670:        /*
        !           671:         * Send the packet to the network module.
        !           672:         */
        !           673:        net_packet(ifp, new_kmsg, pkt->length, ethernet_priority(new_kmsg));
        !           674:        return 1;
        !           675: #else  MACH_KERNEL
        !           676:        eh.ether_type = ntohs(fd_p->length);
        !           677:        bcopy16(fd_p->source, eh.ether_shost, ETHER_ADD_SIZE);
        !           678:        bcopy16(fd_p->destination, eh.ether_dhost, ETHER_ADD_SIZE);
        !           679: 
        !           680:        if ((rbd_p =(rbd_t *)ram_to_ptr(fd_p->rbd_offset, unit))== (rbd_t *)NULL) {
        !           681:                printf("pc%d read(): Invalid buffer\n", unit);
        !           682:                if (pc586hwrst(unit) != TRUE) {
        !           683:                        printf("pc%d read(): hwrst trouble.\n", unit);
        !           684:                }
        !           685:                return 0;
        !           686:        }
        !           687: 
        !           688:        bytes_in_msg = rbd_p->status & RBD_SW_COUNT;
        !           689:        buffer_p = (u_char *)(pc_softc[unit].sram + rbd_p->buffer_addr);
        !           690:        MGET(m, M_DONTWAIT, MT_DATA);
        !           691:        tm = m;
        !           692:        if (m == (struct mbuf *)0) {
        !           693:                /*
        !           694:                 * not only do we want to return, we need to drop the packet on
        !           695:                 * the floor to clear the interrupt.
        !           696:                 *
        !           697:                 */
        !           698:                printf("pc%d read(): No mbuf 1st\n", unit);
        !           699:                if (pc586hwrst(unit) != TRUE) {
        !           700:                        pc586intoff(unit);
        !           701:                        printf("pc%d read(): hwrst trouble.\n", unit);
        !           702:                        pc_softc[unit].timer = 0;
        !           703:                }
        !           704:                return 0;
        !           705:        }
        !           706: m->m_next = (struct mbuf *) 0;
        !           707:        m->m_len = MLEN;
        !           708:        if (bytes_in_msg > 2 * MLEN - sizeof (struct ifnet **)) {
        !           709:                MCLGET(m);
        !           710:        }
        !           711:        /*
        !           712:         * first mbuf in the packet must contain a pointer to the
        !           713:         * ifnet structure.  other mbufs that follow and make up
        !           714:         * the packet do not need this pointer in the mbuf.
        !           715:         *
        !           716:         */
        !           717:        *(mtod(tm, struct ifnet **)) = ifp;
        !           718:        mlen = sizeof (struct ifnet **);
        !           719:        clen = mlen;
        !           720:        bytes_in_mbuf = m->m_len - sizeof(struct ifnet **);
        !           721:        mb_p = mtod(tm, u_char *) + sizeof (struct ifnet **);
        !           722:        bytes = min(bytes_in_mbuf, bytes_in_msg);
        !           723:        do {
        !           724:                if (bytes & 1)
        !           725:                        len = bytes + 1;
        !           726:                else
        !           727:                        len = bytes;
        !           728:                bcopy16(buffer_p, mb_p, len);
        !           729:                clen += bytes;
        !           730:                mlen += bytes;
        !           731: 
        !           732:                if (!(bytes_in_mbuf -= bytes)) {
        !           733:                        MGET(tm->m_next, M_DONTWAIT, MT_DATA);
        !           734:                        tm = tm->m_next;
        !           735:                        if (tm == (struct mbuf *)0) {
        !           736:                                m_freem(m);
        !           737:                                printf("pc%d read(): No mbuf nth\n", unit);
        !           738:                                if (pc586hwrst(unit) != TRUE) {
        !           739:                                        pc586intoff(unit);
        !           740:                                        printf("pc%d read(): hwrst trouble.\n", unit);
        !           741:                                        pc_softc[unit].timer = 0;
        !           742:                                }
        !           743:                                return 0;
        !           744:                        }
        !           745:                        mlen = 0;
        !           746:                        tm->m_len = MLEN;
        !           747:                        bytes_in_mbuf = MLEN;
        !           748:                        mb_p = mtod(tm, u_char *);
        !           749:                } else
        !           750:                        mb_p += bytes;
        !           751: 
        !           752:                if (!(bytes_in_msg  -= bytes)) {
        !           753:                        if (rbd_p->status & RBD_SW_EOF ||
        !           754:                            (rbd_p = (rbd_t *)ram_to_ptr(rbd_p->next_rbd_offset, unit)) ==
        !           755:                             NULL) {
        !           756:                                tm->m_len = mlen;
        !           757:                                break;
        !           758:                        } else {
        !           759:                                bytes_in_msg = rbd_p->status & RBD_SW_COUNT;
        !           760:                                buffer_p = (u_char *)(pc_softc[unit].sram + rbd_p->buffer_addr);
        !           761:                        }
        !           762:                } else
        !           763:                        buffer_p += bytes;
        !           764: 
        !           765:                bytes = min(bytes_in_mbuf, bytes_in_msg);
        !           766:        } while(1);
        !           767: #ifdef IF_CNTRS
        !           768: /*     clen -= (sizeof (struct ifnet **)
        !           769:        clen += 4 /* crc */;
        !           770:        clen += sizeof (struct ether_header);
        !           771:        pc586_ein[log_2(clen)]++;
        !           772:        if (clen < 128) pc586_lin[clen>>3]++;
        !           773: 
        !           774:        if (eh.ether_type == ETHERTYPE_ARP) {
        !           775:                pc586_arp++;
        !           776:                if (pc586_narp) {
        !           777:                        pc586_ein[log_2(clen)]--;
        !           778:                        if (clen < 128) pc586_lin[clen>>3]--;
        !           779:                }
        !           780:        }
        !           781: #endif IF_CNTRS
        !           782:        /*
        !           783:         * received packet is now in a chain of mbuf's.  next step is
        !           784:         * to pass the packet upwards.
        !           785:         *
        !           786:         */
        !           787:        pc586send_packet_up(m, &eh, is);
        !           788:        return 1;
        !           789: #endif MACH_KERNEL
        !           790: }
        !           791: 
        !           792: /*
        !           793:  * Send a packet composed of an mbuf chain to the higher levels
        !           794:  *
        !           795:  */
        !           796: #ifndef        MACH_KERNEL
        !           797: pc586send_packet_up(m, eh, is)
        !           798: struct mbuf *m;
        !           799: struct ether_header *eh;
        !           800: pc_softc_t *is;
        !           801: {
        !           802:        register struct ifqueue *inq;
        !           803:        spl_t                   opri;
        !           804: 
        !           805:        switch (eh->ether_type) {
        !           806: #ifdef INET
        !           807:        case ETHERTYPE_IP:
        !           808:                schednetisr(NETISR_IP);
        !           809:                inq = &ipintrq;
        !           810:                break;
        !           811:        case ETHERTYPE_ARP:
        !           812:                arpinput(&is->pc586_ac, m);
        !           813:                return;
        !           814: #endif
        !           815: #ifdef NS
        !           816:        case ETHERTYPE_NS:
        !           817:                schednetisr(NETISR_NS);
        !           818:                inq = &nsintrq;
        !           819:                break;
        !           820: #endif
        !           821:        default:
        !           822: #if    DLI
        !           823:                {
        !           824:                        eh.ether_type = htons(eh.ether_type);
        !           825:                        dli_input(m,eh.ether_type,&eh.ether_shost[0],
        !           826:                        &de_dlv[ds->ds_if.if_unit], &eh);
        !           827:                }
        !           828: #else  DLI
        !           829:                m_freem(m);
        !           830: #endif DLI
        !           831:                return;
        !           832:        }
        !           833:        opri = SPLNET();
        !           834:        if (IF_QFULL(inq)) {
        !           835:                IF_DROP(inq);
        !           836:                splx(opri);
        !           837:                m_freem(m);
        !           838:                return;
        !           839:        }
        !           840:        IF_ENQUEUE(inq, m);
        !           841:        splx(opri);
        !           842:        return;
        !           843: }
        !           844: #endif MACH_KERNEL
        !           845: 
        !           846: #ifdef MACH_KERNEL
        !           847: pc586output(dev, ior)
        !           848:        dev_t   dev;
        !           849:        io_req_t ior;
        !           850: {
        !           851:        register int    unit;
        !           852: 
        !           853:        unit = minor(dev);      /* XXX */
        !           854:        if (unit < 0 || unit >= NPC586 || !pc_softc[unit].seated)
        !           855:            return (ENXIO);
        !           856: 
        !           857:        return (net_write(&pc_softc[unit].ds_if, pc586start, ior));
        !           858: }
        !           859: 
        !           860: pc586setinput(dev, receive_port, priority, filter, filter_count)
        !           861:        dev_t           dev;
        !           862:        mach_port_t     receive_port;
        !           863:        int             priority;
        !           864:        filter_t        filter[];
        !           865:        unsigned int    filter_count;
        !           866: {
        !           867:        register int unit = minor(dev);
        !           868:        if (unit < 0 || unit >= NPC586 || !pc_softc[unit].seated)
        !           869:            return (ENXIO);
        !           870: 
        !           871:        return (net_set_filter(&pc_softc[unit].ds_if,
        !           872:                        receive_port, priority,
        !           873:                        filter, filter_count));
        !           874: }
        !           875: #else  MACH_KERNEL
        !           876: /*
        !           877:  * pc586output:
        !           878:  *
        !           879:  *     This routine is called by the "if" layer to output a packet to
        !           880:  *     the network.  This code resolves the local ethernet address, and
        !           881:  *     puts it into the mbuf if there is room.  If not, then a new mbuf
        !           882:  *     is allocated with the header information and precedes the data
        !           883:  *     to be transmitted.  The routines that actually transmit the
        !           884:  *     data (pc586xmt()) expect the ethernet structure to precede
        !           885:  *     the data in the mbuf.  This information is required by the
        !           886:  *     82586's transfer command segment, and thus mbuf's cannot
        !           887:  *     be simply "slammed" out onto the network.
        !           888:  *
        !           889:  * input:      ifnet structure pointer, an mbuf with data, and address
        !           890:  *             to be resolved
        !           891:  * output:     mbuf is updated to hold enet address, or a new mbuf
        !           892:  *             with the address is added
        !           893:  *
        !           894:  */
        !           895: pc586output(ifp, m0, dst)
        !           896: struct ifnet   *ifp;
        !           897: struct mbuf    *m0;
        !           898: struct sockaddr *dst;
        !           899: {
        !           900:        register pc_softc_t             *is = &pc_softc[ifp->if_unit];
        !           901:        register struct mbuf            *m = m0;
        !           902:        int                             type, error;
        !           903:        spl_t                           opri;
        !           904:        u_char                          edst[6];
        !           905:        struct in_addr                  idst;
        !           906:        register struct ether_header    *eh;
        !           907:        register int                    off;
        !           908:        int                             usetrailers;
        !           909: 
        !           910:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
        !           911:                printf("pc%d output(): board is not running.\n", ifp->if_unit);
        !           912:                pc586intoff(ifp->if_unit);
        !           913:                error = ENETDOWN;
        !           914:                goto bad;
        !           915:        }
        !           916:        switch (dst->sa_family) {
        !           917: 
        !           918: #ifdef INET
        !           919:        case AF_INET:
        !           920:                idst = ((struct sockaddr_in *)dst)->sin_addr;
        !           921:                if (!arpresolve(&is->pc586_ac, m, &idst, edst, &usetrailers)){
        !           922:                        return (0);     /* if not yet resolved */
        !           923:                }
        !           924:                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
        !           925: 
        !           926:                if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
        !           927:                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
        !           928:                        type = ETHERTYPE_TRAIL + (off>>9);
        !           929:                        m->m_off -= 2 * sizeof (u_short);
        !           930:                        m->m_len += 2 * sizeof (u_short);
        !           931:                        *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
        !           932:                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
        !           933:                        goto gottrailertype;
        !           934:                }
        !           935:                type = ETHERTYPE_IP;
        !           936:                off = 0;
        !           937:                goto gottype;
        !           938: #endif
        !           939: #ifdef NS
        !           940:        case AF_NS:
        !           941:                type = ETHERTYPE_NS;
        !           942:                bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
        !           943:                (caddr_t)edst, sizeof (edst));
        !           944:                off = 0;
        !           945:                goto gottype;
        !           946: #endif
        !           947: 
        !           948: #if    DLI
        !           949:        case AF_DLI:
        !           950:                if (m->m_len < sizeof(struct ether_header))
        !           951:                {
        !           952:                        error = EMSGSIZE;
        !           953:                        goto bad;
        !           954:                }
        !           955:                eh = mtod(m, struct ether_header *);
        !           956:                bcopy(dst->sa_data, (caddr_t)eh->ether_dhost, 
        !           957:                                                sizeof (eh->ether_dhost));
        !           958:                goto gotheader;
        !           959: #endif DLI
        !           960: 
        !           961:        case AF_UNSPEC:
        !           962:                eh = (struct ether_header *)dst->sa_data;
        !           963:                bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
        !           964:                type = eh->ether_type;
        !           965:                goto gottype;
        !           966: 
        !           967:        default:
        !           968:                printf("pc%d output(): can't handle af%d\n",
        !           969:                        ifp->if_unit, dst->sa_family);
        !           970:                error = EAFNOSUPPORT;
        !           971:                goto bad;
        !           972:        }
        !           973: 
        !           974: gottrailertype:
        !           975:        /*
        !           976:         * Packet to be sent as trailer: move first packet
        !           977:         * (control information) to end of chain.
        !           978:         */
        !           979:        while (m->m_next)
        !           980:                m = m->m_next;
        !           981:        m->m_next = m0;
        !           982:        m = m0->m_next;
        !           983:        m0->m_next = 0;
        !           984:        m0 = m;
        !           985: 
        !           986: gottype:
        !           987:        /*
        !           988:         * Add local net header.  If no space in first mbuf,
        !           989:         * allocate another.
        !           990:         */
        !           991:        if (m->m_off > MMAXOFF ||
        !           992:            MMINOFF + sizeof (struct ether_header) > m->m_off) {
        !           993:                m = m_get(M_DONTWAIT, MT_HEADER);
        !           994:                if (m == 0) {
        !           995:                        error = ENOBUFS;
        !           996:                        goto bad;
        !           997:                }
        !           998:                m->m_next = m0;
        !           999:                m->m_off = MMINOFF;
        !          1000:                m->m_len = sizeof (struct ether_header);
        !          1001:        } else {
        !          1002:                m->m_off -= sizeof (struct ether_header);
        !          1003:                m->m_len += sizeof (struct ether_header);
        !          1004:        }
        !          1005:        eh = mtod(m, struct ether_header *);
        !          1006:        eh->ether_type = htons((u_short)type);
        !          1007:        bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
        !          1008:        bcopy((caddr_t)is->ds_addr,(caddr_t)eh->ether_shost, sizeof(edst));
        !          1009: #if    DLI
        !          1010: gotheader:
        !          1011: #endif DLI
        !          1012: 
        !          1013:        /*
        !          1014:         * Queue message on interface, and start output if interface
        !          1015:         * not yet active.
        !          1016:         */
        !          1017:        opri = SPLNET();
        !          1018:        if (IF_QFULL(&ifp->if_snd)) {
        !          1019:                IF_DROP(&ifp->if_snd);
        !          1020:                splx(opri);
        !          1021:                m_freem(m);
        !          1022:                return (ENOBUFS);
        !          1023:        }
        !          1024:        IF_ENQUEUE(&ifp->if_snd, m);
        !          1025:        /*
        !          1026:         * Some action needs to be added here for checking whether the
        !          1027:         * board is already transmitting.  If it is, we don't want to
        !          1028:         * start it up (ie call pc586start()).  We will attempt to send
        !          1029:         * packets that are queued up after an interrupt occurs.  Some
        !          1030:         * flag checking action has to happen here and/or in the start
        !          1031:         * routine.  This note is here to remind me that some thought
        !          1032:         * is needed and there is a potential problem here.
        !          1033:         *
        !          1034:         */
        !          1035:        pc586start(ifp->if_unit);
        !          1036:        splx(opri);
        !          1037:        return (0);
        !          1038: bad:
        !          1039:        m_freem(m0);
        !          1040:        return (error);
        !          1041: }
        !          1042: #endif MACH_KERNEL
        !          1043: 
        !          1044: #ifdef MACH_KERNEL
        !          1045: pc586getstat(dev, flavor, status, count)
        !          1046:        dev_t   dev;
        !          1047:        int     flavor;
        !          1048:        dev_status_t    status;         /* pointer to OUT array */
        !          1049:        unsigned int    *count;         /* out */
        !          1050: {
        !          1051:        register int    unit = minor(dev);
        !          1052:        register pc_softc_t     *sp;
        !          1053: 
        !          1054:        if (unit < 0 || unit >= NPC586 || !pc_softc[unit].seated)
        !          1055:            return (ENXIO);
        !          1056: 
        !          1057:        sp = &pc_softc[unit];
        !          1058:        return (net_getstat(&sp->ds_if, flavor, status, count));
        !          1059: }
        !          1060: 
        !          1061: pc586setstat(dev, flavor, status, count)
        !          1062:        dev_t   dev;
        !          1063:        int     flavor;
        !          1064:        dev_status_t    status;
        !          1065:        unsigned int    count;
        !          1066: {
        !          1067:        register int    unit = minor(dev);
        !          1068:        register pc_softc_t     *sp;
        !          1069: 
        !          1070:        if (unit < 0 || unit >= NPC586 || !pc_softc[unit].seated)
        !          1071:            return (ENXIO);
        !          1072: 
        !          1073:        sp = &pc_softc[unit];
        !          1074: 
        !          1075:        switch (flavor) {
        !          1076:            case NET_STATUS:
        !          1077:            {
        !          1078:                /*
        !          1079:                 * All we can change are flags, and not many of those.
        !          1080:                 */
        !          1081:                register struct net_status *ns = (struct net_status *)status;
        !          1082:                int     mode = 0;
        !          1083: 
        !          1084:                if (count < NET_STATUS_COUNT)
        !          1085:                    return (D_INVALID_OPERATION);
        !          1086: 
        !          1087:                if (ns->flags & IFF_ALLMULTI)
        !          1088:                    mode |= MOD_ENAL;
        !          1089:                if (ns->flags & IFF_PROMISC)
        !          1090:                    mode |= MOD_PROM;
        !          1091: 
        !          1092:                /*
        !          1093:                 * Force a complete reset if the receive mode changes
        !          1094:                 * so that these take effect immediately.
        !          1095:                 */
        !          1096:                if (sp->mode != mode) {
        !          1097:                    sp->mode = mode;
        !          1098:                    if (sp->flags & DSF_RUNNING) {
        !          1099:                        sp->flags &= ~(DSF_LOCK|DSF_RUNNING);
        !          1100:                        pc586init(unit);
        !          1101:                    }
        !          1102:                }
        !          1103:                break;
        !          1104:            }
        !          1105: 
        !          1106:            default:
        !          1107:                return (D_INVALID_OPERATION);
        !          1108:        }
        !          1109:        return (D_SUCCESS);
        !          1110: 
        !          1111: }
        !          1112: #else  MACH_KERNEL
        !          1113: /*
        !          1114:  * pc586ioctl:
        !          1115:  *
        !          1116:  *     This routine processes an ioctl request from the "if" layer
        !          1117:  *     above.
        !          1118:  *
        !          1119:  * input       : pointer the appropriate "if" struct, command, and data
        !          1120:  * output      : based on command appropriate action is taken on the
        !          1121:  *               pc586 board(s) or related structures
        !          1122:  * return      : error is returned containing exit conditions
        !          1123:  *
        !          1124:  */
        !          1125: pc586ioctl(ifp, cmd, data)
        !          1126: struct ifnet   *ifp;
        !          1127: int    cmd;
        !          1128: caddr_t        data;
        !          1129: {
        !          1130:        register struct ifaddr  *ifa = (struct ifaddr *)data;
        !          1131:        int                     unit = ifp->if_unit;
        !          1132:        register pc_softc_t     *is = &pc_softc[unit];
        !          1133:        short                   mode = 0;
        !          1134:        int                     error = 0;
        !          1135:        spl_t                   opri;
        !          1136: 
        !          1137:        opri = SPLNET();
        !          1138:        switch (cmd) {
        !          1139:        case SIOCSIFADDR:
        !          1140:                ifp->if_flags |= IFF_UP;
        !          1141:                pc586init(unit);
        !          1142:                switch (ifa->ifa_addr.sa_family) {
        !          1143: #ifdef INET
        !          1144:                case AF_INET:
        !          1145:                        ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr;
        !          1146:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
        !          1147:                        break;
        !          1148: #endif
        !          1149: #ifdef NS
        !          1150:                case AF_NS:
        !          1151:                        {
        !          1152:                        register struct ns_addr *ina = 
        !          1153:                        &(IA_SNS(ifa)->sns_addr);
        !          1154:                        if (ns_nullhost(*ina))
        !          1155:                                ina->x_host = *(union ns_host *)(ds->ds_addr);
        !          1156:                        else
        !          1157:                                pc586setaddr(ina->x_host.c_host, unit);
        !          1158:                        break;
        !          1159:                        }
        !          1160: #endif
        !          1161:                }
        !          1162:                break;
        !          1163:        case SIOCSIFFLAGS:
        !          1164:                if (ifp->if_flags & IFF_ALLMULTI)
        !          1165:                        mode |= MOD_ENAL;
        !          1166:                if (ifp->if_flags & IFF_PROMISC)
        !          1167:                        mode |= MOD_PROM;
        !          1168:                /*
        !          1169:                 * force a complete reset if the receive multicast/
        !          1170:                 * promiscuous mode changes so that these take 
        !          1171:                 * effect immediately.
        !          1172:                 *
        !          1173:                 */
        !          1174:                if (is->mode != mode) {
        !          1175:                        is->mode = mode;
        !          1176:                        if (is->flags & DSF_RUNNING) {
        !          1177:                                is->flags &= ~(DSF_LOCK|DSF_RUNNING);
        !          1178:                                pc586init(unit);
        !          1179:                        }
        !          1180:                }
        !          1181:                if ((ifp->if_flags & IFF_UP) == 0 && is->flags & DSF_RUNNING) {
        !          1182:                        printf("pc%d ioctl(): board is not running\n", unit);
        !          1183:                        is->flags &= ~(DSF_LOCK | DSF_RUNNING);
        !          1184:                        is->timer = -1;
        !          1185:                        pc586intoff(unit);
        !          1186:                } else if (ifp->if_flags & IFF_UP && (is->flags & DSF_RUNNING) == 0) {
        !          1187:                        pc586init(unit);
        !          1188:                }
        !          1189:                break;
        !          1190: #ifdef IF_CNTRS
        !          1191:        case SIOCCIFCNTRS:
        !          1192:                if (!suser()) {
        !          1193:                        error = EPERM;
        !          1194:                        break;
        !          1195:                }
        !          1196:                bzero((caddr_t)pc586_ein, sizeof (pc586_ein));
        !          1197:                bzero((caddr_t)pc586_eout, sizeof (pc586_eout));
        !          1198:                bzero((caddr_t)pc586_lin, sizeof (pc586_lin));
        !          1199:                bzero((caddr_t)pc586_lout, sizeof (pc586_lout));
        !          1200:                bzero((caddr_t)&pc586_arp, sizeof (int));
        !          1201:                bzero((caddr_t)&pc586_cntrs, sizeof (pc586_cntrs));
        !          1202:                break;
        !          1203: #endif IF_CNTRS
        !          1204:        default:
        !          1205:                error = EINVAL;
        !          1206:        }
        !          1207:        splx(opri);
        !          1208:        return (error);
        !          1209: }
        !          1210: #endif MACH_KERNEL
        !          1211: 
        !          1212: /*
        !          1213:  * pc586hwrst:
        !          1214:  *
        !          1215:  *     This routine resets the pc586 board that corresponds to the 
        !          1216:  *     board number passed in.
        !          1217:  *
        !          1218:  * input       : board number to do a hardware reset
        !          1219:  * output      : board is reset
        !          1220:  *
        !          1221:  */
        !          1222: pc586hwrst(unit)
        !          1223: int unit;
        !          1224: {
        !          1225:        CMD(CHANATT, CMD_0, unit);
        !          1226:        CMD(RESET, CMD_1, unit);
        !          1227:        { int i; for (i = 0; i < 1000; i++);    /* 4 clocks at 6Mhz */}
        !          1228:        CMD(RESET,CMD_0, unit);
        !          1229: 
        !          1230: /*
        !          1231:  *     for (i = 0; i < 1000000; i++); 
        !          1232:  *     with this loop above and with the reset toggle also looping to
        !          1233:  *     1000000.  We don't see the reset behaving as advertised.  DOES
        !          1234:  *     IT HAPPEN AT ALL.  In particular, NORMODE, ENABLE, and XFER
        !          1235:  *     should all be zero and they have not changed at all.
        !          1236:  */
        !          1237:        CMD(INTENAB, CMD_0, unit);
        !          1238:        CMD(NORMMODE, CMD_0, unit);
        !          1239:        CMD(XFERMODE, CMD_1, unit);
        !          1240: 
        !          1241:        pc586bldcu(unit);
        !          1242: 
        !          1243:        if (pc586diag(unit) == FALSE)
        !          1244:                return(FALSE);
        !          1245: 
        !          1246:        if (pc586config(unit) == FALSE)
        !          1247:                return(FALSE);
        !          1248:        /* 
        !          1249:         * insert code for loopback test here
        !          1250:         *
        !          1251:         */
        !          1252:        pc586rustrt(unit);
        !          1253: 
        !          1254:        pc586inton(unit);
        !          1255:        CMD(NORMMODE, CMD_1, unit);
        !          1256:        return(TRUE);
        !          1257: }
        !          1258: 
        !          1259: /*
        !          1260:  * pc586watch():
        !          1261:  *
        !          1262:  *     This routine is the watchdog timer routine for the pc586 chip.  If
        !          1263:  *     chip wedges, this routine will fire and cause a board reset and
        !          1264:  *     begin again.
        !          1265:  *
        !          1266:  * input       : which board is timing out
        !          1267:  * output      : potential board reset if wedged
        !          1268:  *
        !          1269:  */
        !          1270: int watch_dead = 0;
        !          1271: pc586watch(b_ptr)
        !          1272: caddr_t        b_ptr;
        !          1273: {
        !          1274:        spl_t   opri;
        !          1275:        int     unit = *b_ptr;
        !          1276: 
        !          1277:        if ((pc_softc[unit].ds_if.if_flags & IFF_UP) == 0)  {
        !          1278:                return;
        !          1279:        }
        !          1280:        if (pc_softc[unit].timer == -1) {
        !          1281:                timeout(pc586watch, b_ptr, 5*HZ);
        !          1282:                return;
        !          1283:        }
        !          1284:        if (--pc_softc[unit].timer != -1) {
        !          1285:                timeout(pc586watch, b_ptr, 1*HZ);
        !          1286:                return;
        !          1287:        }
        !          1288: 
        !          1289:        opri = SPLNET();
        !          1290: #ifdef notdef
        !          1291:        printf("pc%d watch(): 6sec timeout no %d\n", unit, ++watch_dead);
        !          1292: #endif notdef
        !          1293:        pc586_cntrs[unit].watch++;
        !          1294:        if (pc586hwrst(unit) != TRUE) {
        !          1295:                printf("pc%d watch(): hwrst trouble.\n", unit);
        !          1296:                pc_softc[unit].timer = 0;
        !          1297:        } else {
        !          1298:                timeout(pc586watch, b_ptr, 1*HZ);
        !          1299:                pc_softc[unit].timer = 5;
        !          1300:        }
        !          1301:        splx(opri);
        !          1302: }
        !          1303: 
        !          1304: /*
        !          1305:  * pc586intr:
        !          1306:  *
        !          1307:  *     This function is the interrupt handler for the pc586 ethernet
        !          1308:  *     board.  This routine will be called whenever either a packet
        !          1309:  *     is received, or a packet has successfully been transfered and
        !          1310:  *     the unit is ready to transmit another packet.
        !          1311:  *
        !          1312:  * input       : board number that interrupted
        !          1313:  * output      : either a packet is received, or a packet is transfered
        !          1314:  *
        !          1315:  */
        !          1316: pc586intr(unit)
        !          1317: int unit;
        !          1318: {
        !          1319:        volatile scb_t  *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB);
        !          1320:        volatile ac_t   *cb_p  = (volatile ac_t *)(pc_softc[unit].sram + OFFSET_CU);
        !          1321:        int             next, x;
        !          1322:        int             i;
        !          1323:        u_short         int_type;
        !          1324: 
        !          1325:        if (pc_softc[unit].seated == FALSE) { 
        !          1326:                printf("pc%d intr(): board not seated\n", unit);
        !          1327:                return(-1);
        !          1328:        }
        !          1329: 
        !          1330:        while ((int_type = (scb_p->scb_status & SCB_SW_INT)) != 0) {
        !          1331:                pc586ack(unit);
        !          1332:                if (int_type & SCB_SW_FR) {
        !          1333:                        pc586rcv(unit);
        !          1334:                        watch_dead=0;
        !          1335:                }
        !          1336:                if (int_type & SCB_SW_RNR) {
        !          1337:                        pc586_cntrs[unit].rcv.ovw++;
        !          1338: #ifdef notdef
        !          1339:                        printf("pc%d intr(): receiver overrun! begin_fd = %x\n",
        !          1340:                                unit, pc_softc[unit].begin_fd);
        !          1341: #endif notdef
        !          1342:                        pc586rustrt(unit);
        !          1343:                }
        !          1344:                if (int_type & SCB_SW_CNA) {
        !          1345:                        /*
        !          1346:                         * At present, we don't care about CNA's.  We
        !          1347:                         * believe they are a side effect of XMT.
        !          1348:                         */
        !          1349:                }
        !          1350:                if (int_type & SCB_SW_CX) {
        !          1351:                        /*
        !          1352:                         * At present, we only request Interrupt for
        !          1353:                         * XMT.
        !          1354:                         */
        !          1355:                        if ((!(cb_p->ac_status & AC_SW_OK)) ||
        !          1356:                            (cb_p->ac_status & (0xfff^TC_SQE))) {
        !          1357:                                if (cb_p->ac_status & TC_DEFER) {
        !          1358:                                        if (xmt_watch) printf("DF");
        !          1359:                                        pc586_cntrs[unit].xmt.defer++;
        !          1360:                                } else if (cb_p->ac_status & (TC_COLLISION|0xf)) {
        !          1361:                                        if (xmt_watch) printf("%x",cb_p->ac_status & 0xf);
        !          1362:                                } else if (xmt_watch) 
        !          1363:                                        printf("pc%d XMT: %x %x\n",
        !          1364:                                                unit, cb_p->ac_status, cb_p->ac_command);
        !          1365:                        }
        !          1366:                        pc586_cntrs[unit].xmt.xmti++;
        !          1367:                        pc_softc[unit].tbusy = 0;
        !          1368:                        pc586start(unit);
        !          1369:                }
        !          1370:                pc_softc[unit].timer = 5;
        !          1371:        }
        !          1372:        return(0);
        !          1373: }
        !          1374: 
        !          1375: /*
        !          1376:  * pc586rcv:
        !          1377:  *
        !          1378:  *     This routine is called by the interrupt handler to initiate a
        !          1379:  *     packet transfer from the board to the "if" layer above this
        !          1380:  *     driver.  This routine checks if a buffer has been successfully
        !          1381:  *     received by the pc586.  If so, the routine pc586read is called
        !          1382:  *     to do the actual transfer of the board data (including the
        !          1383:  *     ethernet header) into a packet (consisting of an mbuf chain).
        !          1384:  *
        !          1385:  * input       : number of the board to check
        !          1386:  * output      : if a packet is available, it is "sent up"
        !          1387:  *
        !          1388:  */
        !          1389: pc586rcv(unit)
        !          1390: int    unit;
        !          1391: {
        !          1392:        fd_t    *fd_p;
        !          1393: 
        !          1394:        for (fd_p = pc_softc[unit].begin_fd; fd_p != (fd_t *)NULL;
        !          1395:             fd_p = pc_softc[unit].begin_fd) {
        !          1396:                if (fd_p->status == 0xffff || fd_p->rbd_offset == 0xffff) {
        !          1397:                        if (pc586hwrst(unit) != TRUE)
        !          1398:                                printf("pc%d rcv(): hwrst ffff trouble.\n",
        !          1399:                                        unit);
        !          1400:                        return;
        !          1401:                } else if (fd_p->status & AC_SW_C) {
        !          1402:                        fd_t *bfd = (fd_t *)ram_to_ptr(fd_p->link_offset, unit);
        !          1403: 
        !          1404:                        if (fd_p->status == (RFD_DONE|RFD_RSC)) {
        !          1405:                                        /* lost one */;
        !          1406: #ifdef notdef
        !          1407:                                printf("pc%d RCV: RSC %x\n",
        !          1408:                                        unit, fd_p->status);
        !          1409: #endif notdef
        !          1410:                                pc586_cntrs[unit].rcv.partial++;
        !          1411:                        } else if (!(fd_p->status & RFD_OK))
        !          1412:                                printf("pc%d RCV: !OK %x\n",
        !          1413:                                        unit, fd_p->status);
        !          1414:                        else if (fd_p->status & 0xfff)
        !          1415:                                printf("pc%d RCV: ERRs %x\n",
        !          1416:                                        unit, fd_p->status);
        !          1417:                        else
        !          1418:                                if (!pc586read(unit, fd_p))
        !          1419:                                        return;
        !          1420:                        if (!pc586requeue(unit, fd_p)) {        /* abort on chain error */
        !          1421:                                if (pc586hwrst(unit) != TRUE)
        !          1422:                                        printf("pc%d rcv(): hwrst trouble.\n", unit);
        !          1423:                                return;
        !          1424:                        }
        !          1425:                        pc_softc[unit].begin_fd = bfd;
        !          1426:                } else
        !          1427:                        break;
        !          1428:        }
        !          1429:        return;
        !          1430: }
        !          1431: 
        !          1432: /*
        !          1433:  * pc586requeue:
        !          1434:  *
        !          1435:  *     This routine puts rbd's used in the last receive back onto the
        !          1436:  *     free list for the next receive.
        !          1437:  *
        !          1438:  */
        !          1439: pc586requeue(unit, fd_p)
        !          1440: int    unit;
        !          1441: fd_t   *fd_p;
        !          1442: {
        !          1443:        rbd_t   *l_rbdp;
        !          1444:        rbd_t   *f_rbdp;
        !          1445: 
        !          1446: #ifndef        REQUEUE_DBG
        !          1447:        if (bad_rbd_chain(fd_p->rbd_offset, unit))
        !          1448:                return 0;
        !          1449: #endif REQUEUE_DBG
        !          1450:        f_rbdp = (rbd_t *)ram_to_ptr(fd_p->rbd_offset, unit);
        !          1451:        if (f_rbdp != NULL) {
        !          1452:                l_rbdp = f_rbdp;
        !          1453:                while ( (!(l_rbdp->status & RBD_SW_EOF)) && 
        !          1454:                        (l_rbdp->next_rbd_offset != 0xffff)) 
        !          1455:                {
        !          1456:                        l_rbdp->status = 0;
        !          1457:                        l_rbdp = (rbd_t *)ram_to_ptr(l_rbdp->next_rbd_offset,
        !          1458:                                                     unit);
        !          1459:                }
        !          1460:                l_rbdp->next_rbd_offset = PC586NULL;
        !          1461:                l_rbdp->status = 0;
        !          1462:                l_rbdp->size |= AC_CW_EL;
        !          1463:                pc_softc[unit].end_rbd->next_rbd_offset = 
        !          1464:                        ptr_to_ram((char *)f_rbdp, unit);
        !          1465:                pc_softc[unit].end_rbd->size &= ~AC_CW_EL;
        !          1466:                pc_softc[unit].end_rbd= l_rbdp;
        !          1467:        }
        !          1468: 
        !          1469:        fd_p->status = 0;
        !          1470:        fd_p->command = AC_CW_EL;
        !          1471:        fd_p->link_offset = PC586NULL;
        !          1472:        fd_p->rbd_offset = PC586NULL;
        !          1473: 
        !          1474:        pc_softc[unit].end_fd->link_offset = ptr_to_ram((char *)fd_p, unit);
        !          1475:        pc_softc[unit].end_fd->command = 0;
        !          1476:        pc_softc[unit].end_fd = fd_p;
        !          1477: 
        !          1478:        return 1;
        !          1479: }
        !          1480: 
        !          1481: /*
        !          1482:  * pc586xmt:
        !          1483:  *
        !          1484:  *     This routine fills in the appropriate registers and memory
        !          1485:  *     locations on the PC586 board and starts the board off on
        !          1486:  *     the transmit.
        !          1487:  *
        !          1488:  * input       : board number of interest, and a pointer to the mbuf
        !          1489:  * output      : board memory and registers are set for xfer and attention
        !          1490:  *
        !          1491:  */
        !          1492: #ifdef DEBUG
        !          1493: int xmt_debug = 0;
        !          1494: #endif DEBUG
        !          1495: pc586xmt(unit, m)
        !          1496: int    unit;
        !          1497: #ifdef MACH_KERNEL
        !          1498: io_req_t       m;
        !          1499: #else  MACH_KERNEL
        !          1500: struct mbuf    *m;
        !          1501: #endif MACH_KERNEL
        !          1502: {
        !          1503:        pc_softc_t                      *is = &pc_softc[unit];
        !          1504:        register u_char                 *xmtdata_p = (u_char *)(is->sram + OFFSET_TBUF);
        !          1505:        register u_short                *xmtshort_p;
        !          1506: #ifdef MACH_KERNEL
        !          1507:        register struct ether_header    *eh_p = (struct ether_header *)m->io_data;
        !          1508: #else  MACH_KERNEL
        !          1509:        struct  mbuf                    *tm_p = m;
        !          1510:        register struct ether_header    *eh_p = mtod(m, struct ether_header *);
        !          1511:        u_char                          *mb_p = mtod(m, u_char *) + sizeof(struct ether_header);
        !          1512:        u_short                         count = m->m_len - sizeof(struct ether_header);
        !          1513: #endif MACH_KERNEL
        !          1514:        volatile scb_t                  *scb_p = (volatile scb_t *)(is->sram + OFFSET_SCB);
        !          1515:        volatile ac_t                   *cb_p = (volatile ac_t *)(is->sram + OFFSET_CU);
        !          1516:        tbd_t                           *tbd_p = (tbd_t *)(is->sram + OFFSET_TBD);
        !          1517:        u_short                         tbd = OFFSET_TBD;
        !          1518:        u_short                         len, clen = 0;
        !          1519: 
        !          1520:        cb_p->ac_status = 0;
        !          1521:        cb_p->ac_command = (AC_CW_EL|AC_TRANSMIT|AC_CW_I);
        !          1522:        cb_p->ac_link_offset = PC586NULL;
        !          1523:        cb_p->cmd.transmit.tbd_offset = OFFSET_TBD;
        !          1524: 
        !          1525:        bcopy16(eh_p->ether_dhost, cb_p->cmd.transmit.dest_addr, ETHER_ADD_SIZE);
        !          1526:        cb_p->cmd.transmit.length = (u_short)(eh_p->ether_type);
        !          1527: 
        !          1528: #ifndef        MACH_KERNEL
        !          1529: #ifdef DEBUG
        !          1530:        if (xmt_debug)
        !          1531:                printf("XMT    mbuf: L%d @%x ", count, mb_p);
        !          1532: #endif DEBUG
        !          1533: #endif MACH_KERNEL
        !          1534:        tbd_p->act_count = 0;
        !          1535:        tbd_p->buffer_base = 0;
        !          1536:        tbd_p->buffer_addr = ptr_to_ram(xmtdata_p, unit);
        !          1537: #ifdef MACH_KERNEL
        !          1538:        { int Rlen, Llen;
        !          1539:            clen = m->io_count - sizeof(struct ether_header);
        !          1540:            Llen = clen & 1;
        !          1541:            Rlen = ((int)(m->io_data + sizeof(struct ether_header))) & 1;
        !          1542: 
        !          1543:            bcopy16(m->io_data + sizeof(struct ether_header) - Rlen,
        !          1544:                    xmtdata_p,
        !          1545:                    clen + (Rlen + Llen) );
        !          1546:            xmtdata_p += clen + Llen;
        !          1547:            tbd_p->act_count = clen;
        !          1548:            tbd_p->buffer_addr += Rlen;
        !          1549:        }
        !          1550: #else  MACH_KERNEL
        !          1551:        do {
        !          1552:                if (count) {
        !          1553:                        if (clen + count > ETHERMTU)
        !          1554:                                break;
        !          1555:                        if (count & 1)
        !          1556:                                len = count + 1;
        !          1557:                        else
        !          1558:                                len = count;
        !          1559:                        bcopy16(mb_p, xmtdata_p, len);
        !          1560:                        clen += count;
        !          1561:                        tbd_p->act_count += count;
        !          1562:                        xmtdata_p += len;
        !          1563:                        if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
        !          1564:                                break;
        !          1565:                        if (count & 1) {
        !          1566:                                /* go to the next descriptor */
        !          1567:                                tbd_p++->next_tbd_offset = (tbd += sizeof (tbd_t));
        !          1568:                                tbd_p->act_count = 0;
        !          1569:                                tbd_p->buffer_base = 0;
        !          1570:                                tbd_p->buffer_addr = ptr_to_ram(xmtdata_p, unit);
        !          1571:                                /* at the end -> coallesce remaining mbufs */
        !          1572:                                if (tbd == OFFSET_TBD + (N_TBD-1) * sizeof (tbd_t)) {
        !          1573:                                        pc586sftwsleaze(&count, &mb_p, &tm_p, unit);
        !          1574:                                        continue;
        !          1575:                                }
        !          1576:                                /* next mbuf short -> coallesce as needed */
        !          1577:                                if ( (tm_p->m_next == (struct mbuf *) 0) ||
        !          1578: #define HDW_THRESHOLD 55
        !          1579:                                      tm_p->m_len > HDW_THRESHOLD)
        !          1580:                                        /* ok */;
        !          1581:                                else {
        !          1582:                                        pc586hdwsleaze(&count, &mb_p, &tm_p, unit);
        !          1583:                                        continue;
        !          1584:                                }
        !          1585:                        }
        !          1586:                } else if ((tm_p = tm_p->m_next) == (struct mbuf *)0)
        !          1587:                        break;
        !          1588:                count = tm_p->m_len;
        !          1589:                mb_p = mtod(tm_p, u_char *);
        !          1590: #ifdef DEBUG
        !          1591:                if (xmt_debug)
        !          1592:                        printf("mbuf+ L%d @%x ", count, mb_p);
        !          1593: #endif DEBUG
        !          1594:        } while (1);
        !          1595: #endif MACH_KERNEL
        !          1596: #ifdef DEBUG
        !          1597:        if (xmt_debug)
        !          1598:                printf("CLEN = %d\n", clen);
        !          1599: #endif DEBUG
        !          1600:        if (clen < ETHERMIN) {
        !          1601:                tbd_p->act_count += ETHERMIN - clen;
        !          1602:                for (xmtshort_p = (u_short *)xmtdata_p;
        !          1603:                     clen < ETHERMIN;
        !          1604:                     clen += 2) *xmtshort_p++ = 0;
        !          1605:        }
        !          1606:        tbd_p->act_count |= TBD_SW_EOF;
        !          1607:        tbd_p->next_tbd_offset = PC586NULL;
        !          1608: #ifdef IF_CNTRS
        !          1609:        clen += sizeof (struct ether_header) + 4 /* crc */;
        !          1610:        pc586_eout[log_2(clen)]++;
        !          1611:        if (clen < 128)  pc586_lout[clen>>3]++;
        !          1612: #endif IF_CNTRS
        !          1613: #ifdef DEBUG
        !          1614:        if (xmt_debug) {
        !          1615:                pc586tbd(unit);
        !          1616:                printf("\n");
        !          1617:        }
        !          1618: #endif DEBUG
        !          1619: 
        !          1620:        while (scb_p->scb_command) ;
        !          1621:        scb_p->scb_command = SCB_CU_STRT;
        !          1622:        pc586chatt(unit);
        !          1623: 
        !          1624: #ifdef MACH_KERNEL
        !          1625:        iodone(m);
        !          1626: #else  MACH_KERNEL
        !          1627:        for (count=0; ((count < 6) && (eh_p->ether_dhost[count] == 0xff)); count++)  ;
        !          1628:        if (count == 6) {
        !          1629:                pc586send_packet_up(m, eh_p, is);
        !          1630:        } else
        !          1631:                m_freem(m);
        !          1632: #endif MACH_KERNEL
        !          1633:        return;
        !          1634: }
        !          1635: 
        !          1636: /*
        !          1637:  * pc586bldcu:
        !          1638:  *
        !          1639:  *     This function builds up the command unit structures.  It inits
        !          1640:  *     the scp, iscp, scb, cb, tbd, and tbuf.
        !          1641:  *
        !          1642:  */
        !          1643: pc586bldcu(unit)
        !          1644: {
        !          1645:        char            *sram = pc_softc[unit].sram;
        !          1646:        scp_t           *scp_p = (scp_t *)(sram + OFFSET_SCP);
        !          1647:        iscp_t          *iscp_p = (iscp_t *)(sram + OFFSET_ISCP);
        !          1648:        volatile scb_t  *scb_p = (volatile scb_t *)(sram + OFFSET_SCB);
        !          1649:        volatile ac_t   *cb_p = (volatile ac_t *)(sram + OFFSET_CU);
        !          1650:        tbd_t           *tbd_p = (tbd_t *)(sram + OFFSET_TBD);
        !          1651:        int             i;
        !          1652: 
        !          1653:        scp_p->scp_sysbus = 0;
        !          1654:        scp_p->scp_iscp = OFFSET_ISCP;
        !          1655:        scp_p->scp_iscp_base = 0;
        !          1656: 
        !          1657:        iscp_p->iscp_busy = 1;
        !          1658:        iscp_p->iscp_scb_offset = OFFSET_SCB;
        !          1659:        iscp_p->iscp_scb = 0;
        !          1660:        iscp_p->iscp_scb_base = 0;
        !          1661: 
        !          1662:        pc586_cntrs[unit].rcv.crc += scb_p->scb_crcerrs;
        !          1663:        pc586_cntrs[unit].rcv.frame += scb_p->scb_alnerrs;
        !          1664:        pc586_cntrs[unit].rcv.rscerrs += scb_p->scb_rscerrs;
        !          1665:        pc586_cntrs[unit].rcv.ovrnerrs += scb_p->scb_ovrnerrs;
        !          1666:        scb_p->scb_status = 0;
        !          1667:        scb_p->scb_command = 0;
        !          1668:        scb_p->scb_cbl_offset = OFFSET_CU;
        !          1669:        scb_p->scb_rfa_offset = OFFSET_RU;
        !          1670:        scb_p->scb_crcerrs = 0;
        !          1671:        scb_p->scb_alnerrs = 0;
        !          1672:        scb_p->scb_rscerrs = 0;
        !          1673:        scb_p->scb_ovrnerrs = 0;
        !          1674: 
        !          1675:        scb_p->scb_command = SCB_RESET;
        !          1676:        pc586chatt(unit);
        !          1677:        for (i = 1000000; iscp_p->iscp_busy && (i-- > 0); );
        !          1678:        if (!i) printf("pc%d bldcu(): iscp_busy timeout.\n", unit);
        !          1679:        for (i = STATUS_TRIES; i-- > 0; ) {
        !          1680:                if (scb_p->scb_status == (SCB_SW_CX|SCB_SW_CNA)) 
        !          1681:                        break;
        !          1682:        }
        !          1683:        if (!i)
        !          1684:                printf("pc%d bldcu(): not ready after reset.\n", unit);
        !          1685:        pc586ack(unit);
        !          1686: 
        !          1687:        cb_p->ac_status = 0;
        !          1688:        cb_p->ac_command = AC_CW_EL;
        !          1689:        cb_p->ac_link_offset = OFFSET_CU;
        !          1690: 
        !          1691:        tbd_p->act_count = 0;
        !          1692:        tbd_p->next_tbd_offset = PC586NULL;
        !          1693:        tbd_p->buffer_addr = 0;
        !          1694:        tbd_p->buffer_base = 0;
        !          1695:        return;
        !          1696: }
        !          1697: 
        !          1698: /*
        !          1699:  * pc586bldru:
        !          1700:  *
        !          1701:  *     This function builds the linear linked lists of fd's and
        !          1702:  *     rbd's.  Based on page 4-32 of 1986 Intel microcom handbook.
        !          1703:  *
        !          1704:  */
        !          1705: char *
        !          1706: pc586bldru(unit)
        !          1707: int unit;
        !          1708: {
        !          1709:        fd_t    *fd_p = (fd_t *)(pc_softc[unit].sram + OFFSET_RU);
        !          1710:        ru_t    *rbd_p = (ru_t *)(pc_softc[unit].sram + OFFSET_RBD);
        !          1711:        int     i;
        !          1712: 
        !          1713:        pc_softc[unit].begin_fd = fd_p;
        !          1714:        for(i = 0; i < N_FD; i++, fd_p++) {
        !          1715:                fd_p->status = 0;
        !          1716:                fd_p->command   = 0;
        !          1717:                fd_p->link_offset = ptr_to_ram((char *)(fd_p + 1), unit);
        !          1718:                fd_p->rbd_offset = PC586NULL;
        !          1719:        }
        !          1720:        pc_softc[unit].end_fd = --fd_p;
        !          1721:        fd_p->link_offset = PC586NULL;
        !          1722:        fd_p->command = AC_CW_EL;
        !          1723:        fd_p = (fd_t *)(pc_softc[unit].sram + OFFSET_RU);
        !          1724: 
        !          1725:        fd_p->rbd_offset = ptr_to_ram((char *)rbd_p, unit);
        !          1726:        for(i = 0; i < N_RBD; i++, rbd_p = (ru_t *) &(rbd_p->rbuffer[RCVBUFSIZE])) {
        !          1727:                rbd_p->r.status = 0;
        !          1728:                rbd_p->r.buffer_addr = ptr_to_ram((char *)(rbd_p->rbuffer),
        !          1729:                                                   unit);
        !          1730:                rbd_p->r.buffer_base = 0;
        !          1731:                rbd_p->r.size = RCVBUFSIZE;
        !          1732:                if (i != N_RBD-1) {
        !          1733:                        rbd_p->r.next_rbd_offset=ptr_to_ram(&(rbd_p->rbuffer[RCVBUFSIZE]),
        !          1734:                                                            unit);
        !          1735:                } else {
        !          1736:                        rbd_p->r.next_rbd_offset = PC586NULL;
        !          1737:                        rbd_p->r.size |= AC_CW_EL;
        !          1738:                        pc_softc[unit].end_rbd = (rbd_t *)rbd_p;
        !          1739:                }
        !          1740:        }
        !          1741:        return (char *)pc_softc[unit].begin_fd;
        !          1742: }
        !          1743: 
        !          1744: /*
        !          1745:  * pc586rustrt:
        !          1746:  *
        !          1747:  *     This routine starts the receive unit running.  First checks if the
        !          1748:  *     board is actually ready, then the board is instructed to receive
        !          1749:  *     packets again.
        !          1750:  *
        !          1751:  */
        !          1752: pc586rustrt(unit)
        !          1753: int unit;
        !          1754: {
        !          1755:        volatile scb_t  *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB);
        !          1756:        char            *strt;
        !          1757: 
        !          1758:        if ((scb_p->scb_status & SCB_RUS_READY) == SCB_RUS_READY)
        !          1759:                return;
        !          1760: 
        !          1761:        strt = pc586bldru(unit);
        !          1762:        scb_p->scb_command = SCB_RU_STRT;
        !          1763:        scb_p->scb_rfa_offset = ptr_to_ram(strt, unit);
        !          1764:        pc586chatt(unit);
        !          1765:        return;
        !          1766: }
        !          1767: 
        !          1768: /*
        !          1769:  * pc586diag:
        !          1770:  *
        !          1771:  *     This routine does a 586 op-code number 7, and obtains the
        !          1772:  *     diagnose status for the pc586.
        !          1773:  *
        !          1774:  */
        !          1775: pc586diag(unit)
        !          1776: int unit;
        !          1777: {
        !          1778:        volatile scb_t  *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB);
        !          1779:        volatile ac_t   *cb_p  = (volatile ac_t *)(pc_softc[unit].sram + OFFSET_CU);
        !          1780:        int             i;
        !          1781: 
        !          1782:        if (scb_p->scb_status & SCB_SW_INT) {
        !          1783:                printf("pc%d diag(): bad initial state %\n",
        !          1784:                        unit, scb_p->scb_status);
        !          1785:                pc586ack(unit);
        !          1786:        }
        !          1787:        cb_p->ac_status = 0;
        !          1788:        cb_p->ac_command = (AC_DIAGNOSE|AC_CW_EL);
        !          1789:        scb_p->scb_command = SCB_CU_STRT;
        !          1790:        pc586chatt(unit);
        !          1791: 
        !          1792:        for(i = 0; i < 0xffff; i++)
        !          1793:                if ((cb_p->ac_status & AC_SW_C))
        !          1794:                        break;
        !          1795:        if (i == 0xffff || !(cb_p->ac_status & AC_SW_OK)) {
        !          1796:                printf("pc%d: diag failed; status = %x\n",
        !          1797:                        unit, cb_p->ac_status);
        !          1798:                return(FALSE);
        !          1799:        }
        !          1800: 
        !          1801:        if ( (scb_p->scb_status & SCB_SW_INT) && (scb_p->scb_status != SCB_SW_CNA) )  {
        !          1802:                printf("pc%d diag(): bad final state %x\n",
        !          1803:                        unit, scb_p->scb_status);
        !          1804:                pc586ack(unit);
        !          1805:        }
        !          1806:        return(TRUE);
        !          1807: }
        !          1808: 
        !          1809: /*
        !          1810:  * pc586config:
        !          1811:  *
        !          1812:  *     This routine does a standard config of the pc586 board.
        !          1813:  *
        !          1814:  */
        !          1815: pc586config(unit)
        !          1816: int unit;
        !          1817: {
        !          1818:        volatile scb_t  *scb_p  = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB);
        !          1819:        volatile ac_t   *cb_p   = (volatile ac_t *)(pc_softc[unit].sram + OFFSET_CU);
        !          1820:        int             i;
        !          1821: 
        !          1822: 
        !          1823: /*
        !          1824:        if ((scb_p->scb_status != SCB_SW_CNA) && (scb_p->scb_status & SCB_SW_INT) ) {
        !          1825:                printf("pc%d config(): unexpected initial state %x\n",
        !          1826:                        unit, scb_p->scb_status);
        !          1827:        }
        !          1828: */
        !          1829:        pc586ack(unit);
        !          1830: 
        !          1831:        cb_p->ac_status = 0;
        !          1832:        cb_p->ac_command = (AC_CONFIGURE|AC_CW_EL);
        !          1833: 
        !          1834:        /*
        !          1835:         * below is the default board configuration from p2-28 from 586 book
        !          1836:         */
        !          1837:        cb_p->cmd.configure.fifolim_bytecnt     = 0x080c;
        !          1838:        cb_p->cmd.configure.addrlen_mode        = 0x2600;
        !          1839:        cb_p->cmd.configure.linprio_interframe  = 0x6000;
        !          1840:        cb_p->cmd.configure.slot_time           = 0xf200;
        !          1841:        cb_p->cmd.configure.hardware            = 0x0000;
        !          1842:        cb_p->cmd.configure.min_frame_len       = 0x0040;
        !          1843: 
        !          1844:        scb_p->scb_command = SCB_CU_STRT;
        !          1845:        pc586chatt(unit);
        !          1846: 
        !          1847:        for(i = 0; i < 0xffff; i++)
        !          1848:                if ((cb_p->ac_status & AC_SW_C))
        !          1849:                        break;
        !          1850:        if (i == 0xffff || !(cb_p->ac_status & AC_SW_OK)) {
        !          1851:                printf("pc%d: config-configure failed; status = %x\n",
        !          1852:                        unit, cb_p->ac_status);
        !          1853:                return(FALSE);
        !          1854:        }
        !          1855: /*
        !          1856:        if (scb_p->scb_status & SCB_SW_INT) {
        !          1857:                printf("pc%d configure(): bad configure state %x\n",
        !          1858:                        unit, scb_p->scb_status);
        !          1859:                pc586ack(unit);
        !          1860:        }
        !          1861: */
        !          1862:        cb_p->ac_status = 0;
        !          1863:        cb_p->ac_command = (AC_IASETUP|AC_CW_EL);
        !          1864: 
        !          1865:        bcopy16(pc_softc[unit].ds_addr, cb_p->cmd.iasetup, ETHER_ADD_SIZE);
        !          1866: 
        !          1867:        scb_p->scb_command = SCB_CU_STRT;
        !          1868:        pc586chatt(unit);
        !          1869: 
        !          1870:        for (i = 0; i < 0xffff; i++)
        !          1871:                if ((cb_p->ac_status & AC_SW_C))
        !          1872:                        break;
        !          1873:        if (i == 0xffff || !(cb_p->ac_status & AC_SW_OK)) {
        !          1874:                printf("pc%d: config-address failed; status = %x\n",
        !          1875:                        unit, cb_p->ac_status);
        !          1876:                return(FALSE);
        !          1877:        }
        !          1878: /*
        !          1879:        if ((scb_p->scb_status & SCB_SW_INT) != SCB_SW_CNA) {
        !          1880:                printf("pc%d configure(): unexpected final state %x\n",
        !          1881:                        unit, scb_p->scb_status);
        !          1882:        }
        !          1883: */
        !          1884:        pc586ack(unit);
        !          1885: 
        !          1886:        return(TRUE);
        !          1887: }
        !          1888: 
        !          1889: /*
        !          1890:  * pc586ack:
        !          1891:  */
        !          1892: pc586ack(unit)
        !          1893: {
        !          1894:        volatile scb_t  *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB);
        !          1895:        int i;
        !          1896: 
        !          1897:        if (!(scb_p->scb_command = scb_p->scb_status & SCB_SW_INT))
        !          1898:                return;
        !          1899:        CMD(CHANATT, 0x0001, unit);
        !          1900:        for (i = 1000000; scb_p->scb_command && (i-- > 0); );
        !          1901:        if (!i)
        !          1902:                printf("pc%d pc586ack(): board not accepting command.\n", unit);
        !          1903: }
        !          1904: 
        !          1905: char *
        !          1906: ram_to_ptr(offset, unit)
        !          1907: int unit;
        !          1908: u_short        offset;
        !          1909: {
        !          1910:        if (offset == PC586NULL)
        !          1911:                return(NULL);
        !          1912:        if (offset > 0x3fff) {
        !          1913:                printf("ram_to_ptr(%x, %d)\n", offset, unit);
        !          1914:                panic("range");
        !          1915:                return(NULL);
        !          1916:        }
        !          1917:        return(pc_softc[unit].sram + offset);
        !          1918: }
        !          1919: 
        !          1920: #ifndef        REQUEUE_DBG
        !          1921: bad_rbd_chain(offset, unit)
        !          1922: {
        !          1923:        rbd_t   *rbdp;
        !          1924:        char    *sram = pc_softc[unit].sram;
        !          1925: 
        !          1926:        for (;;) {
        !          1927:                if (offset == PC586NULL)
        !          1928:                        return 0;
        !          1929:                if (offset > 0x3fff) {
        !          1930:                        printf("pc%d: bad_rbd_chain offset = %x\n",
        !          1931:                                unit, offset);
        !          1932:                        pc586_cntrs[unit].rcv.bad_chain++;
        !          1933:                        return 1;
        !          1934:                }
        !          1935: 
        !          1936:                rbdp = (rbd_t *)(sram + offset);
        !          1937:                offset = rbdp->next_rbd_offset;
        !          1938:        }
        !          1939: }
        !          1940: #endif REQUEUE_DBG
        !          1941: 
        !          1942: u_short
        !          1943: ptr_to_ram(k_va, unit)
        !          1944: char   *k_va;
        !          1945: int unit;
        !          1946: {
        !          1947:        return((u_short)(k_va - pc_softc[unit].sram));
        !          1948: }
        !          1949: 
        !          1950: pc586scb(unit)
        !          1951: {
        !          1952:        volatile scb_t  *scb = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB);
        !          1953:        volatile u_short*cmd = (volatile u_short *)(pc_softc[unit].prom + OFFSET_NORMMODE);
        !          1954:        u_short          i;
        !          1955: 
        !          1956:        i = scb->scb_status;
        !          1957:        printf("stat: stat %x, cus %x, rus %x //",
        !          1958:                (i&0xf000)>>12, (i&0x0700)>>8, (i&0x0070)>>4);
        !          1959:        i = scb->scb_command;
        !          1960:        printf(" cmd: ack %x, cuc %x, ruc %x\n",
        !          1961:                (i&0xf000)>>12, (i&0x0700)>>8, (i&0x0070)>>4);
        !          1962: 
        !          1963:        printf("crc %d[%d], align %d[%d], rsc %d[%d], ovr %d[%d]\n",
        !          1964:                scb->scb_crcerrs, pc586_cntrs[unit].rcv.crc,
        !          1965:                scb->scb_alnerrs, pc586_cntrs[unit].rcv.frame,
        !          1966:                scb->scb_rscerrs, pc586_cntrs[unit].rcv.rscerrs,
        !          1967:                scb->scb_ovrnerrs, pc586_cntrs[unit].rcv.ovrnerrs);
        !          1968: 
        !          1969:        printf("cbl %x, rfa %x //", scb->scb_cbl_offset, scb->scb_rfa_offset);
        !          1970:        printf(" norm %x, ena %x, xfer %x //",
        !          1971:                cmd[0] & 1, cmd[3] & 1, cmd[4] & 1);
        !          1972:        printf(" atn %x, reset %x, type %x, stat %x\n",
        !          1973:                cmd[1] & 1, cmd[2] & 1, cmd[5] & 1, cmd[6] & 1);
        !          1974: }
        !          1975: 
        !          1976: pc586tbd(unit)
        !          1977: {
        !          1978:        pc_softc_t      *is = &pc_softc[unit];
        !          1979:        tbd_t           *tbd_p = (tbd_t *)(is->sram + OFFSET_TBD);
        !          1980:        int             i = 0;
        !          1981:        int             sum = 0;
        !          1982: 
        !          1983:        do {
        !          1984:                sum += (tbd_p->act_count & ~TBD_SW_EOF);
        !          1985:                printf("%d: addr %x, count %d (%d), next %x, base %x\n",
        !          1986:                        i++, tbd_p->buffer_addr,
        !          1987:                        (tbd_p->act_count & ~TBD_SW_EOF), sum,
        !          1988:                        tbd_p->next_tbd_offset,
        !          1989:                        tbd_p->buffer_base);
        !          1990:                if (tbd_p->act_count & TBD_SW_EOF)
        !          1991:                        break;
        !          1992:                tbd_p = (tbd_t *)(is->sram + tbd_p->next_tbd_offset);
        !          1993:        } while (1);
        !          1994: }
        !          1995: 
        !          1996: #ifndef        MACH_KERNEL
        !          1997: pc586hdwsleaze(countp, mb_pp, tm_pp, unit)
        !          1998: struct mbuf **tm_pp;
        !          1999: u_char **mb_pp;
        !          2000: u_short *countp;
        !          2001: {
        !          2002:        struct mbuf     *tm_p = *tm_pp;
        !          2003:        u_char          *mb_p = *mb_pp;
        !          2004:        u_short         count = 0;
        !          2005:        u_char          *cp;
        !          2006:        int             len;
        !          2007: 
        !          2008:        pc586_cntrs[unit].xmt.sleaze++;
        !          2009:        /*
        !          2010:         * can we get a run that will be coallesced or
        !          2011:         * that terminates before breaking
        !          2012:         */
        !          2013:        do {
        !          2014:                count += tm_p->m_len;
        !          2015:                if (tm_p->m_len & 1)
        !          2016:                        break;
        !          2017:        } while ((tm_p = tm_p->m_next) != (struct mbuf *)0);
        !          2018:        if ( (tm_p == (struct mbuf *)0) ||
        !          2019:              count > HDW_THRESHOLD) {
        !          2020:                *countp = (*tm_pp)->m_len;
        !          2021:                *mb_pp = mtod((*tm_pp), u_char *);
        !          2022:                printf("\n");
        !          2023:                return;
        !          2024:        }
        !          2025: 
        !          2026:        /* we need to copy */
        !          2027:        pc586_cntrs[unit].xmt.intrinsic++;
        !          2028:        tm_p = *tm_pp;
        !          2029:        mb_p = *mb_pp;
        !          2030:        count = 0;
        !          2031:        cp = (u_char *) t_packet;
        !          2032:        do {
        !          2033:                bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
        !          2034:                count += len;
        !          2035:                if (count > HDW_THRESHOLD)
        !          2036:                        break;
        !          2037:                cp += len;
        !          2038:                if (tm_p->m_next == (struct mbuf *)0)
        !          2039:                        break;
        !          2040:                tm_p = tm_p->m_next;
        !          2041:        } while (1);
        !          2042:        pc586_cntrs[unit].xmt.intrinsic_count += count;
        !          2043:        *countp = count;
        !          2044:        *mb_pp = (u_char *) t_packet;
        !          2045:        *tm_pp = tm_p;
        !          2046:        return;
        !          2047: }
        !          2048: 
        !          2049: pc586sftwsleaze(countp, mb_pp, tm_pp, unit)
        !          2050: struct mbuf **tm_pp;
        !          2051: u_char **mb_pp;
        !          2052: u_short *countp;
        !          2053: {
        !          2054:        struct mbuf     *tm_p = *tm_pp;
        !          2055:        u_char          *mb_p = *mb_pp;
        !          2056:        u_short         count = 0;
        !          2057:        u_char          *cp = (u_char *) t_packet;
        !          2058:        int             len;
        !          2059: 
        !          2060:        pc586_cntrs[unit].xmt.chain++;
        !          2061:        /* we need to copy */
        !          2062:        do {
        !          2063:                bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len);
        !          2064:                count += len;
        !          2065:                cp += len;
        !          2066:                if (tm_p->m_next == (struct mbuf *)0)
        !          2067:                        break;
        !          2068:                tm_p = tm_p->m_next;
        !          2069:        } while (1);
        !          2070: 
        !          2071:        *countp = count;
        !          2072:        *mb_pp = (u_char *) t_packet;
        !          2073:        *tm_pp = tm_p;
        !          2074:        return;
        !          2075: }
        !          2076: #endif MACH_KERNEL

unix.superglobalmegacorp.com

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