Annotation of Gnu-Mach/i386/i386at/if_ns8390.c, revision 1.1.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: /* NOTE:
                     27:  *     There are three outstanding bug/features in this implementation.
                     28:  * They may even be hardware misfeatures.  The conditions are registered
                     29:  * by counters maintained by the software.
                     30:  *     1: over_write is a condition that means that the board wants to store
                     31:  * packets, but there is no room.  So new packets are lost.  What seems to
                     32:  * be happening is that we get an over_write condition, but there are no
                     33:  * or just a few packets in the board's ram.  Also it seems that we get
                     34:  * several over_writes in a row.
                     35:  *     2: Since there is only one transmit buffer, we need a lock to indicate
                     36:  * whether it is in use.  We clear this lock when we get a transmit interrupt.
                     37:  * Sometimes we go to transmit and although there is no transmit in progress,
                     38:  * the lock is set.  (In this case, we just ignore the lock.)  It would look
                     39:  * like we can miss transmit interrupts?
                     40:  *     3: We tried to clean up the unnecessary switches to bank 0.  
                     41:  * Unfortunately, when you do an ifconfig "down", the system tend to lock up
                     42:  * a few seconds later (this was when DSF_RUNNING) was not being set before.
                     43:  * But even with DSF_RUNNING, on an EISA bus machine we ALWAYS lock up after
                     44:  * a few seconds. 
                     45:  */
                     46: 
                     47: /*
                     48:  * Western Digital 8003E Mach Ethernet driver (for intel 80386)
                     49:  * Copyright (c) 1990 by Open Software Foundation (OSF).
                     50:  */
                     51: 
                     52: /*
                     53:   Copyright 1990 by Open Software Foundation,
                     54: Cambridge, MA.
                     55: 
                     56:                All Rights Reserved
                     57: 
                     58:   Permission to use, copy, modify, and distribute this software and
                     59: its documentation for any purpose and without fee is hereby granted,
                     60: provided that the above copyright notice appears in all copies and
                     61: that both the copyright notice and this permission notice appear in
                     62: supporting documentation, and that the name of OSF or Open Software
                     63: Foundation not be used in advertising or publicity pertaining to
                     64: distribution of the software without specific, written prior
                     65: permission.
                     66: 
                     67:   OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
                     68: <INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
                     69: IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
                     70: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                     71: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
                     72: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
                     73: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     74: */
                     75: 
                     76: #define IF_CNTRS       MACH
                     77: 
                     78: #include       <ns8390.h>
                     79: #if NNS8390 > 0
                     80: 
                     81: #include       <mach_ttd.h>
                     82: #include       <kern/time_out.h>
                     83: #include       <device/device_types.h>
                     84: #include       <device/errno.h>
                     85: #include       <device/io_req.h>
                     86: #include       <device/if_hdr.h>
                     87: #include       <device/if_ether.h>
                     88: #include       <device/net_status.h>
                     89: #include       <device/net_io.h>
                     90: #include       "vm_param.h"
                     91: #include       <i386/ipl.h>
                     92: #include       <chips/busses.h>
                     93: #include       <i386at/ds8390.h>
                     94: #include       <i386at/if_wd8003.h>
                     95: #include       <i386at/if_3c503.h>
                     96: 
                     97: #if    MACH_TTD
                     98: #include <ttd/ttd_stub.h>
                     99: #endif /* MACH_TTD */
                    100: 
                    101: 
                    102: #define        SPLNET  spl6
                    103: 
                    104: int wd_debug = 0;
                    105:   
                    106: int    ns8390probe();
                    107: void   ns8390attach();
                    108: int    ns8390intr();
                    109: int    ns8390init();
                    110: int    ns8390output();
                    111: int    ns8390ioctl();
                    112: int    ns8390reset();
                    113: int     ns8390rcv();
                    114: int    ns8390watch();
                    115: int     ns8390get_CURR();
                    116: int     ns8390over_write();
                    117: 
                    118: struct bus_device      *ns8390info[NNS8390];   /* ???? */
                    119: 
                    120: static vm_offset_t ns8390_std[NNS8390] = { 0 };
                    121: static struct bus_device *ns8390_info[NNS8390];
                    122: struct bus_driver      ns8390driver =
                    123:        {ns8390probe, 0, ns8390attach, 0, ns8390_std, "ns8390", ns8390_info, 0, 0, 0};
                    124: 
                    125: int    watchdog_id;
                    126: 
                    127: char *wd8003_card = "wd";
                    128: char *elii_card = "el";
                    129: /*               2e0, 2a0, 280,  250,   350,   330,   310, 300*/
                    130: int elii_irq[8] = {5,   2,   2,     5,     5, 0x711, 0x711,  5};
                    131: int elii_bnc[8] = {1,   0,   1,     1,     0, 0x711, 0x711,  0};
                    132: /*int elii_bnc[8] = {0, 1,   1,     1,     1,     1,     0,  1}; */
                    133: 
                    134: typedef struct {
                    135: #ifdef MACH_KERNEL
                    136:        struct  ifnet   ds_if;          /* generic interface header */
                    137:        u_char  ds_addr[6];             /* Ethernet hardware address */
                    138: #else  MACH_KERNEL
                    139:        struct  arpcom  ns8390_ac;
                    140: #define        ds_if   ns8390_ac.ac_if
                    141: #define        ds_addr ns8390_ac.ac_enaddr
                    142: #endif MACH_KERNEL
                    143:        int     flags;
                    144:        int     timer;
                    145:        int     interrupt;
                    146:        char    *nic;
                    147:        u_char   address[ETHER_ADDR_SIZE];
                    148:        short   mode;
                    149:        int     tbusy;
                    150:        char    *sram;          /* beginning of the shared memory RAM buffer */
                    151:        int     read_nxtpkt_ptr;/* pointer to next packet available */
                    152:        int     pstart;         /* page start hold */
                    153:        int     pstop;          /* page stop hold */
                    154:        int     tpsr;           /* transmit page start hold */
                    155:        int     fifo_depth;     /* NIC fifo threshold */
                    156:        char    *card;
                    157:        int     board_id;
                    158: }
                    159: ns8390_softc_t;
                    160: 
                    161: ns8390_softc_t ns8390_softc[NNS8390];
                    162: 
                    163: struct ns8390_cntrs {
                    164: u_int  ovw,
                    165:        jabber,
                    166:        crc,
                    167:        frame,
                    168:        miss,
                    169:        fifo,
                    170:        rcv;
                    171: u_int  xmt,
                    172:        xmti,
                    173:        busy,
                    174:        heart;
                    175: } ns8390_cntrs[NNS8390];
                    176: 
                    177: #if    MACH_TTD        
                    178: boolean_t ttd_poll_loop;
                    179: 
                    180: int ns8390poll_receive();
                    181: int ns8390transmit_ttd();
                    182: #endif /* MACH_TTD */
                    183: 
                    184: #ifdef IF_CNTRS
                    185: int ns_narp = 1, ns_arp = 0;
                    186: int ns_ein[32], ns_eout[32]; 
                    187: int ns_lin[128/8], ns_lout[128/8]; 
                    188: static
                    189: log_2(no)
                    190: unsigned long no;
                    191: {
                    192:        return ({ unsigned long _temp__;
                    193:                asm("bsr %1, %0; jne 0f; xorl %0, %0; 0:" :
                    194:                    "=r" (_temp__) : "a" (no));
                    195:                _temp__;});
                    196: }
                    197: #endif IF_CNTRS
                    198: 
                    199: /* Interrupts mask bits */
                    200: int  imr_hold = DSIM_PRXE|DSIM_PTXE|DSIM_RXEE|DSIM_TXEE|DSIM_OVWE|DSIM_CNTE; 
                    201: 
                    202: /*
                    203:  * ns8390probe:
                    204:  *
                    205:  *     This function "probes" or checks for the wd8003 board on the bus to see
                    206:  *     if it is there.  As far as I can tell, the best break between this
                    207:  *     routine and the attach code is to simply determine whether the board
                    208:  *      is configured in properly. Currently my approach to this is to test the
                    209:  *      base I/O special offset for the Western Digital unique byte sequence
                    210:  *      identifier.  If the bytes match we assume board is there.
                    211:  *     The config code expects to see a successful return from the probe
                    212:  *     routine before attach will be called.
                    213:  *
                    214:  * input       : address device is mapped to, and unit # being checked
                    215:  * output      : a '1' is returned if the board exists, and a 0 otherwise
                    216:  *
                    217:  */
                    218: 
                    219: ns8390probe(port, dev)
                    220: struct bus_device      *dev;
                    221: {
                    222:        caddr_t         hdwbase = (caddr_t)dev->address;
                    223:        int             unit = dev->unit;
                    224:        ns8390_softc_t  *sp = &ns8390_softc[unit];
                    225:        int             tmp;
                    226:        int             vendor_id;
                    227: 
                    228:        if ((unit < 0) || (unit > NNS8390)) {
                    229:                printf("ns8390 ethernet unit %d out of range\n", unit);
                    230:                return(0);
                    231:        }
                    232:        if (((u_char) inb(hdwbase+IFWD_LAR_0) == (u_char) WD_NODE_ADDR_0) &&
                    233:            ((u_char) inb(hdwbase+IFWD_LAR_1) == (u_char) WD_NODE_ADDR_1) &&
                    234:            ((u_char) inb(hdwbase+IFWD_LAR_2) == (u_char) WD_NODE_ADDR_2)) {
                    235:                        ns8390info[unit] = dev;
                    236:                        sp->card = wd8003_card;
                    237:                        dev->name = wd8003_card;
                    238:                        sp->nic = hdwbase + OFF_8390;
                    239:                                /* enable mem access to board */
                    240:                        sp->board_id = wd80xxget_board_id(dev);
                    241: 
                    242:                        *(sp->address)      = inb(hdwbase+IFWD_LAR_0);
                    243:                        *(sp->address + 1)  = inb(hdwbase+IFWD_LAR_1);
                    244:                        *(sp->address + 2)  = inb(hdwbase+IFWD_LAR_2);
                    245:                        *(sp->address + 3)  = inb(hdwbase+IFWD_LAR_3);
                    246:                        *(sp->address + 4)  = inb(hdwbase+IFWD_LAR_4);
                    247:                        *(sp->address + 5)  = inb(hdwbase+IFWD_LAR_5);
                    248:                        return (1);
                    249:                }  /* checks the address of the board to verify that it is a WD */
                    250:        
                    251:        /* try to avoid any NE2000 pretending to be an el II */
                    252:        if (inb(hdwbase + 0x408) == 0xff) 
                    253:                return 0;
                    254: 
                    255:        /* check vendor id */
                    256:        tmp = inb(hdwbase + CTLR);
                    257: 
                    258:        outb(hdwbase + CTLR, CTLR_RST|CTLR_THIN); /* Reset it... */
                    259:        outb(hdwbase + CTLR, CTLR_THIN);
                    260:        /* 
                    261:         * Map the station addr PROM into the lower I/O ports. We now
                    262:         * check for both the old and new 3Com prefix 
                    263:         */
                    264:        outb(hdwbase + CTLR, CTLR_STA_ADDR|CTLR_THIN);
                    265:        vendor_id = inb(hdwbase)*0x10000 + inb(hdwbase + 1)*0x100 + 
                    266:                inb(hdwbase + 2);
                    267:        /* Restore the register we frobbed. */
                    268:        outb(hdwbase + CTLR, tmp);
                    269:        if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) 
                    270:                return 0;
                    271: 
                    272:        if ((tmp = inb(hdwbase+BCFR))) {
                    273:                switch(tmp) {
                    274:                case (1<<7):    sp->board_id = 7; break;        /*irq5 xvcr*/
                    275: #ifdef not_currently_possible
                    276:                case (1<<6):    sp->board_id = 6; break;
                    277:                case (1<<5):    sp->board_id = 5; break;
                    278: #endif not_currently_possible
                    279:                case (1<<4):    sp->board_id = 4; break;
                    280:                case (1<<3):    sp->board_id = 3; break;
                    281:                case (1<<2):    sp->board_id = 2; break;        /*irq2 bnc*/
                    282:                case (1<<1):    sp->board_id = 1; break;        /*irq2 xvcr*/
                    283:                case (1<<0):    sp->board_id = 0; break;        /*irq5 bnc*/
                    284:                default:        return 0;
                    285:                }
                    286:                switch (inb(hdwbase+PCFR)) {
                    287:                case (1<<7):    dev->phys_address = 0xDC000; break;
                    288:                case (1<<6):    dev->phys_address = 0xD8000; break;
                    289: #ifdef not_currently_possible
                    290:                case (1<<5):    dev->phys_address = 0xCC000; break;
                    291:                case (1<<4):    dev->phys_address = 0xC8000; break;
                    292: #endif not_currently_possible
                    293:                default:
                    294:                        printf("EtherLink II with NO memory configured\n");
                    295:                        return 0;
                    296:                }
                    297:                ns8390info[unit] = dev;
                    298:                dev->sysdep1 = elii_irq[sp->board_id];
                    299:                if (dev->sysdep1 == 2)
                    300:                        dev->sysdep1 = 9;
                    301:                sp->card = elii_card;
                    302:                dev->name = elii_card;
                    303:                sp->nic = hdwbase;
                    304:                return 1;
                    305:         }
                    306: 
                    307:        return(0);
                    308: }
                    309: 
                    310: /*
                    311:  * ns8390attach:
                    312:  *
                    313:  *     This function attaches a ns8390 board to the "system".  The rest of
                    314:  *     runtime structures are initialized here (this routine is called after
                    315:  *     a successful probe of the board).  Once the ethernet address is read
                    316:  *     and stored, the board's ifnet structure is attached and readied.
                    317:  *
                    318:  * input       : bus_device structure setup in autoconfig
                    319:  * output      : board structs and ifnet is setup
                    320:  *
                    321:  */
                    322: 
                    323: void ns8390attach(dev)
                    324: struct bus_device      *dev;
                    325: {
                    326:        ns8390_softc_t  *sp;
                    327:        struct  ifnet   *ifp;
                    328:        u_char          unit;
                    329:        int             temp;
                    330: 
                    331:        take_dev_irq(dev);
                    332:        unit = (u_char)dev->unit;
                    333:        sp = &ns8390_softc[unit];
                    334:        printf(", port = %x, spl = %d, pic = %d. ",
                    335:                dev->address, dev->sysdep, dev->sysdep1);
                    336: 
                    337:        if (sp->card == elii_card) {
                    338:                if (elii_bnc[sp->board_id])
                    339:                        printf("cheapernet ");
                    340:                else
                    341:                        printf("ethernet ");
                    342:        } else
                    343:                printf("ethernet ");
                    344: 
                    345:        (volatile char *)sp->sram =
                    346:            (volatile char *) phystokv(dev->phys_address);
                    347:        dev->address = (vm_offset_t) phystokv(dev->address);
                    348:        sp->timer = -1;
                    349:        sp->flags = 0;
                    350:        sp->mode  = 0;
                    351: 
                    352:        if (!ns8390hwrst(unit)) {
                    353:                printf("%s%d: attach(): reset failed.\n",
                    354:                        sp->card, unit);
                    355:                return;
                    356:        }
                    357:                /* N.B. sp->address is not determined till
                    358:                 * hwrst time. */
                    359:        *(sp->ds_addr)      = *(sp->address);
                    360:        *(sp->ds_addr + 1)  = *(sp->address + 1);
                    361:        *(sp->ds_addr + 2)  = *(sp->address + 2);
                    362:        *(sp->ds_addr + 3)  = *(sp->address + 3);
                    363:        *(sp->ds_addr + 4)  = *(sp->address + 4);
                    364:        *(sp->ds_addr + 5)  = *(sp->address + 5);
                    365: 
                    366:        printf("id [%x:%x:%x:%x:%x:%x]",
                    367:                sp->address[0],sp->address[1],sp->address[2],
                    368:                sp->address[3],sp->address[4],sp->address[5]);
                    369:        ifp = &(sp->ds_if);
                    370:        ifp->if_unit = unit;
                    371:        ifp->if_mtu = ETHERMTU;
                    372:        ifp->if_flags = IFF_BROADCAST;
                    373: #ifdef MACH_KERNEL
                    374:        ifp->if_header_size = sizeof(struct ether_header);
                    375:        ifp->if_header_format = HDR_ETHERNET;
                    376:        ifp->if_address_size = 6;
                    377:        ifp->if_address = (char *)&sp->address[0];
                    378:        if_init_queues(ifp);
                    379: #else  MACH_KERNEL
                    380:        ifp->if_name = sp->card;
                    381:        ifp->if_init = ns8390init;
                    382:        ifp->if_output = ns8390output;
                    383:        ifp->if_ioctl = ns8390ioctl;
                    384:        ifp->if_reset = ns8390reset;
                    385:        ifp->if_next = NULL;
                    386:        if_attach(ifp);
                    387: #ifdef notdef
                    388:        watchdog_id = timeout(ns8390watch, &(ifp->if_unit), 20*HZ);
                    389: #endif
                    390: #endif MACH_KERNEL
                    391: 
                    392: #ifdef MACH_KERNEL
                    393: #if    MACH_TTD
                    394:        if (!ttd_get_packet) {
                    395:                ttd_device_unit = unit;
                    396:                ttd_get_packet = ns8390poll_receive;
                    397:                ttd_send_packet = ns8390transmit_ttd;
                    398:                ttd_host_ether_id.array[0] = *(sp->address);
                    399:                ttd_host_ether_id.array[1] = *(sp->address + 1);
                    400:                ttd_host_ether_id.array[2] = *(sp->address + 2);
                    401:                ttd_host_ether_id.array[3] = *(sp->address + 3);
                    402:                ttd_host_ether_id.array[4] = *(sp->address + 4);
                    403:                ttd_host_ether_id.array[5] = *(sp->address + 5);
                    404:        }
                    405: #endif /* MACH_TTD */
                    406: #endif /* MACH_KERNEL */
                    407: }
                    408: 
                    409: /*
                    410:  * ns8390watch():
                    411:  *
                    412:  */
                    413: 
                    414: int
                    415: ns8390watch(b_ptr)
                    416: caddr_t        b_ptr;
                    417: {
                    418:        int     x,
                    419:                y,
                    420:                opri,
                    421:                unit;
                    422:        int     temp_cr;
                    423:        caddr_t nic;
                    424: 
                    425:        unit = *b_ptr;
                    426: #ifdef MACH_KERNEL
                    427:        timeout(ns8390watch,b_ptr,20*HZ);
                    428: #else  MACH_KERNEL
                    429:        watchdog_id = timeout(ns8390watch,b_ptr,20*HZ);
                    430: #endif MACH_KERNEL
                    431:        nic = ns8390_softc[unit].nic;
                    432:        temp_cr = inb(nic+ds_cmd);
                    433:        outb(nic + ds_cmd, (temp_cr & 0x3f) | DSCM_PG0);
                    434:        printf("<<< ISR=%x CURR=%x rdnxt=%x BNDY=%x>>> ",
                    435:                inb(nic + ds0_isr),
                    436:                ns8390get_CURR(unit), ns8390_softc[unit].read_nxtpkt_ptr,
                    437:                inb(nic+ds0_bndy));
                    438:        outb(nic+ds_cmd,temp_cr);
                    439: }
                    440: 
                    441: #ifdef MACH_KERNEL
                    442: int ns8390start();     /* forward */
                    443: 
                    444: /*ARGSUSED*/
                    445: wd8003open(dev, flag)
                    446:        dev_t   dev;
                    447:        int     flag;
                    448: {
                    449:        register int    unit = minor(dev);
                    450: 
                    451:        if (ns8390_softc[unit].card != wd8003_card)
                    452:                return (ENXIO);
                    453:        if (unit < 0 || unit >= NNS8390 ||
                    454:                ns8390_softc[unit].nic == 0)
                    455:            return (ENXIO);
                    456: 
                    457:        ns8390_softc[unit].ds_if.if_flags |= IFF_UP;
                    458:        ns8390init(unit);
                    459:        return(0);
                    460: }
                    461: 
                    462: eliiopen(dev, flag)
                    463:        dev_t   dev;
                    464:        int     flag;
                    465: {
                    466:        register int    unit = minor(dev);
                    467: 
                    468:        if (ns8390_softc[unit].card != elii_card)
                    469:                return (ENXIO);
                    470:        if (unit < 0 || unit >= NNS8390 ||
                    471:                ns8390_softc[unit].nic == 0)
                    472:            return (ENXIO);
                    473: 
                    474:        ns8390_softc[unit].ds_if.if_flags |= IFF_UP;
                    475:        ns8390init(unit);
                    476:        return(0);
                    477: }
                    478: 
                    479: ns8390output(dev, ior)
                    480:        dev_t           dev;
                    481:        io_req_t        ior;
                    482: {
                    483:        register int    unit = minor(dev);
                    484: 
                    485:        if (unit < 0 || unit >= NNS8390 ||
                    486:                ns8390_softc[unit].nic == 0)
                    487:            return (ENXIO);
                    488:        return (net_write(&ns8390_softc[unit].ds_if, ns8390start, ior));
                    489: }
                    490: 
                    491: ns8390setinput(dev, receive_port, priority, filter, filter_count)
                    492:        dev_t           dev;
                    493:        mach_port_t     receive_port;
                    494:        int             priority;
                    495:        filter_t        filter[];
                    496:        unsigned int    filter_count;
                    497: {
                    498:        register int unit = minor(dev);
                    499: 
                    500:        if (unit < 0 || unit >= NNS8390 ||
                    501:                ns8390_softc[unit].nic == 0)
                    502:            return (ENXIO);
                    503: 
                    504:        return (net_set_filter(&ns8390_softc[unit].ds_if,
                    505:                        receive_port, priority,
                    506:                        filter, filter_count));
                    507: }
                    508: 
                    509: #else  MACH_KERNEL
                    510: /*
                    511:  * ns8390output:
                    512:  *
                    513:  *     This routine is called by the "if" layer to output a packet to
                    514:  *     the network.  This code resolves the local ethernet address, and
                    515:  *     puts it into the mbuf if there is room.  If not, then a new mbuf
                    516:  *     is allocated with the header information and precedes the data
                    517:  *     to be transmitted.  The routine ns8390xmt() which actually
                    518:  *      transmits the data expects the ethernet header to precede the
                    519:  *      data in the mbuf.
                    520:  *
                    521:  * input:      ifnet structure pointer, an mbuf with data, and address
                    522:  *             to be resolved
                    523:  * output:     mbuf is updated to hold enet address, or a new mbuf
                    524:  *             with the address is added
                    525:  *
                    526:  */
                    527: 
                    528: ns8390output(ifp, m0, dst)
                    529: struct ifnet   *ifp;
                    530: struct mbuf    *m0;
                    531: struct sockaddr *dst;
                    532: {
                    533:        register ns8390_softc_t         *is = &ns8390_softc[ifp->if_unit];
                    534:        u_char                          edst[6];
                    535:        struct in_addr                  idst;
                    536:        register struct mbuf            *m = m0;
                    537:        register struct ether_header    *eh;
                    538:        register int                    off;
                    539:        int                             usetrailers;
                    540:        int                             type, error;
                    541:        spl_t                           opri;
                    542: 
                    543:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
                    544:                printf("%s%d output(): Turning off board %d\n",
                    545:                        is->card, ifp->if_unit);
                    546:                ns8390intoff(ifp->if_unit);
                    547:                error = ENETDOWN;
                    548:                goto bad;
                    549:        }
                    550:        switch (dst->sa_family) {
                    551: #ifdef INET
                    552:        case AF_INET:
                    553:                idst = ((struct sockaddr_in *)dst)->sin_addr;
                    554:                if (!arpresolve(&is->ns8390_ac, m, &idst, edst, &usetrailers)){
                    555:                        return (0);     /* if not yet resolved */
                    556:                }
                    557:                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                    558:                if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
                    559:                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
                    560:                        type = ETHERTYPE_TRAIL + (off>>9);
                    561:                        m->m_off -= 2 * sizeof (u_short);
                    562:                        m->m_len += 2 * sizeof (u_short);
                    563:                        *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
                    564:                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
                    565:                        goto gottrailertype;
                    566:                }
                    567:                type = ETHERTYPE_IP;
                    568:                off = 0;
                    569:                goto gottype;
                    570: #endif
                    571: #ifdef NS
                    572:        case AF_NS:
                    573:                type = ETHERTYPE_NS;
                    574:                bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
                    575:                      (caddr_t)edst,
                    576:                      sizeof (edst));
                    577:                off = 0;
                    578:                goto gottype;
                    579: #endif
                    580:        case AF_UNSPEC:
                    581:                eh = (struct ether_header *)dst->sa_data;
                    582:                bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
                    583:                type = eh->ether_type;
                    584:                goto gottype;
                    585:        default:
                    586:                printf("%s%d output(): can't handle af%d\n",
                    587:                        is->card, ifp->if_unit,
                    588:                        dst->sa_family);
                    589:                error = EAFNOSUPPORT;
                    590:                goto bad;
                    591:        }
                    592: gottrailertype:
                    593:        /*
                    594:         * Packet to be sent as trailer: move first packet
                    595:         * (control information) to end of chain.
                    596:         */
                    597:        while (m->m_next)
                    598:                m = m->m_next;
                    599:        m->m_next = m0;
                    600:        m = m0->m_next;
                    601:        m0->m_next = 0;
                    602:        m0 = m;
                    603: gottype:
                    604:        /*
                    605:         * Add local net header.  If no space in first mbuf,
                    606:         * allocate another.
                    607:         */
                    608:        if (m->m_off > MMAXOFF ||
                    609:            MMINOFF + sizeof (struct ether_header) > m->m_off) {
                    610:                m = m_get(M_DONTWAIT, MT_HEADER);
                    611:                if (m == 0) {
                    612:                        error = ENOBUFS;
                    613:                        goto bad;
                    614:                }
                    615:                m->m_next = m0;
                    616:                m->m_off = MMINOFF;
                    617:                m->m_len = sizeof (struct ether_header);
                    618:        } else {
                    619:                m->m_off -= sizeof (struct ether_header);
                    620:                m->m_len += sizeof (struct ether_header);
                    621:        }
                    622:        eh = mtod(m, struct ether_header *);
                    623:        eh->ether_type = htons((u_short)type);
                    624:        bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
                    625:        bcopy((caddr_t)is->address,
                    626:              (caddr_t)eh->ether_shost,
                    627:              sizeof(edst));
                    628:        /*
                    629:         * Queue message on interface, and start output if interface
                    630:         * not yet active.
                    631:         */
                    632:        opri = SPLNET();
                    633:        if (IF_QFULL(&ifp->if_snd)) {
                    634:                IF_DROP(&ifp->if_snd);
                    635:                splx(opri);
                    636:                m_freem(m);
                    637:                return (ENOBUFS);
                    638:        }
                    639:        IF_ENQUEUE(&ifp->if_snd, m);
                    640:        /*
                    641:         * Some action needs to be added here for checking whether the
                    642:         * board is already transmitting.  If it is, we don't want to
                    643:         * start it up (ie call ns8390start()).  We will attempt to send
                    644:         * packets that are queued up after an interrupt occurs.  Some
                    645:         * flag checking action has to happen here and/or in the start
                    646:         * routine.  This note is here to remind me that some thought
                    647:         * is needed and there is a potential problem here.
                    648:         *
                    649:         */
                    650:        ns8390start(ifp->if_unit);
                    651:        splx(opri);
                    652:        return (0);
                    653: bad:
                    654:        m_freem(m0);
                    655:        return (error);
                    656: }
                    657: #endif MACH_KERNEL
                    658: 
                    659: /*
                    660:  * ns8390reset:
                    661:  *
                    662:  *     This routine is in part an entry point for the "if" code.  Since most
                    663:  *     of the actual initialization has already (we hope already) been done
                    664:  *     by calling ns8390attach().
                    665:  *
                    666:  * input       : unit number or board number to reset
                    667:  * output      : board is reset
                    668:  *
                    669:  */
                    670: 
                    671: int
                    672: ns8390reset(unit)
                    673: int    unit;
                    674: {
                    675: 
                    676:        ns8390_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
                    677:        return(ns8390init(unit));
                    678: }
                    679: 
                    680: /*
                    681:  * ns8390init:
                    682:  *
                    683:  *     Another routine that interfaces the "if" layer to this driver.
                    684:  *     Simply resets the structures that are used by "upper layers".
                    685:  *     As well as calling ns8390hwrst that does reset the ns8390 board.
                    686:  *
                    687:  * input       : board number
                    688:  * output      : structures (if structs) and board are reset
                    689:  *
                    690:  */
                    691: 
                    692: int
                    693: ns8390init(unit)
                    694: int    unit;
                    695: {
                    696:        struct  ifnet   *ifp;
                    697:        int             stat;
                    698:        spl_t           oldpri;
                    699: 
                    700:        ifp = &(ns8390_softc[unit].ds_if);
                    701: #ifdef MACH_KERNEL
                    702: #else  MACH_KERNEL
                    703:        if (ifp->if_addrlist == (struct ifaddr *)0) {
                    704:                return;
                    705:        }
                    706: #endif MACH_KERNEL
                    707:        oldpri = SPLNET();
                    708:        if ((stat = ns8390hwrst(unit)) == TRUE) {
                    709:                ns8390_softc[unit].ds_if.if_flags |= IFF_RUNNING;
                    710:                ns8390_softc[unit].flags |= DSF_RUNNING;
                    711:                ns8390_softc[unit].tbusy = 0;
                    712:                ns8390start(unit);
                    713:        } else
                    714:                printf("%s%d init(): trouble resetting board %d\n",
                    715:                        ns8390_softc[unit].card, unit);
                    716:        ns8390_softc[unit].timer = 5;
                    717:        splx(oldpri);
                    718:        return(stat);
                    719: }
                    720: 
                    721: /*
                    722:  * ns8390start:
                    723:  *
                    724:  *     This is yet another interface routine that simply tries to output a
                    725:  *     in an mbuf after a reset.
                    726:  *
                    727:  * input       : board number
                    728:  * output      : stuff sent to board if any there
                    729:  *
                    730:  */
                    731: 
                    732: ns8390start(unit)
                    733: int    unit;
                    734: {
                    735:        register ns8390_softc_t *is = &ns8390_softc[unit];
                    736:        struct  ifnet           *ifp;
                    737: #ifdef MACH_KERNEL
                    738:        io_req_t        m;
                    739: #else  MACH_KERNEL
                    740:        struct  mbuf    *m;
                    741: #endif MACH_KERNEL
                    742: 
                    743:        if (is->tbusy) {
                    744:                caddr_t nic = ns8390_softc[unit].nic;
                    745:                if (!(inb(nic+ds_cmd) & DSCM_TRANS)) {
                    746:                        is->tbusy = 0;
                    747:                        ns8390_cntrs[unit].busy++;
                    748:                } else
                    749:                        return;
                    750:        }
                    751: 
                    752:        ifp = &(ns8390_softc[unit].ds_if);
                    753: 
                    754:        IF_DEQUEUE(&ifp->if_snd, m);
                    755: #ifdef MACH_KERNEL
                    756:        if (m != 0)
                    757: #else  MACH_KERNEL
                    758:        if (m != (struct mbuf *)0)
                    759: #endif MACH_KERNEL
                    760:        {
                    761:                is->tbusy++;
                    762:                ns8390_cntrs[unit].xmt++;
                    763:                ns8390xmt(unit, m);
                    764:        }
                    765: }
                    766: 
                    767: #ifdef MACH_KERNEL
                    768: /*ARGSUSED*/
                    769: ns8390getstat(dev, flavor, status, count)
                    770:        dev_t           dev;
                    771:        int             flavor;
                    772:        dev_status_t    status;         /* pointer to OUT array */
                    773:        unsigned int    *count;         /* out */
                    774: {
                    775:        register int    unit = minor(dev);
                    776: 
                    777:        if (unit < 0 || unit >= NNS8390 ||
                    778:                ns8390_softc[unit].nic == 0)
                    779:            return (ENXIO);
                    780: 
                    781:        return (net_getstat(&ns8390_softc[unit].ds_if,
                    782:                            flavor,
                    783:                            status,
                    784:                            count));
                    785: }
                    786: ns8390setstat(dev, flavor, status, count)
                    787:        dev_t           dev;
                    788:        int             flavor;
                    789:        dev_status_t    status;
                    790:        unsigned int    count;
                    791: {
                    792:        register int    unit = minor(dev);
                    793:        register ns8390_softc_t *sp;
                    794: 
                    795:        if (unit < 0 || unit >= NNS8390 ||
                    796:                ns8390_softc[unit].nic == 0)
                    797:            return (ENXIO);
                    798: 
                    799:        sp = &ns8390_softc[unit];
                    800: 
                    801:        switch (flavor) {
                    802:            case NET_STATUS:
                    803:            {
                    804:                /*
                    805:                 * All we can change are flags, and not many of those.
                    806:                 */
                    807:                register struct net_status *ns = (struct net_status *)status;
                    808:                int     mode = 0;
                    809: 
                    810:                if (count < NET_STATUS_COUNT)
                    811:                    return (D_INVALID_SIZE);
                    812: 
                    813:                if (ns->flags & IFF_ALLMULTI)
                    814:                    mode |= MOD_ENAL;
                    815:                if (ns->flags & IFF_PROMISC)
                    816:                    mode |= MOD_PROM;
                    817: 
                    818:                /*
                    819:                 * Force a complete reset if the receive mode changes
                    820:                 * so that these take effect immediately.
                    821:                 */
                    822:                if (sp->mode != mode) {
                    823:                    sp->mode = mode;
                    824:                    if (sp->flags & DSF_RUNNING) {
                    825:                        sp->flags &= ~(DSF_LOCK | DSF_RUNNING);
                    826:                        ns8390init(unit);
                    827:                    }
                    828:                }
                    829:                break;
                    830:            }
                    831: 
                    832:            default:
                    833:                return (D_INVALID_OPERATION);
                    834:        }
                    835:        return (D_SUCCESS);
                    836: }
                    837: #else  MACH_KERNEL
                    838: /*
                    839:  * ns8390ioctl:
                    840:  *
                    841:  *     This routine processes an ioctl request from the "if" layer
                    842:  *     above.
                    843:  *
                    844:  * input       : pointer the appropriate "if" struct, command, and data
                    845:  * output      : based on command appropriate action is taken on the
                    846:  *               ns8390 board(s) or related structures
                    847:  * return      : error is returned containing exit conditions
                    848:  *
                    849:  */
                    850: 
                    851: int
                    852: ns8390ioctl(ifp, cmd, data)
                    853: struct ifnet   *ifp;
                    854: int    cmd;
                    855: caddr_t        data;
                    856: {
                    857:        register struct ifaddr  *ifa = (struct ifaddr *)data;
                    858:        register ns8390_softc_t *is;
                    859:        int                     error;
                    860:        spl_t                   opri;
                    861:        short                    mode = 0;
                    862: 
                    863:        is = &ns8390_softc[ifp->if_unit];
                    864:        opri = SPLNET();
                    865:        error = 0;
                    866:        switch (cmd) {
                    867:        case SIOCSIFADDR:
                    868:                ifp->if_flags |= IFF_UP;
                    869:                ns8390init(ifp->if_unit);
                    870:                switch (ifa->ifa_addr.sa_family) {
                    871: #ifdef INET
                    872:                case AF_INET:
                    873:                        ((struct arpcom *)ifp)->ac_ipaddr =
                    874:                            IA_SIN(ifa)->sin_addr;
                    875:                        arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
                    876:                        break;
                    877: #endif
                    878: #ifdef NS
                    879:                case AF_NS:
                    880:                        {
                    881:                                register struct ns_addr *ina =
                    882:                                    &(IA_SNS(ifa)->sns_addr);
                    883:                                if (ns_nullhost(*ina))
                    884:                                        ina->x_host =
                    885:                                            *(union ns_host *)(ds->ds_addr);
                    886:                                else
                    887: ????
                    888:                                        ns8390seteh(ina->x_host.c_host,
                    889:                                                    ns8390_softc[ifp->if_unit].base);
                    890:                                break;
                    891:                        }
                    892: #endif
                    893:                }
                    894:                break;
                    895:        case SIOCSIFFLAGS:
                    896:                if (ifp->if_flags & IFF_ALLMULTI)
                    897:                        mode |= MOD_ENAL;
                    898:                if (ifp->if_flags & IFF_PROMISC)
                    899:                        mode |= MOD_PROM;
                    900:                /*
                    901:                 * force a complete reset if the receive multicast/
                    902:                 * promiscuous mode changes so that these take
                    903:                 * effect immediately.
                    904:                 *
                    905:                 */
                    906:                if (is->mode != mode) {
                    907:                        is->mode = mode;
                    908:                        if (is->flags & DSF_RUNNING) {
                    909:                                is->flags &=
                    910:                                    ~(DSF_LOCK|DSF_RUNNING);
                    911:                                ns8390init(ifp->if_unit);
                    912:                        }
                    913:                }
                    914:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    915:                    is->flags & DSF_RUNNING) {
                    916:                        printf("%s%d ioctl(): turning off board %d\n",
                    917:                                is->card, ifp->if_unit);
                    918:                        is->flags &= ~(DSF_LOCK | DSF_RUNNING);
                    919:                        is->timer = -1;
                    920:                        ns8390intoff(ifp->if_unit);
                    921:                        ns8390over_write(ifp->if_unit);
                    922:                } else
                    923:                    if (ifp->if_flags & IFF_UP &&
                    924:                    (is->flags & DSF_RUNNING) == 0)
                    925:                        ns8390init(ifp->if_unit);
                    926:                break;
                    927: #ifdef IF_CNTRS
                    928:        case SIOCCIFCNTRS:
                    929:                if (!suser()) {
                    930:                        error = EPERM;
                    931:                        break;
                    932:                }
                    933:                bzero((caddr_t)ns_ein, sizeof (ns_ein));
                    934:                bzero((caddr_t)ns_eout, sizeof (ns_eout));
                    935:                bzero((caddr_t)ns_lin, sizeof (ns_lin));
                    936:                bzero((caddr_t)ns_lout, sizeof (ns_lout));
                    937:                bzero((caddr_t)&ns_arp, sizeof (int));
                    938:                bzero((caddr_t)&ns8390_cntrs, sizeof (ns8390_cntrs));
                    939:                break;
                    940: #endif IF_CNTRS
                    941:        default:
                    942:                error = EINVAL;
                    943:        }
                    944:        splx(opri);
                    945:        return (error);
                    946: }
                    947: #endif MACH_KERNEL
                    948: 
                    949: /*
                    950:  * ns8390hwrst:
                    951:  *
                    952:  *     This routine resets the ns8390 board that corresponds to the
                    953:  *     board number passed in.
                    954:  *
                    955:  * input       : board number to do a hardware reset
                    956:  * output      : board is reset
                    957:  *
                    958:  */
                    959: 
                    960: int
                    961: ns8390hwrst(unit)
                    962: int unit;
                    963: {
                    964:        caddr_t nic = ns8390_softc[unit].nic;
                    965:        int     count;
                    966:        u_char  stat;
                    967:        spl_t   spl = SPLNET();
                    968: 
                    969:        if (ns8390_softc[unit].card == wd8003_card && 
                    970:            config_wd8003(unit) == FALSE) {
                    971:                printf("%s%d hwrst(): config_wd8003 failed.\n",
                    972:                        ns8390_softc[unit].card, unit);
                    973:                splx(spl);
                    974:                return(FALSE);
                    975:        }
                    976:        if (ns8390_softc[unit].card == elii_card && 
                    977:            config_3c503(unit) == FALSE) {
                    978:                printf("%s%d hwrst(): config_3c503 failed.\n",
                    979:                        ns8390_softc[unit].card, unit);
                    980:                splx(spl);
                    981:                return(FALSE);
                    982:        }
                    983:        if (config_nic(unit) == FALSE) {
                    984:                printf("%s%d hwrst(): config_nic failed.\n",
                    985:                        ns8390_softc[unit].card, unit);
                    986:                splx(spl);
                    987:                return(FALSE);
                    988:        }
                    989:        splx(spl);
                    990:        return(TRUE);
                    991: }
                    992: 
                    993: /*
                    994:  * ns8390intr:
                    995:  *
                    996:  *     This function is the interrupt handler for the ns8390 ethernet
                    997:  *     board.  This routine will be called whenever either a packet
                    998:  *     is received, or a packet has successfully been transfered and
                    999:  *     the unit is ready to transmit another packet.
                   1000:  *
                   1001:  * input       : board number that interrupted
                   1002:  * output      : either a packet is received, or a packet is transfered
                   1003:  *
                   1004:  */
                   1005: int
                   1006: ns8390intr(unit)
                   1007: {
                   1008:        int     opri, i;
                   1009:        int     isr_status;
                   1010:        int     temp_cr;
                   1011:        caddr_t nic = ns8390_softc[unit].nic;
                   1012: 
                   1013:        temp_cr = inb(nic+ds_cmd);
                   1014:        outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0);
                   1015:        outb(nic+ds0_imr, 0);                   /* stop board interrupts */
                   1016:        outb(nic+ds_cmd, temp_cr);
                   1017:        while (isr_status = inb(nic+ds0_isr)) {
                   1018:                outb(nic+ds0_isr, isr_status);          /* clear interrupt status */
                   1019: 
                   1020:                if ((isr_status & (DSIS_ROVRN|DSIS_RXE)) == DSIS_RXE) {
                   1021:                        int rsr = inb(nic+ds0_rsr);
                   1022:                        if (rsr & DSRS_DFR) ns8390_cntrs[unit].jabber++;
                   1023:                        if (rsr & ~(DSRS_DFR|DSRS_PHY|DSRS_FAE|DSRS_CRC|DSIS_RX))
                   1024:                                printf("%s%d intr(): isr = %x, RSR = %x\n",
                   1025:                                        ns8390_softc[unit].card, unit,
                   1026:                                        isr_status, rsr);
                   1027:                } else if (isr_status & DSIS_ROVRN) {
                   1028:                        ns8390_cntrs[unit].ovw++;
                   1029:                        ns8390over_write(unit);
                   1030:                }
                   1031:                if (isr_status & DSIS_RX) {     /* DFR & PRX is possible */
                   1032:                        ns8390rcv(unit);
                   1033: 
                   1034: #if    MACH_TTD
                   1035:                        if (kttd_active)
                   1036:                                ttd_poll_loop = FALSE;
                   1037: #endif /* MACH_TTD */
                   1038:                }
                   1039: 
                   1040:                if (isr_status & DSIS_TXE) {
                   1041:                        int tsr = inb(nic+ds0_tsr);
                   1042:                        tsr &= ~0x2;            /* unadvertised special */
                   1043: #if    MACH_TTD
                   1044:                        if (!kttd_active)
                   1045: #endif /* MACH_TTD */
                   1046:                        {
                   1047:                                if (tsr == (DSTS_CDH|DSTS_ABT))
                   1048:                                        ns8390_cntrs[unit].heart++;
                   1049:                                else
                   1050:                                        printf("%s%d intr(): isr = %x, TSR = %x\n",
                   1051:                                               ns8390_softc[unit].card, unit,
                   1052:                                               isr_status, tsr);
                   1053:                                ns8390_softc[unit].tbusy = 0;
                   1054:                                ns8390start(unit);
                   1055:                        }
                   1056:                } else if (isr_status & DSIS_TX) {
                   1057: #if    MACH_TTD
                   1058:                        if (!kttd_active)
                   1059: #endif /* MACH_TTD */
                   1060:                        {
                   1061:                                ns8390_cntrs[unit].xmti++;
                   1062:                                ns8390_softc[unit].tbusy = 0;
                   1063:                                ns8390start(unit);
                   1064:                        }
                   1065:                }
                   1066: 
                   1067:                if (isr_status & DSIS_CTRS) {
                   1068:                        int c0 = inb(nic+ds0_cntr0);
                   1069:                        int c1 = inb(nic+ds0_cntr1);
                   1070:                        int c2 = inb(nic+ds0_cntr2);
                   1071:                        ns8390_cntrs[unit].frame += c0;
                   1072:                        ns8390_cntrs[unit].crc += c1;
                   1073:                        ns8390_cntrs[unit].miss += c2;
                   1074: #ifdef COUNTERS
                   1075:                        printf("%s%d intr(): isr = %x, FRAME %x, CRC %x, MISS %x\n",
                   1076:                                ns8390_softc[unit].card, unit,
                   1077:                                isr_status, c0, c1, c2);
                   1078:                        printf("%s%d intr(): TOTAL   , FRAME %x, CRC %x, MISS %x\n",
                   1079:                                ns8390_softc[unit].card, unit,
                   1080:                                ns8390_cntrs[unit].frame,
                   1081:                                ns8390_cntrs[unit].crc,
                   1082:                                ns8390_cntrs[unit].miss);
                   1083: #endif COUNTERS
                   1084:                        outb(nic+ds0_isr, isr_status);  /* clear interrupt status again */
                   1085:                }
                   1086:        }
                   1087:        temp_cr=inb(nic+ds_cmd);
                   1088:        outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0);
                   1089:        outb(nic+ds0_imr, imr_hold);
                   1090:        outb(nic+ds_cmd, temp_cr);
                   1091:        return(0);
                   1092: }
                   1093: 
                   1094: /*
                   1095:  *  Called if on board buffer has been completely filled by ns8390intr.  It stops
                   1096:  *  the board, reads in all the buffers that are currently in the buffer, and
                   1097:  *  then restart board.
                   1098:  */
                   1099: ns8390over_write(unit)
                   1100: int unit;
                   1101: {
                   1102:        caddr_t nic = ns8390_softc[unit].nic;
                   1103:        int     no;
                   1104:        int     count = 0;
                   1105: 
                   1106:        outb(nic+ds_cmd, DSCM_NODMA|DSCM_STOP|DSCM_PG0);        /* clear the receive buffer */
                   1107:        outb(nic+ds0_rbcr0, 0);
                   1108:        outb(nic+ds0_rbcr1, 0);  
                   1109:        while ((!(inb (nic + ds0_isr) & DSIS_RESET)) && (count < 10000))
                   1110:                count++;
                   1111:        if (count == 10000) {
                   1112:                printf("%s%d: over_write(): would not reset.\n",
                   1113:                        ns8390_softc[unit].card, unit);
                   1114:        }
                   1115:        no = ns8390rcv(unit);
                   1116: #ifdef OVWBUG
                   1117:        printf("%s%d over_write(): ns8390 OVW ... %d.\n",
                   1118:                ns8390_softc[unit].card, unit, no);
                   1119: #endif OVWBUG
                   1120:        outb(nic+ds0_tcr, DSTC_LB0);    /* External loopback mode */
                   1121:        outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0);
                   1122:        outb(nic+ds0_tcr, 0);
                   1123:        return;
                   1124: }
                   1125: 
                   1126: /*
                   1127:  * ns8390rcv:
                   1128:  *
                   1129:  *     This routine is called by the interrupt handler to initiate a
                   1130:  *     packet transfer from the board to the "if" layer above this
                   1131:  *     driver.  This routine checks if a buffer has been successfully
                   1132:  *     received by the ns8390.  If so, it does the actual transfer of the
                   1133:  *      board data (including the ethernet header) into a packet (consisting
                   1134:  *      of an mbuf chain) and enqueues it to a higher level.
                   1135:  *      Then check again whether there are any packets in the receive ring,
                   1136:  *      if so, read the next packet, until there are no more.
                   1137:  *
                   1138:  * input       : number of the board to check
                   1139:  * output      : if a packet is available, it is "sent up"
                   1140:  */
                   1141: ns8390rcv(unit)
                   1142: int unit;
                   1143: {
                   1144:        register ns8390_softc_t *is = &ns8390_softc[unit];
                   1145:        register struct ifnet   *ifp = &is->ds_if;
                   1146:        caddr_t                 nic = is->nic;
                   1147:        int                     packets = 0;
                   1148:        struct ether_header     eh;
                   1149:        u_short                 mlen, len, bytes_in_mbuf, bytes;
                   1150:        u_short                 remaining;
                   1151:        int                     temp_cr;
                   1152:        u_char                  *mb_p;
                   1153:        int                     board_id = is->board_id;
                   1154:        vm_offset_t             hdwbase = ns8390info[unit]->address;
                   1155:        spl_t                   s;
                   1156: 
                   1157:        /* calculation of pkt size */
                   1158:        int nic_overcount;         /* NIC says 1 or 2 more than we need */
                   1159:        int pkt_size;              /* calculated size of received data */
                   1160:        int wrap_size;             /* size of data before wrapping it */
                   1161:        int header_nxtpkt_ptr;     /* NIC's next pkt ptr in rcv header */
                   1162:        int low_byte_count;        /* low byte count of read from rcv header */
                   1163:        int high_byte_count;       /* calculated high byte count */
                   1164: 
                   1165: 
                   1166:        volatile char *sram_nxtpkt_ptr;   /* mem location of next packet */
                   1167:        volatile char *sram_getdata_ptr;  /* next location to be read */
                   1168: #ifdef MACH_KERNEL
                   1169:        ipc_kmsg_t      new_kmsg;
                   1170:        struct ether_header *ehp;
                   1171:        struct packet_header *pkt;
                   1172: #else  MACH_KERNEL
                   1173:        struct mbuf *m, *tm;              /* initial allocation of mem; temp */
                   1174: #endif MACH_KERNEL
                   1175: 
                   1176: 
                   1177: #if    MACH_TTD
                   1178:        if (((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) &&
                   1179:            !kttd_active) {
                   1180: #else
                   1181:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
                   1182: #endif /* MACH_TTD */
                   1183:                temp_cr = inb(nic+ds_cmd); /* get current CR value */
                   1184:                outb(nic+ds_cmd,((temp_cr & 0x3F)|DSCM_PG0|DSCM_STOP));
                   1185:                outb(nic+ds0_imr, 0);      /* Interrupt Mask Register  */
                   1186:                outb(nic+ds_cmd, temp_cr);
                   1187:                return -1;
                   1188:        }
                   1189: 
                   1190:        while(is->read_nxtpkt_ptr != ns8390get_CURR(unit))   {
                   1191: 
                   1192:                /* while there is a packet to read from the buffer */
                   1193: 
                   1194:                if ((is->read_nxtpkt_ptr < is->pstart) ||
                   1195:                    (is->read_nxtpkt_ptr >= is->pstop)) {
                   1196:                        ns8390hwrst(unit);
                   1197:                        return -1;
                   1198:                }    /* if next packet pointer is out of receive ring bounds */
                   1199: 
                   1200: #if    MACH_TTD
                   1201:                if (!kttd_active)
                   1202: #endif /* MACH_TTD */
                   1203:                {
                   1204:                        packets++;
                   1205:                        ns8390_cntrs[unit].rcv++;
                   1206:                }
                   1207: 
                   1208:                sram_nxtpkt_ptr = (char *) (is->sram + (is->read_nxtpkt_ptr << 8));
                   1209: 
                   1210:                /* get packet size and location of next packet */
                   1211:                header_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
                   1212:                header_nxtpkt_ptr &= 0xFF;
                   1213:                low_byte_count = *(sram_nxtpkt_ptr + 2);
                   1214:                low_byte_count &= 0xFF;
                   1215: 
                   1216:                if ((low_byte_count + NIC_HEADER_SIZE) > NIC_PAGE_SIZE)
                   1217:                        nic_overcount = 2;
                   1218:                else
                   1219:                        nic_overcount = 1;
                   1220:                if (header_nxtpkt_ptr > is->read_nxtpkt_ptr) {
                   1221:                        wrap_size = 0;
                   1222:                        high_byte_count = header_nxtpkt_ptr - is->read_nxtpkt_ptr -
                   1223:                            nic_overcount;
                   1224:                } else {
                   1225:                        wrap_size = (int) (is->pstop - is->read_nxtpkt_ptr - nic_overcount);
                   1226:                        high_byte_count = is->pstop - is->read_nxtpkt_ptr +
                   1227:                            header_nxtpkt_ptr - is->pstart - nic_overcount;
                   1228:                }
                   1229:                pkt_size = (high_byte_count << 8) | (low_byte_count & 0xFF);
                   1230:                /* does not seem to include NIC_HEADER_SIZE */
                   1231:                if (!pkt_size) {
                   1232:                        printf("%s%d rcv(): zero length.\n",
                   1233:                                ns8390_softc[unit].card, unit);
                   1234:                        goto next_pkt;
                   1235:                }
                   1236:                len = pkt_size;
                   1237: 
                   1238:                sram_getdata_ptr = sram_nxtpkt_ptr + NIC_HEADER_SIZE;
                   1239:                if (board_id & IFWD_SLOT_16BIT) {
                   1240: #if    MACH_TTD
                   1241:                        if (!kttd_active)
                   1242: #endif /* MACH_TTD */
                   1243:                        { s = splhi(); }
                   1244: 
                   1245:                        en_16bit_access(hdwbase, board_id);
                   1246:                        bcopy16 (sram_getdata_ptr,
                   1247:                                 &eh,
                   1248:                                 sizeof(struct ether_header));
                   1249:                        dis_16bit_access (hdwbase, board_id);
                   1250: #if    MACH_TTD
                   1251:                        if (!kttd_active)
                   1252: #endif /* MACH_TTD */
                   1253:                        { splx(s); }
                   1254: 
                   1255:                } else {
                   1256:                        bcopy16 (sram_getdata_ptr,
                   1257:                                 &eh,
                   1258:                                 sizeof(struct ether_header));
                   1259:                }                   
                   1260:                sram_getdata_ptr += sizeof(struct ether_header);
                   1261:                len -= (sizeof(struct ether_header) + 4);       /* crc size */
                   1262: #ifdef MACH_KERNEL
                   1263: #if    MACH_TTD
                   1264:                if (kttd_active) {
                   1265:                        new_kmsg = (ipc_kmsg_t)ttd_request_msg;
                   1266:                }else
                   1267: #endif /* MACH_TTD */
                   1268:                {
                   1269:                        new_kmsg = net_kmsg_get();
                   1270:                        if (new_kmsg == IKM_NULL) {
                   1271:                                /*
                   1272:                                 * Drop the packet.
                   1273:                                 */
                   1274:                                is->ds_if.if_rcvdrops++;    
                   1275:                                /*
                   1276:                                 * not only do we want to return, we need to drop
                   1277:                                 * the packet on the floor to clear the interrupt.
                   1278:                                 */
                   1279:                                ns8390lost_frame(unit);
                   1280:                                return;/* packets;*/
                   1281:                        }
                   1282:                }
                   1283: 
                   1284: #if    DEBUG_TTD
                   1285:                dump_ether_header("ns8390wire",&eh);
                   1286: #endif /* DEBUG_TTD */
                   1287: 
                   1288:                ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]);
                   1289:                pkt = (struct packet_header *) (&net_kmsg(new_kmsg)->packet[0]);
                   1290: 
                   1291: #if    DEBUG_TTD
                   1292:                printf("!ehp = 0x%x, pkt = 0x%x!",ehp, pkt);
                   1293: #endif /* DEBUG_TTD */
                   1294: 
                   1295:                *ehp = eh;
                   1296:                if (len >
                   1297:                    (wrap_size = (is->sram + (is->pstop << 8) - sram_getdata_ptr))) {
                   1298:                        /* if needs to wrap */
                   1299:                        if (board_id & IFWD_SLOT_16BIT) {
                   1300: #if    MACH_TTD
                   1301:                                if (!kttd_active)
                   1302: #endif /* MACH_TTD */
                   1303:                                { s = splhi(); }
                   1304: 
                   1305:                                en_16bit_access(hdwbase, board_id);
                   1306:                                bcopy16 (sram_getdata_ptr, (char *) (pkt + 1),
                   1307:                                         wrap_size);
                   1308:                                dis_16bit_access (hdwbase, board_id);
                   1309: #if    MACH_TTD
                   1310:                                if (!kttd_active)
                   1311: #endif /* MACH_TTD */
                   1312:                                { splx(s); }
                   1313:                        } else {
                   1314:                                bcopy (sram_getdata_ptr, (char *) (pkt + 1),
                   1315:                                       wrap_size);
                   1316:                        }
                   1317:                        sram_getdata_ptr = (volatile char *)
                   1318:                            (is->sram + (is->pstart << 8));
                   1319:                } else {   /* normal getting data from buffer */
                   1320:                        wrap_size = 0;
                   1321:                }
                   1322:                if (board_id & IFWD_SLOT_16BIT) {
                   1323: #if    MACH_TTD
                   1324:                        if (!kttd_active)
                   1325: #endif /* MACH_TTD */
                   1326:                        { s = splhi(); }
                   1327:                        en_16bit_access(hdwbase, board_id);
                   1328:                        bcopy16 (sram_getdata_ptr,
                   1329:                                 (char *) (pkt + 1) + wrap_size,
                   1330:                                 len - wrap_size);
                   1331:                        dis_16bit_access (hdwbase, board_id);
                   1332: #if    MACH_TTD
                   1333:                        if (!kttd_active)
                   1334: #endif /* MACH_TTD */
                   1335:                        { splx(s); }
                   1336:                } else {
                   1337:                        bcopy (sram_getdata_ptr,
                   1338:                               (char *) (pkt + 1) + wrap_size,
                   1339:                               len - wrap_size);
                   1340:                }
                   1341: 
                   1342:                pkt->type = ehp->ether_type;
                   1343:                pkt->length = len + sizeof(struct packet_header);
                   1344: 
                   1345: #if    MACH_TTD
                   1346:                /*
                   1347:                 * Don't want to call net_packet if we are polling
                   1348:                 * for a packet.
                   1349:                 */
                   1350:                if (!kttd_active)
                   1351: #endif /* MACH_TTD */
                   1352:                {
                   1353:                        /*
                   1354:                         * Hand the packet to the network module.
                   1355:                         */
                   1356:                        net_packet(ifp, new_kmsg, pkt->length,
                   1357:                                   ethernet_priority(new_kmsg));
                   1358:                }
                   1359: 
                   1360: #else  MACH_KERNEL
                   1361: #define NEW
                   1362: #ifdef NEW
                   1363:                m = (struct mbuf *) 0;
                   1364:                eh.ether_type = ntohs(eh.ether_type);
                   1365:                MGET(m, M_DONTWAIT, MT_DATA);
                   1366:                if (m == (struct mbuf *) 0) {
                   1367:                        printf("%s%d rcv(): Lost frame\n",
                   1368:                                ns8390_softc[unit].card, unit);
                   1369:                        ns8390lost_frame(unit); /* update NIC pointers and registers */
                   1370:                        return packets;
                   1371:                }
                   1372:                m->m_next = (struct mbuf *) 0;
                   1373:                tm = m;
                   1374:                m->m_len = MLEN;
                   1375:                if (len > 2 * MLEN - sizeof (struct ifnet **)) {
                   1376:                        MCLGET(m);
                   1377:                }
                   1378:                *(mtod(tm, struct ifnet **)) = ifp;
                   1379:                mlen = sizeof (struct ifnet **);
                   1380:                bytes_in_mbuf = m->m_len - sizeof(struct ifnet **);
                   1381:                mb_p = mtod(tm, u_char *) + sizeof (struct ifnet **);
                   1382:                bytes = min(bytes_in_mbuf, len);
                   1383:                remaining =  (int) (is->sram + (is->pstop << 8) -
                   1384:                                    sram_getdata_ptr);
                   1385:                bytes = min(bytes, remaining);
                   1386:                do {
                   1387:                        if (board_id & IFWD_SLOT_16BIT) {
                   1388:                                s = splhi();
                   1389:                                en_16bit_access(hdwbase, board_id);
                   1390:                                bcopy16 (sram_getdata_ptr, mb_p, bytes);
                   1391:                                dis_16bit_access (hdwbase, board_id);
                   1392:                                splx(s);
                   1393:                        } else {
                   1394:                                bcopy16 (sram_getdata_ptr, mb_p, bytes);
                   1395:                        }
                   1396:                        
                   1397:                        mlen += bytes;
                   1398: 
                   1399:                        if (!(bytes_in_mbuf -= bytes)) {
                   1400:                                MGET(tm->m_next, M_DONTWAIT, MT_DATA);
                   1401:                                tm = tm->m_next;
                   1402:                                if (tm == (struct mbuf *)0) {
                   1403:                                        printf("%s%d rcv(): No mbufs, lost frame\n",
                   1404:                                                ns8390_softc[unit].card, unit);
                   1405:                                        m_freem(m);              /* free the mbuf chain */
                   1406:                                        ns8390lost_frame(unit);  /* update NIC pointers and registers */
                   1407:                                        return;
                   1408:                                }
                   1409:                                mlen = 0;
                   1410:                                tm->m_len = MLEN;
                   1411:                                bytes_in_mbuf = MLEN;
                   1412:                                mb_p = mtod(tm, u_char *);
                   1413:                        } else
                   1414:                                mb_p += bytes;
                   1415: 
                   1416:                        if (!(len  -= bytes)) {
                   1417:                                tm->m_len = mlen;
                   1418:                                break;
                   1419:                        } else if (bytes == remaining) {
                   1420:                                sram_getdata_ptr = (volatile char *) (is->sram +
                   1421:                                    (is->pstart << 8));
                   1422:                                bytes = len;
                   1423:                                remaining = ETHERMTU;
                   1424:                        } else {
                   1425:                                sram_getdata_ptr += bytes;
                   1426:                                remaining -= bytes;
                   1427:                        }
                   1428: 
                   1429:                        bytes = min(bytes_in_mbuf, len);
                   1430:                        bytes = min(bytes, remaining);
                   1431:                } while(1);
                   1432: #else  NEW
                   1433:                m = (struct mbuf *) 0;
                   1434:                eh.ether_type = ntohs(eh.ether_type);
                   1435: 
                   1436:                while ( len ) {
                   1437:                        if (m == (struct mbuf *) 0) {
                   1438:                                m = m_get(M_DONTWAIT, MT_DATA);
                   1439:                                if (m == (struct mbuf *) 0) {
                   1440:                                        printf("%s%d rcv(): Lost frame\n",
                   1441:                                        ns8390_softc[unit].card, unit);
                   1442:                                        ns8390lost_frame(unit); /* update NIC pointers and registers */
                   1443:                                        return packets;
                   1444:                                }
                   1445:                                tm = m;
                   1446:                                tm->m_off = MMINOFF;
                   1447: 
                   1448: 
                   1449:                                /*
                   1450:                                 * first mbuf in the packet must contain a pointer to the
                   1451:                                 * ifnet structure.  other mbufs that follow and make up
                   1452:                                 * the packet do not need this pointer in the mbuf.
                   1453:                                 *
                   1454:                                 */
                   1455: 
                   1456:                                *(mtod(tm, struct ifnet **)) = ifp;
                   1457:                                tm->m_len = sizeof(struct ifnet **);
                   1458: 
                   1459:                        /* end of first buffer of packet */
                   1460:                        } else {
                   1461:                                tm->m_next = m_get(M_DONTWAIT, MT_DATA);
                   1462:                                tm = tm->m_next;
                   1463:                                if (tm == (struct mbuf *) 0) {
                   1464:                                        printf("%s%d rcv(): No mbufs, lost frame\n",
                   1465:                                                ns8390_softc[unit].card, unit);
                   1466:                                        m_freem(m);              /* free the mbuf chain */
                   1467:                                        ns8390lost_frame(unit);  /* update NIC pointers and registers */
                   1468:                                        return packets;
                   1469:                                }
                   1470:                                tm->m_off = MMINOFF;
                   1471:                                tm->m_len = 0;
                   1472:                        }
                   1473: 
                   1474:                        tlen = MIN( MLEN - tm->m_len, len);
                   1475:                        /* size of mbuf so you know how much you can copy from board */
                   1476:                        tm->m_next = (struct mbuf *) 0;
                   1477:                        if (sram_getdata_ptr + tlen >=
                   1478:                            (volatile char *) (is->sram + (is->pstop << 8))) {
                   1479:                                /* if needs to wrap */
                   1480:                                wrap_size = (int) (is->sram + (is->pstop << 8) -
                   1481:                                    sram_getdata_ptr);
                   1482:                                if (board_id & IFWD_SLOT_16BIT) {
                   1483:                                        s = splhi();
                   1484:                                        en_16bit_access(hdwbase, board_id);
                   1485:                                        bcopy16 (sram_getdata_ptr,
                   1486:                                                 mtod(tm, char*) + tm->m_len,
                   1487:                                                 wrap_size);
                   1488:                                        dis_16bit_access (hdwbase, board_id);
                   1489:                                        splx(s);
                   1490:                                } else {
                   1491:                                        bcopy16 (sram_getdata_ptr,
                   1492:                                                 mtod(tm, char*) + tm->m_len,
                   1493:                                                 wrap_size);
                   1494:                                }
                   1495:                                tm->m_len += wrap_size;
                   1496:                                len -= wrap_size;
                   1497: 
                   1498:                                sram_getdata_ptr = (volatile char *) (is->sram +
                   1499:                                    (is->pstart << 8));
                   1500:                        } else {   /* normal getting data from buffer */
                   1501:                                if (board_id & IFWD_SLOT_16BIT) {
                   1502:                                        s = splhi();
                   1503:                                        en_16bit_access(hdwbase, board_id);
                   1504:                                        bcopy16 (sram_getdata_ptr,
                   1505:                                                 mtod(tm, char*) + tm->m_len,
                   1506:                                                 tlen);
                   1507:                                        dis_16bit_access (hdwbase, board_id);
                   1508:                                        splx(s);
                   1509:                                } else {
                   1510:                                        bcopy16 (sram_getdata_ptr,
                   1511:                                                 mtod(tm, char*) + tm->m_len,
                   1512:                                                 tlen);
                   1513:                                }
                   1514:                                sram_getdata_ptr += tlen;
                   1515:                                tm->m_len += tlen;
                   1516:                                len -= tlen;
                   1517: 
                   1518:                              }
                   1519:                }
                   1520: 
                   1521: #endif NEW
                   1522:                if (!ns8390send_packet_up(m, &eh, is))
                   1523:                        m_freem(m);
                   1524: #ifdef IF_CNTRS
                   1525:                ns_ein[log_2(pkt_size)]++;
                   1526:                if (pkt_size < 128) ns_lin[(pkt_size)>>3]++;
                   1527: 
                   1528:                if (eh.ether_type == ETHERTYPE_ARP) {
                   1529:                        ns_arp++;
                   1530:                        if (ns_narp) {
                   1531:                                ns_ein[log_2(pkt_size)]--;
                   1532:                                if (pkt_size < 128) ns_lin[(pkt_size)>>3]--;
                   1533:                        }
                   1534:                }
                   1535: #endif IF_CNTRS
                   1536: #endif MACH_KERNEL
                   1537: 
                   1538: next_pkt:
                   1539:                is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
                   1540:                is->read_nxtpkt_ptr &= 0xFF;
                   1541: 
                   1542: #if    MACH_TTD
                   1543:                if (!kttd_active)
                   1544: #endif /* MACH_TTD */
                   1545:                {
                   1546:                        temp_cr = inb(nic+ds_cmd);
                   1547:                        outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0);
                   1548:                }
                   1549: 
                   1550:                if (is->read_nxtpkt_ptr == ns8390get_CURR(unit))
                   1551:                        if (is->read_nxtpkt_ptr == is->pstart)
                   1552:                                outb(nic+ds0_bndy, is->pstop - 1);
                   1553:                        else
                   1554:                                outb(nic+ds0_bndy, is->read_nxtpkt_ptr - 1);
                   1555:                else
                   1556:                        outb(nic+ds0_bndy, is->read_nxtpkt_ptr);
                   1557: 
                   1558: #if    MACH_TTD
                   1559:                if (!kttd_active)
                   1560: #endif /* MACH_TTD */
                   1561:                { outb(nic+ds_cmd, temp_cr); }
                   1562: 
                   1563: #if    MACH_TTD
                   1564:                /*
                   1565:                 * Hand the packet back to the TTD server, if active.
                   1566:                 */
                   1567:                if (kttd_active && pkt_size)
                   1568:                        return 1;
                   1569: #endif /* MACH_TTD */
                   1570: 
                   1571: 
                   1572:        }
                   1573:        return packets;
                   1574: 
                   1575: }
                   1576: 
                   1577: #ifdef MACH_KERNEL
                   1578: #if    MACH_TTD
                   1579: /*
                   1580:  * Polling routines for the TTD debugger.
                   1581:  */
                   1582: int ns8390poll_receive(unit)
                   1583:        int     unit;
                   1584: {
                   1585:        int s;
                   1586:        int orig_cr;
                   1587:        int orig_imr;
                   1588:        int isr_status;
                   1589:        int pkts;
                   1590:        
                   1591:        ttd_poll_loop = TRUE;
                   1592: 
                   1593:        
                   1594:        /*
                   1595:         * Should already in at splhigh.  Is this necessary? XXX
                   1596:         */
                   1597:        s = splhigh();
                   1598: 
                   1599: #if    0
                   1600:        if (kttd_debug)
                   1601:                printf("ns8390poll_receive: beginning polling loop\n");
                   1602: #endif /* DEBUG_TTD */
                   1603: 
                   1604:        /*
                   1605:         * Loop until packet arrives.
                   1606:         */
                   1607:        while(ttd_poll_loop) {
                   1608: 
                   1609:                /*
                   1610:                 * Call intr routine
                   1611:                 */
                   1612: 
                   1613:                ns8390intr(unit);
                   1614:        }
                   1615: 
                   1616: #if    0
                   1617:        if (kttd_debug)
                   1618:                printf("ns8390poll_receive: got packet exiting loop\n");
                   1619: #endif /* DEBUG_TTD */
                   1620: 
                   1621:        splx(s);
                   1622: }
                   1623: 
                   1624: int ns8390transmit_ttd(unit, packet, len)
                   1625:        int unit;
                   1626:        char * packet;
                   1627:        int len;
                   1628: {
                   1629:        ns8390_softc_t  *is = &ns8390_softc[unit];
                   1630:        caddr_t         nic = is->nic;
                   1631:        u_short         count = 0;      /* amount of data already copied */
                   1632:        volatile char   *sram_write_pkt;
                   1633:        int             board_id = is->board_id;
                   1634:        caddr_t         hdwbase = ns8390info[unit]->address;
                   1635:        int             s;
                   1636:        int             orig_cr;
                   1637:        int             orig_imr;
                   1638:        int             isr_status;
                   1639:        boolean_t       loop = TRUE;
                   1640: 
                   1641: #if    0
                   1642:        dump_ipudpbootp("Beg of xmit",packet);
                   1643: #endif
                   1644: 
                   1645:        s = splhigh();
                   1646: 
                   1647:        /* begining of physical address of transmition buffer */
                   1648: 
                   1649:        sram_write_pkt = is->sram + is->tpsr * 0x100; 
                   1650: 
                   1651:        count = len;
                   1652:        if (board_id & IFWD_SLOT_16BIT) {
                   1653:                en_16bit_access(hdwbase, board_id);
                   1654:                bcopy16 (packet, sram_write_pkt,  count);
                   1655:                dis_16bit_access (hdwbase, board_id);
                   1656:        } else {
                   1657:                bcopy (packet, sram_write_pkt,  count);
                   1658:        }
                   1659: 
                   1660:        while (count < ETHERMIN+sizeof(struct ether_header)) {
                   1661:                *(sram_write_pkt + count) = 0;
                   1662:                count++;
                   1663:        }
                   1664:        outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0);               /* select page 0 */
                   1665:        outb(nic+ds0_tpsr, is->tpsr);           /* xmt page start at 0 of RAM */
                   1666:        outb(nic+ds0_tbcr1, count >> 8);                /* upper byte of count */
                   1667:        outb(nic+ds0_tbcr0, count & 0xFF);              /* lower byte of count */
                   1668:        outb(nic+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);             /* start transmission */
                   1669: 
                   1670:        ns8390intr(unit);
                   1671: 
                   1672:        splx(s);
                   1673: }
                   1674: #endif /* MACH_TTD */
                   1675: #endif /* MACH_KERNEL */
                   1676: 
                   1677: #ifdef MACH_KERNEL
                   1678: #else  MACH_KERNEL
                   1679: /*
                   1680:  * Send a packet composed of an mbuf chain to the higher levels
                   1681:  *
                   1682:  */
                   1683: ns8390send_packet_up(m, eh, is)
                   1684: struct mbuf *m;
                   1685: struct ether_header *eh;
                   1686: ns8390_softc_t *is;
                   1687: {
                   1688:        register struct ifqueue *inq;
                   1689:        spl_t                   opri;
                   1690: 
                   1691:        switch (eh->ether_type) {
                   1692: #ifdef INET
                   1693:        case ETHERTYPE_IP:
                   1694:                schednetisr(NETISR_IP);
                   1695:                inq = &ipintrq;
                   1696:                break;
                   1697:        case ETHERTYPE_ARP:
                   1698:                arpinput(&is->ns8390_ac, m);
                   1699:                return(TRUE);
                   1700: #endif
                   1701: #ifdef NS
                   1702:        case ETHERTYPE_NS:
                   1703:                schednetisr(NETISR_NS);
                   1704:                inq = &nsintrq;
                   1705:                break;
                   1706: #endif
                   1707:        default:
                   1708:                return(FALSE);
                   1709:        }
                   1710:        opri = SPLNET();
                   1711:        if (IF_QFULL(inq)) {
                   1712:                IF_DROP(inq);
                   1713:                splx(opri);
                   1714:                return(FALSE);
                   1715:        }
                   1716:        IF_ENQUEUE(inq, m);
                   1717:        splx(opri);
                   1718:        return(TRUE);
                   1719: }
                   1720: #endif MACH_KERNEL
                   1721: 
                   1722: /*
                   1723:  *  ns8390lost_frame:
                   1724:  *  this routine called by ns8390read after memory for mbufs could not be
                   1725:  *  allocated.  It sets the boundary pointers and registers to the next
                   1726:  *  packet location.
                   1727:  */
                   1728: 
                   1729: ns8390lost_frame(unit)
                   1730: int unit;
                   1731: {
                   1732:        ns8390_softc_t *is = &ns8390_softc[unit];
                   1733:        caddr_t        nic = is->nic;
                   1734:        volatile char  *sram_nxtpkt_ptr;
                   1735:        int            temp_cr;
                   1736: 
                   1737: 
                   1738: 
                   1739:        sram_nxtpkt_ptr = (volatile char *) (is->sram +
                   1740:            (is->read_nxtpkt_ptr << 8));
                   1741: 
                   1742:        is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
                   1743:        is->read_nxtpkt_ptr &= 0xFF;
                   1744: 
                   1745:        temp_cr = inb(nic+ds_cmd);
                   1746:        outb(nic+ds_cmd, (temp_cr & 0x3f) | DSCM_PG0);
                   1747: 
                   1748:        /* update boundary register */
                   1749:        if (is->read_nxtpkt_ptr == ns8390get_CURR(unit))
                   1750:                if (is->read_nxtpkt_ptr == is->pstart)
                   1751:                        outb(nic+ds0_bndy, is->pstop - 1);
                   1752:                else
                   1753:                        outb(nic+ds0_bndy, is->read_nxtpkt_ptr - 1);
                   1754:        else
                   1755:                outb(nic+ds0_bndy, is->read_nxtpkt_ptr);
                   1756: 
                   1757:        outb(nic+ds_cmd, temp_cr);
                   1758: 
                   1759:        return;
                   1760: }
                   1761: 
                   1762: /*
                   1763:  * ns8390get_CURR():
                   1764:  *
                   1765:  * Returns the value of the register CURR, which points to the next
                   1766:  * available space for NIC to receive from network unto receive ring.
                   1767:  *
                   1768:  */
                   1769: 
                   1770: int
                   1771: ns8390get_CURR(unit)
                   1772: int unit;
                   1773: {
                   1774:        caddr_t nic = ns8390_softc[unit].nic;
                   1775:        int     temp_cr;
                   1776:        int     ret_val;
                   1777:        spl_t   s;
                   1778:   
                   1779:        s = SPLNET();
                   1780: 
                   1781:        temp_cr = inb(nic+ds_cmd);                  /* get current CR value */
                   1782:        outb(nic+ds_cmd, ((temp_cr & 0x3F) | DSCM_PG1)); /* select page 1 registers */
                   1783:        ret_val = inb(nic+ds1_curr);                /* read CURR value */
                   1784:        outb(nic+ds_cmd, temp_cr);
                   1785:        splx(s);
                   1786:        return (ret_val & 0xFF);
                   1787: }
                   1788: 
                   1789: /*
                   1790:  * ns8390xmt:
                   1791:  *
                   1792:  *     This routine fills in the appropriate registers and memory
                   1793:  *     locations on the ns8390 board and starts the board off on
                   1794:  *     the transmit.
                   1795:  *
                   1796:  * input       : board number of interest, and a pointer to the mbuf
                   1797:  * output      : board memory and registers are set for xfer and attention
                   1798:  *
                   1799:  */
                   1800: 
                   1801: ns8390xmt(unit, m)
                   1802: int    unit;
                   1803: #ifdef MACH_KERNEL
                   1804: io_req_t       m;
                   1805: #else  MACH_KERNEL
                   1806: struct mbuf    *m;
                   1807: #endif MACH_KERNEL
                   1808: {
                   1809:        ns8390_softc_t          *is = &ns8390_softc[unit];
                   1810:        caddr_t                 nic = is->nic;
                   1811:        struct ether_header     *eh;
                   1812:        int                     i;
                   1813:        int                     opri;
                   1814:        u_short                 count = 0;      /* amount of data already copied */
                   1815:        volatile char           *sram_write_pkt;
                   1816:        int                     board_id = is->board_id;
                   1817:        vm_offset_t             hdwbase = ns8390info[unit]->address;
                   1818:        spl_t     s;
                   1819: 
                   1820: #ifdef MACH_KERNEL
                   1821: #else  MACH_KERNEL
                   1822:        register struct mbuf    *tm_p;
                   1823: #endif MACH_KERNEL
                   1824:        /* begining of physical address of transmition buffer */
                   1825: 
                   1826:        sram_write_pkt = is->sram + is->tpsr * 0x100; 
                   1827: 
                   1828: #ifdef MACH_KERNEL
                   1829:        count = m->io_count;
                   1830:        if (board_id & IFWD_SLOT_16BIT) {
                   1831:                s = splhi();
                   1832:                en_16bit_access(hdwbase, board_id);
                   1833:                bcopy16 (m->io_data, sram_write_pkt,  count);
                   1834:                dis_16bit_access (hdwbase, board_id);
                   1835:                splx(s);
                   1836:        } else {
                   1837:                bcopy (m->io_data, sram_write_pkt,  count);
                   1838:        }
                   1839: #else  MACH_KERNEL
                   1840:        for(tm_p = m; tm_p != (struct mbuf *)0; tm_p = tm_p->m_next)  {
                   1841:                if (count + tm_p->m_len > ETHERMTU + sizeof (struct ether_header))
                   1842:                        break;
                   1843:                if (tm_p->m_len == 0)
                   1844:                        continue;
                   1845:                if (board_id & IFWD_SLOT_16BIT) {
                   1846:                        s = splhi();
                   1847:                        en_16bit_access(hdwbase, board_id);
                   1848:                        bcopy16 (mtod(tm_p, caddr_t),
                   1849:                                 sram_write_pkt + count,
                   1850:                                 tm_p->m_len);
                   1851:                        dis_16bit_access (hdwbase, board_id);
                   1852:                        splx(s);
                   1853:                } else {
                   1854:                        bcopy16 (mtod(tm_p, caddr_t),
                   1855:                                 sram_write_pkt + count,
                   1856:                                 tm_p->m_len);
                   1857:                }
                   1858:                count += tm_p->m_len;
                   1859:        }
                   1860: #ifdef IF_CNTRS
                   1861:        ns_eout[log_2(count+4/*crc*/)]++;
                   1862:        if (count < 128)  ns_lout[(count+4/*crc*/)>>3]++;
                   1863: #endif IF_CNTRS
                   1864: #endif MACH_KERNEL
                   1865:        while (count < ETHERMIN+sizeof(struct ether_header)) {
                   1866:                *(sram_write_pkt + count) = 0;
                   1867:                count++;
                   1868:        }
                   1869: 
                   1870:        /* select page 0 */
                   1871:        outb(nic+ds_cmd, DSCM_NODMA|DSCM_START|DSCM_PG0);
                   1872:        outb(nic+ds0_tpsr, is->tpsr);   /* xmt page start at 0 of RAM */
                   1873:        outb(nic+ds0_tbcr1, count >> 8);        /* upper byte of count */
                   1874:        outb(nic+ds0_tbcr0, count & 0xFF);      /* lower byte of count */
                   1875:        /* start transmission */
                   1876:        outb(nic+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);     
                   1877: 
                   1878: #ifdef MACH_KERNEL
                   1879:        iodone(m);
                   1880:        m=0;
                   1881: #else  MACH_KERNEL
                   1882:        /* If this is a broadcast packet, loop it back to rcv.  */
                   1883:        eh = mtod( m, struct ether_header *);
                   1884:        for (i=0; ((i < 6) && (eh->ether_dhost[i] == 0xff)); i++)  ;
                   1885:        if (i == 6) {
                   1886:                if (!ns8390send_packet_up(m, eh, is))
                   1887:                        m_freem(m);
                   1888:        } else
                   1889:                m_freem(m);
                   1890: #endif MACH_KERNEL
                   1891:        return;
                   1892: }
                   1893: 
                   1894: config_nic(unit)
                   1895: int unit;
                   1896: {
                   1897:        ns8390_softc_t *is = &ns8390_softc[unit];
                   1898:        caddr_t   nic = is->nic;
                   1899:        int       i;
                   1900:        int       temp;
                   1901:        int       count = 0;
                   1902:        spl_t     s;
                   1903: 
                   1904:        /* soft reset and page 0 */
                   1905:        outb (nic+ds_cmd, DSCM_PG0|DSCM_NODMA|DSCM_STOP);             
                   1906: 
                   1907:        while ((!(inb (nic + ds0_isr) & DSIS_RESET)) && (count < 10000))
                   1908:                count++;
                   1909:        if (count == 10000) {
                   1910:                printf("%s%d: config_nic(): would not reset.\n",
                   1911:                        ns8390_softc[unit].card, unit);
                   1912:        }
                   1913: 
                   1914:        /* fifo depth | not loopback */
                   1915:        temp = ((is->fifo_depth & 0x0c) << 3) | DSDC_BMS;    
                   1916: 
                   1917:        /* word xfer select (16 bit cards ) */
                   1918:        if (is->board_id & IFWD_SLOT_16BIT)
                   1919:                temp |= DSDC_WTS;                       
                   1920: 
                   1921:        outb (nic+ds0_dcr, temp);
                   1922:        outb (nic+ds0_tcr, 0);
                   1923:        outb (nic+ds0_rcr, DSRC_MON);   /* receive configuration register */
                   1924:        /* recieve ring starts 2k into RAM */
                   1925:        outb (nic+ds0_pstart, is->pstart);      
                   1926:        /* stop at last RAM buffer rcv location */
                   1927:        outb (nic+ds0_pstop, is->pstop);        
                   1928: 
                   1929:        /* boundary pointer for page 0 */
                   1930:        outb (nic+ds0_bndy, is->pstart);        
                   1931:        s = SPLNET();
                   1932: 
                   1933:        /* maintain rst | sel page 1 */
                   1934:        outb (nic+ds_cmd, DSCM_PG1|DSCM_NODMA|DSCM_STOP);       
                   1935: 
                   1936:        /* internal next packet pointer */
                   1937:        is->read_nxtpkt_ptr = is->pstart + 1;   
                   1938: 
                   1939:        outb (nic+ds1_curr, is->read_nxtpkt_ptr);       /* Current page register */
                   1940:        for(i=0; i<ETHER_ADDR_SIZE; i++)
                   1941:                outb (nic+ds1_par0+i, is->address[i]);
                   1942:        for(i=0; i<8; i++)
                   1943:                outb (nic+ds1_mar0+i, 0);
                   1944: 
                   1945:        outb (nic+ds_cmd, DSCM_PG0|DSCM_STOP|DSCM_NODMA);
                   1946:        splx(s);
                   1947:        outb (nic+ds0_isr, 0xff);               /* clear all interrupt status bits */
                   1948:        outb (nic+ds0_imr, imr_hold);   /* Enable interrupts */
                   1949:        outb (nic+ds0_rbcr0, 0);        /* clear remote byte count */
                   1950:        outb (nic+ds0_rbcr1, 0);
                   1951: 
                   1952:        /* start NIC | select page 0 */
                   1953:        outb (nic+ds_cmd, DSCM_PG0|DSCM_START|DSCM_NODMA); 
                   1954: 
                   1955:        outb (nic+ds0_rcr, DSRC_AB);            /* receive configuration register */
                   1956: 
                   1957:        return TRUE;
                   1958: }
                   1959: 
                   1960: /*
                   1961:  * config_ns8390:
                   1962:  *
                   1963:  *     This routine does a standard config of a wd8003 family board, with
                   1964:  *      the proper modifications to different boards within this family.
                   1965:  *
                   1966:  */
                   1967: config_wd8003(unit)
                   1968: int    unit;
                   1969: {
                   1970:        ns8390_softc_t *is = &ns8390_softc[unit];
                   1971:        vm_offset_t   hdwbase = ns8390info[unit]->address;
                   1972:        int       i;
                   1973:        int       RAMsize;
                   1974:        volatile char  *RAMbase;
                   1975:        int       addr_temp;
                   1976: 
                   1977:        is->tpsr = 0;                   /* transmit page start hold */
                   1978:        is->pstart = 0x06;              /* receive page start hold */
                   1979:        is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
                   1980:        is->fifo_depth = 0x08;          /* NIC fifo threshold */
                   1981:        switch (is->board_id & IFWD_RAM_SIZE_MASK) {
                   1982:              case IFWD_RAM_SIZE_8K:  
                   1983:                RAMsize =  0x2000;      break;
                   1984:              case IFWD_RAM_SIZE_16K: 
                   1985:                RAMsize =  0x4000;      break;
                   1986:              case IFWD_RAM_SIZE_32K: 
                   1987:                RAMsize =  0x8000;      break;
                   1988:              case IFWD_RAM_SIZE_64K: 
                   1989:                RAMsize = 0x10000;      break;
                   1990:              default:           
                   1991:                RAMsize =  0x2000;      break;
                   1992:        }
                   1993:        is->pstop = (((int)RAMsize >> 8) & 0x0ff);      /* rcv page stop hold */
                   1994:        RAMbase = (volatile char *)ns8390info[unit]->phys_address;
                   1995:        addr_temp = ((int)(RAMbase) >> 13) & 0x3f; /* convert to be written to MSR */
                   1996:        outb(hdwbase+IFWD_MSR, addr_temp | IFWD_MENB); /* initialize MSR */
                   1997:        /* enable 16 bit access from lan controller */
                   1998:        if (is->board_id & IFWD_SLOT_16BIT) {
                   1999:                if (is->board_id & IFWD_INTERFACE_CHIP) {
                   2000:                        outb(hdwbase+IFWD_REG_5,
                   2001:                             (inb(hdwbase + IFWD_REG_5) & IFWD_REG5_MEM_MASK) |
                   2002:                             IFWD_LAN16ENB);
                   2003:                } else {
                   2004:                        outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19));
                   2005:                }
                   2006:        }
                   2007:        /*
                   2008:          outb(hdwbase+LAAR, LAN16ENB | LA19| MEM16ENB | SOFTINT);
                   2009:          */
                   2010:        
                   2011:        return TRUE;
                   2012: }
                   2013: 
                   2014: /*
                   2015:  * config_ns8390:
                   2016:  *
                   2017:  *     This routine does a standard config of a 3 com etherlink II board.
                   2018:  *
                   2019:  */
                   2020: int
                   2021: config_3c503(unit)
                   2022: int    unit;
                   2023: {
                   2024:        ns8390_softc_t  *is = &ns8390_softc[unit];
                   2025:        struct bus_device       *dev = ns8390info[unit];
                   2026:        vm_offset_t             hdwbase = dev->address;
                   2027:        int             RAMsize = dev->am;
                   2028:        int             i;
                   2029: 
                   2030:        is->tpsr =   0x20;              /* transmit page start hold */
                   2031:        is->sram = (char *)phystokv(dev->phys_address) - is->tpsr * 0x100;
                   2032:                                        /* When NIC says page 20, this means go to
                   2033:                                           the beginning of the sram range */
                   2034:        is->pstart = 0x26;              /* receive page start hold */
                   2035:        is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
                   2036:        is->fifo_depth = 0x08;          /* NIC fifo threshold */
                   2037:        is->pstop = is->tpsr + ((RAMsize >> 8) & 0x0ff);      /* rcv page stop hold */
                   2038: 
                   2039:        outb(hdwbase+CTLR, CTLR_RST|CTLR_THIN);
                   2040:        outb(hdwbase+CTLR, CTLR_THIN);
                   2041:        outb(hdwbase+CTLR, CTLR_STA_ADDR|CTLR_THIN);
                   2042:        for (i = 0; i < 6; i++)
                   2043:                is->address[i] = inb(hdwbase+i);
                   2044:        outb(hdwbase+CTLR, elii_bnc[is->board_id]?CTLR_THIN:CTLR_THICK);
                   2045:        outb(hdwbase+PSTR, is->pstart);
                   2046:        outb(hdwbase+PSPR, is->pstop);
                   2047:        outb(hdwbase+IDCFR, IDCFR_IRQ2 << (elii_irq[is->board_id] - 2));
                   2048:        outb(hdwbase+GACFR, GACFR_TCM|GACFR_8K);
                   2049:        /* BCFR & PCRFR ro */
                   2050:        /* STREG ro & dma */
                   2051:        outb(hdwbase+DQTR, 0);
                   2052:        outb(hdwbase+DAMSB, 0);
                   2053:        outb(hdwbase+DALSB, 0);
                   2054:        outb(hdwbase+VPTR2, 0);
                   2055:        outb(hdwbase+VPTR1, 0);
                   2056:        outb(hdwbase+VPTR0, 0);
                   2057:        outb(hdwbase+RFMSB, 0);
                   2058:        outb(hdwbase+RFLSB, 0);
                   2059:        return TRUE;
                   2060: }
                   2061: 
                   2062: /*
                   2063:  * ns8390intoff:
                   2064:  *
                   2065:  *     This function turns interrupts off for the ns8390 board indicated.
                   2066:  *
                   2067:  */
                   2068: void
                   2069: ns8390intoff(unit)
                   2070: int unit;
                   2071: {
                   2072:        caddr_t nic = ns8390_softc[unit].nic;
                   2073:        int temp_cr = inb(nic+ds_cmd);  /* get current CR value */
                   2074: 
                   2075:        outb(nic+ds_cmd,((temp_cr & 0x3F)|DSCM_PG0|DSCM_STOP));
                   2076:        outb(nic+ds0_imr, 0);                   /* Interrupt Mask Register  */
                   2077:        outb(nic+ds_cmd, temp_cr|DSCM_STOP);
                   2078: 
                   2079: }
                   2080: 
                   2081: 
                   2082: /*
                   2083:  *   wd80xxget_board_id:
                   2084:  *
                   2085:  *   determine which board is being used.
                   2086:  *   Currently supports:
                   2087:  *    wd8003E (tested)
                   2088:  *    wd8003EBT
                   2089:  *    wd8003EP (tested)
                   2090:  *    wd8013EP (tested)
                   2091:  *
                   2092:  */
                   2093: wd80xxget_board_id(dev)
                   2094: struct bus_device      *dev;
                   2095: {
                   2096:        vm_offset_t    hdwbase = dev->address;
                   2097:        long           unit = dev->unit;
                   2098:        long           board_id = 0;
                   2099:        int            reg_temp;
                   2100:        int            rev_num;                 /* revision number */
                   2101:        int            ram_flag;
                   2102:        int            intr_temp;
                   2103:        int            i;
                   2104:        boolean_t      register_aliasing;
                   2105: 
                   2106:        rev_num = (inb(hdwbase + IFWD_BOARD_ID) & IFWD_BOARD_REV_MASK) >> 1;
                   2107:        printf("%s%d: ", ns8390_softc[unit].card, unit);
                   2108:        
                   2109:        if (rev_num == 0) {
                   2110:                printf("rev 0x00\n");
                   2111:                /* It must be 8000 board */
                   2112:                return 0;
                   2113:        }
                   2114:        
                   2115:        /* Check if register aliasing is true, that is reading from register
                   2116:           offsets 0-7 will return the contents of register offsets 8-f */
                   2117:        
                   2118:        register_aliasing = TRUE;
                   2119:        for (i = 1; i < 5; i++) {
                   2120:                if (inb(hdwbase + IFWD_REG_0 + i) !=
                   2121:                    inb(hdwbase + IFWD_LAR_0 + i))
                   2122:                    register_aliasing = FALSE;
                   2123:        }
                   2124:        if (inb(hdwbase + IFWD_REG_7) != inb(hdwbase + IFWD_CHKSUM))
                   2125:            register_aliasing = FALSE;
                   2126:        
                   2127:        
                   2128:        if (register_aliasing == FALSE) {
                   2129:                /* Check if board has interface chip */
                   2130:                
                   2131:                reg_temp = inb(hdwbase + IFWD_REG_7);   /* save old */
                   2132:                outb(hdwbase + IFWD_REG_7, 0x35);       /* write value */
                   2133:                inb(hdwbase + IFWD_REG_0);              /* dummy read */
                   2134:                if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x35) {
                   2135:                        outb(hdwbase + IFWD_REG_7, 0x3a);/* Try another value*/
                   2136:                        inb(hdwbase + IFWD_REG_0);      /* dummy read */
                   2137:                        if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x3a) {
                   2138:                                board_id |= IFWD_INTERFACE_CHIP;
                   2139:                                outb(hdwbase + IFWD_REG_7, reg_temp);
                   2140:                                /* restore old value */
                   2141:                        }
                   2142:                }
                   2143:                
                   2144:                /* Check if board is 16 bit by testing if bit zero in
                   2145:                   register 1 is unchangeable by software. If so then
                   2146:                   card has 16 bit capability */
                   2147:                reg_temp = inb(hdwbase + IFWD_REG_1);
                   2148:                outb(hdwbase + IFWD_REG_1, reg_temp ^ IFWD_16BIT);
                   2149:                inb(hdwbase + IFWD_REG_0);                   /* dummy read */
                   2150:                if ((inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) ==
                   2151:                    (reg_temp & IFWD_16BIT)) {        /* Is bit unchanged */
                   2152:                        board_id |= IFWD_BOARD_16BIT; /* Yes == 16 bit */
                   2153:                        reg_temp &= 0xfe;             /* For 16 bit board
                   2154:                                                         always reset bit 0 */
                   2155:                }
                   2156:                outb(hdwbase + IFWD_REG_1, reg_temp);    /* write value back */
                   2157:                
                   2158:                /* Test if 16 bit card is in 16 bit slot by reading bit zero in
                   2159:                   register 1. */
                   2160:                if (board_id & IFWD_BOARD_16BIT) {
                   2161:                        if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) {
                   2162:                                board_id |= IFWD_SLOT_16BIT;
                   2163:                        }
                   2164:                }
                   2165:        }
                   2166:        
                   2167:        /* Get media type */
                   2168:        
                   2169:        if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEDIA_TYPE) {
                   2170:                board_id |= IFWD_ETHERNET_MEDIA;
                   2171:        } else if (rev_num == 1) {
                   2172:                board_id |= IFWD_STARLAN_MEDIA;
                   2173:        } else {
                   2174:                board_id |= IFWD_TWISTED_PAIR_MEDIA;
                   2175:        }
                   2176: 
                   2177:        if (rev_num == 2) {
                   2178:                if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_SOFT_CONFIG) {
                   2179:                        if ((board_id & IFWD_STATIC_ID_MASK) == WD8003EB ||
                   2180:                            (board_id & IFWD_STATIC_ID_MASK) == WD8003W) {
                   2181:                                board_id |= IFWD_ALTERNATE_IRQ_BIT;
                   2182:                        }
                   2183:                }
                   2184:                /* Check for memory size */
                   2185:                
                   2186:                ram_flag = inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEMSIZE;
                   2187:            
                   2188:                switch (board_id & IFWD_STATIC_ID_MASK) {
                   2189:                      case WD8003E: /* same as WD8003EBT */
                   2190:                      case WD8003S: /* same as WD8003SH */
                   2191:                      case WD8003WT:
                   2192:                      case WD8003W:
                   2193:                      case WD8003EB: /* same as WD8003EP */
                   2194:                        if (ram_flag)
                   2195:                            board_id |= IFWD_RAM_SIZE_32K;
                   2196:                        else
                   2197:                            board_id |= IFWD_RAM_SIZE_8K;
                   2198:                        break;
                   2199:                      case WD8003ETA:
                   2200:                      case WD8003STA:
                   2201:                      case WD8003EA:
                   2202:                      case WD8003SHA:
                   2203:                      case WD8003WA:
                   2204:                        board_id |= IFWD_RAM_SIZE_16K;
                   2205:                        break;
                   2206:                      case WD8013EBT:
                   2207:                        if (board_id & IFWD_SLOT_16BIT) {
                   2208:                                if (ram_flag)
                   2209:                                    board_id |= IFWD_RAM_SIZE_64K;
                   2210:                                else
                   2211:                                    board_id |= IFWD_RAM_SIZE_16K;
                   2212:                        } else {
                   2213:                                if (ram_flag)
                   2214:                                    board_id |= IFWD_RAM_SIZE_32K;
                   2215:                                else
                   2216:                                    board_id |= IFWD_RAM_SIZE_8K;
                   2217:                        }
                   2218:                        break;
                   2219:                      default:
                   2220:                        board_id |= IFWD_RAM_SIZE_UNKNOWN;
                   2221:                        break;
                   2222:                }
                   2223:        } else if (rev_num >= 3) {
                   2224:                board_id &= (long) ~IFWD_MEDIA_MASK;   /* remove media info */
                   2225:                board_id |= IFWD_INTERFACE_584_CHIP;
                   2226:                board_id |= wd80xxget_eeprom_info(hdwbase, board_id);
                   2227:        } else {
                   2228:                /* Check for memory size */
                   2229:                if (board_id & IFWD_BOARD_16BIT) {
                   2230:                        if (board_id & IFWD_SLOT_16BIT)
                   2231:                            board_id |= IFWD_RAM_SIZE_16K;
                   2232:                        else
                   2233:                            board_id |= IFWD_RAM_SIZE_8K;
                   2234:                } else if (board_id & IFWD_MICROCHANNEL)
                   2235:                    board_id |= IFWD_RAM_SIZE_16K;
                   2236:                else if (board_id & IFWD_INTERFACE_CHIP) {
                   2237:                        if (inb(hdwbase + IFWD_REG_1) & IFWD_MEMSIZE)
                   2238:                            board_id |= IFWD_RAM_SIZE_32K;
                   2239:                        else
                   2240:                            board_id |= IFWD_RAM_SIZE_8K;
                   2241:                } else
                   2242:                    board_id |= IFWD_RAM_SIZE_UNKNOWN;
                   2243:                
                   2244:                /* No support for 690 chip yet. It should be checked here */
                   2245:        }
                   2246:        
                   2247:        switch (board_id & IFWD_STATIC_ID_MASK) {
                   2248:              case WD8003E: printf("WD8003E or WD8003EBT"); break;
                   2249:              case WD8003S: printf("WD8003S or WD8003SH"); break;
                   2250:              case WD8003WT: printf("WD8003WT"); break;
                   2251:              case WD8003W: printf("WD8003W"); break;
                   2252:              case WD8003EB:
                   2253:                if (board_id & IFWD_INTERFACE_584_CHIP)
                   2254:                    printf("WD8003EP");
                   2255:                else
                   2256:                    printf("WD8003EB");
                   2257:                break;
                   2258:              case WD8003EW: printf("WD8003EW"); break;
                   2259:              case WD8003ETA: printf("WD8003ETA"); break;
                   2260:              case WD8003STA: printf("WD8003STA"); break;
                   2261:              case WD8003EA: printf("WD8003EA"); break;
                   2262:              case WD8003SHA: printf("WD8003SHA"); break;
                   2263:              case WD8003WA: printf("WD8003WA"); break;
                   2264:              case WD8013EBT: printf("WD8013EBT"); break;
                   2265:              case WD8013EB:
                   2266:                if (board_id & IFWD_INTERFACE_584_CHIP)
                   2267:                    printf("WD8013EP");
                   2268:                else
                   2269:                    printf("WD8013EB");
                   2270:                break;
                   2271:              case WD8013W: printf("WD8013W"); break;
                   2272:              case WD8013EW: printf("WD8013EW"); break;
                   2273:              default: printf("unknown"); break;
                   2274:        }
                   2275:        printf(" rev 0x%02x", rev_num);
                   2276:        switch(board_id & IFWD_RAM_SIZE_RES_7) {
                   2277:              case IFWD_RAM_SIZE_UNKNOWN:
                   2278:                break;
                   2279:              case IFWD_RAM_SIZE_8K:
                   2280:                printf(" 8 kB ram");
                   2281:                break;
                   2282:              case IFWD_RAM_SIZE_16K:
                   2283:                printf(" 16 kB ram");
                   2284:                break;
                   2285:              case IFWD_RAM_SIZE_32K:
                   2286:                printf(" 32 kB ram");
                   2287:                break;
                   2288:              case IFWD_RAM_SIZE_64K:
                   2289:                printf(" 64 kB ram");
                   2290:                break;
                   2291:              default:
                   2292:                printf("wd: Internal error ram size value invalid %d\n",
                   2293:                       (board_id & IFWD_RAM_SIZE_RES_7)>>16);
                   2294:        }
                   2295:        
                   2296:        if (board_id & IFWD_BOARD_16BIT) {
                   2297:                if (board_id & IFWD_SLOT_16BIT) {
                   2298:                        printf(", in 16 bit slot");
                   2299:                } else {
                   2300:                        printf(", 16 bit board in 8 bit slot");
                   2301:                }
                   2302:        }
                   2303:        if (board_id & IFWD_INTERFACE_CHIP) {
                   2304:                if (board_id & IFWD_INTERFACE_584_CHIP) {
                   2305:                        printf(", 584 chip");
                   2306:                } else {
                   2307:                        printf(", 583 chip");
                   2308:                }
                   2309:        }
                   2310:        if ((board_id & IFWD_INTERFACE_CHIP) == IFWD_INTERFACE_CHIP) {
                   2311:                /* program the WD83C583 EEPROM registers */
                   2312:                int irr_temp, icr_temp;
                   2313:                
                   2314:                icr_temp = inb(hdwbase + IFWD_ICR);
                   2315:                irr_temp = inb(hdwbase + IFWD_IRR);
                   2316:                
                   2317:                irr_temp &= ~(IFWD_IR0 | IFWD_IR1);
                   2318:                irr_temp |= IFWD_IEN;
                   2319:                
                   2320:                icr_temp &= IFWD_WTS;
                   2321:                
                   2322:                if (!(board_id & IFWD_INTERFACE_584_CHIP)) {
                   2323:                        icr_temp |= IFWD_DMAE | IFWD_IOPE;
                   2324:                        if (ram_flag)
                   2325:                            icr_temp |= IFWD_MSZ;
                   2326:                }
                   2327:                
                   2328:                if (board_id & IFWD_INTERFACE_584_CHIP) {
                   2329:                        switch(ns8390info[unit]->sysdep1) {
                   2330:                              case 10:
                   2331:                                icr_temp |= IFWD_DMAE;
                   2332:                                break;
                   2333:                              case 2:
                   2334:                              case 9: /* Same as 2 */
                   2335:                                break;
                   2336:                              case 11:
                   2337:                                icr_temp |= IFWD_DMAE;
                   2338:                                /*FALLTHROUGH*/
                   2339:                              case 3:
                   2340:                                irr_temp |= IFWD_IR0;
                   2341:                                break;
                   2342:                              case 15:
                   2343:                                icr_temp |= IFWD_DMAE;
                   2344:                                /*FALLTHROUGH*/
                   2345:                              case 5:
                   2346:                                irr_temp |= IFWD_IR1;
                   2347:                                break;
                   2348:                              case 4:
                   2349:                                icr_temp |= IFWD_DMAE;
                   2350:                                /*FALLTHROUGH*/
                   2351:                              case 7:
                   2352:                                irr_temp |= IFWD_IR0 | IFWD_IR1;
                   2353:                                break;
                   2354:                              default:
                   2355:                                printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n",
                   2356:                                       ns8390_softc[unit].card, unit,
                   2357:                                       ns8390info[unit]->sysdep1);
                   2358:                                break;
                   2359:                        }
                   2360:                } else {
                   2361:                        switch(ns8390info[unit]->sysdep1) {
                   2362:                                /* attempt to set interrupt according to assigned pic */
                   2363:                              case 2:
                   2364:                              case 9: /* Same as 2 */
                   2365:                                break;
                   2366:                              case 3:
                   2367:                                irr_temp |= IFWD_IR0;
                   2368:                                break;
                   2369:                              case 4:
                   2370:                                irr_temp |= IFWD_IR1;
                   2371:                                break;
                   2372:                              case 5:
                   2373:                                irr_temp |= IFWD_IR1 | IFWD_AINT;
                   2374:                                break;
                   2375:                              case 7: 
                   2376:                                irr_temp |= IFWD_IR0 | IFWD_IR1;
                   2377:                                break;
                   2378:                              default: 
                   2379:                                printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n",
                   2380:                                       ns8390_softc[unit].card, unit,
                   2381:                                       ns8390info[unit]->sysdep1);
                   2382:                        }
                   2383:                }
                   2384:                outb(hdwbase + IFWD_IRR, irr_temp);
                   2385:                outb(hdwbase + IFWD_ICR, icr_temp);
                   2386:        }
                   2387:        printf("\n");
                   2388:        return (board_id);
                   2389: }
                   2390: 
                   2391: wd80xxget_eeprom_info(hdwbase, board_id)
                   2392:      caddr_t   hdwbase;
                   2393:      long      board_id;
                   2394: {
                   2395:   unsigned long new_bits = 0;
                   2396:   int          reg_temp;
                   2397:   
                   2398:   outb(hdwbase + IFWD_REG_1,
                   2399:        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT));
                   2400:   outb(hdwbase + IFWD_REG_3,
                   2401:        ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_ENGR_PAGE));
                   2402:   outb(hdwbase + IFWD_REG_1,
                   2403:        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) |
                   2404:        (IFWD_RLA | IFWD_OTHER_BIT)));
                   2405:   while (inb(hdwbase + IFWD_REG_1) & IFWD_RECALL_DONE_MASK)
                   2406:       ;
                   2407:   
                   2408:   reg_temp = inb(hdwbase + IFWD_EEPROM_1);
                   2409:   switch (reg_temp & IFWD_EEPROM_BUS_TYPE_MASK) {
                   2410:        case IFWD_EEPROM_BUS_TYPE_AT:
                   2411:          if (wd_debug & 1) printf("wd: AT bus, ");
                   2412:          break;
                   2413:        case IFWD_EEPROM_BUS_TYPE_MCA:
                   2414:          if (wd_debug & 1) printf("wd: MICROCHANNEL, ");
                   2415:          new_bits |= IFWD_MICROCHANNEL;
                   2416:          break;
                   2417:        default:
                   2418:          break;
                   2419:   }
                   2420:   switch (reg_temp & IFWD_EEPROM_BUS_SIZE_MASK) {
                   2421:        case IFWD_EEPROM_BUS_SIZE_8BIT:
                   2422:          if (wd_debug & 1) printf("8 bit bus size, ");
                   2423:          break;
                   2424:        case IFWD_EEPROM_BUS_SIZE_16BIT:
                   2425:          if (wd_debug & 1) printf("16 bit bus size ");
                   2426:          new_bits |= IFWD_BOARD_16BIT;
                   2427:          if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) {
                   2428:                  new_bits |= IFWD_SLOT_16BIT;
                   2429:                  if (wd_debug & 1)
                   2430:                      printf("in 16 bit slot, ");
                   2431:          } else {
                   2432:                  if (wd_debug & 1)
                   2433:                      printf("in 8 bit slot (why?), ");
                   2434:          }
                   2435:          break;
                   2436:        default:
                   2437:          if (wd_debug & 1) printf("bus size other than 8 or 16 bit, ");
                   2438:          break;
                   2439:   }
                   2440:   reg_temp = inb(hdwbase + IFWD_EEPROM_0);
                   2441:   switch (reg_temp & IFWD_EEPROM_MEDIA_MASK) {
                   2442:        case IFWD_STARLAN_TYPE:
                   2443:          if (wd_debug & 1) printf("Starlan media, ");
                   2444:          new_bits |= IFWD_STARLAN_MEDIA;
                   2445:          break;
                   2446:        case IFWD_TP_TYPE:
                   2447:          if (wd_debug & 1) printf("Twisted pair media, ");
                   2448:          new_bits |= IFWD_TWISTED_PAIR_MEDIA;
                   2449:          break;
                   2450:        case IFWD_EW_TYPE:
                   2451:          if (wd_debug & 1) printf("Ethernet and twisted pair media, ");
                   2452:          new_bits |= IFWD_EW_MEDIA;
                   2453:          break;
                   2454:        case IFWD_ETHERNET_TYPE: /*FALLTHROUGH*/
                   2455:        default:
                   2456:          if (wd_debug & 1) printf("ethernet media, ");
                   2457:          new_bits |= IFWD_ETHERNET_MEDIA;
                   2458:          break;
                   2459:   }
                   2460:   switch (reg_temp & IFWD_EEPROM_IRQ_MASK) {
                   2461:        case IFWD_ALTERNATE_IRQ_1:
                   2462:          if (wd_debug & 1) printf("Alternate irq 1\n");
                   2463:          new_bits |= IFWD_ALTERNATE_IRQ_BIT;
                   2464:          break;
                   2465:        default:
                   2466:          if (wd_debug & 1) printf("\n");
                   2467:          break;
                   2468:   }
                   2469:   switch (reg_temp & IFWD_EEPROM_RAM_SIZE_MASK) {
                   2470:        case IFWD_EEPROM_RAM_SIZE_8K:
                   2471:          new_bits |= IFWD_RAM_SIZE_8K;
                   2472:          break;
                   2473:        case IFWD_EEPROM_RAM_SIZE_16K:
                   2474:          if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT))
                   2475:              new_bits |= IFWD_RAM_SIZE_16K;
                   2476:          else
                   2477:              new_bits |= IFWD_RAM_SIZE_8K;
                   2478:          break;
                   2479:        case IFWD_EEPROM_RAM_SIZE_32K:
                   2480:          new_bits |= IFWD_RAM_SIZE_32K;
                   2481:          break;
                   2482:        case IFWD_EEPROM_RAM_SIZE_64K:
                   2483:          if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT))
                   2484:              new_bits |= IFWD_RAM_SIZE_64K;
                   2485:          else
                   2486:              new_bits |= IFWD_RAM_SIZE_32K;
                   2487:          break;
                   2488:        default:
                   2489:          new_bits |= IFWD_RAM_SIZE_UNKNOWN;
                   2490:          break;
                   2491:   }
                   2492:   outb(hdwbase + IFWD_REG_1,
                   2493:        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT));
                   2494:   outb(hdwbase + IFWD_REG_3,
                   2495:        ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_EA6));
                   2496:   outb(hdwbase + IFWD_REG_1,
                   2497:        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_RLA));
                   2498:   return (new_bits);
                   2499: }
                   2500: 
                   2501: wdpr(unit)
                   2502: {
                   2503:        caddr_t nic = ns8390_softc[unit].nic;
                   2504:        spl_t   s;
                   2505:        int     temp_cr;
                   2506: 
                   2507:        s = SPLNET();
                   2508:        temp_cr = inb(nic+ds_cmd);      /* get current CR value */
                   2509: 
                   2510:        printf("CR %x, BNDRY %x, TSR %x, NCR %x, FIFO %x, ISR %x, RSR %x\n",
                   2511:                inb(nic+0x0), inb(nic+0x3), inb(nic+0x4), inb(nic+0x5),
                   2512:                inb(nic+0x6), inb(nic+0x7), inb(nic+0xc));
                   2513:        printf("CLD %x:%x, CRD %x:%x, FR %x, CRC %x, Miss %x\n",
                   2514:                inb(nic+0x1), inb(nic+0x2),
                   2515:                inb(nic+0x8), inb(nic+0x9),
                   2516:                inb(nic+0xd), inb(nic+0xe), inb(nic+0xf));
                   2517: 
                   2518:        
                   2519:        outb(nic, (temp_cr&0x3f)|DSCM_PG1);             /* page 1 CR value */
                   2520:        printf("PHYS %x:%x:%x:%x:%x CUR %x\n",
                   2521:                inb(nic+0x1), inb(nic+0x2), inb(nic+0x3),
                   2522:                inb(nic+0x4), inb(nic+0x5), inb(nic+0x6),
                   2523:                inb(nic+0x7));
                   2524:        printf("MAR %x:%x:%x:%x:%x:%x:%x:%x\n",
                   2525:                inb(nic+0x8), inb(nic+0x9), inb(nic+0xa), inb(nic+0xb),
                   2526:                inb(nic+0xc), inb(nic+0xd), inb(nic+0xe), inb(nic+0xf));
                   2527:        outb(nic, temp_cr);                     /* restore current CR value */
                   2528:        splx(s);
                   2529: }
                   2530: 
                   2531: 
                   2532: /*
                   2533:   This sets bit 7 (0 justified) of register offset 0x05. It will enable
                   2534:   the host to access shared RAM 16 bits at a time. It will also maintain
                   2535:   the LAN16BIT bit high in addition, this routine maintains address bit 19
                   2536:   (previous cards assumed this bit high...we must do it manually)
                   2537:   
                   2538:   note 1: this is a write only register
                   2539:   note 2: this routine should be called only after interrupts are disabled
                   2540:     and they should remain disabled until after the routine 'dis_16bit_access'
                   2541:     is called
                   2542: */
                   2543: 
                   2544: en_16bit_access (hdwbase, board_id)
                   2545:        caddr_t hdwbase;
                   2546:        long    board_id;
                   2547: {
                   2548:        if (board_id & IFWD_INTERFACE_CHIP)
                   2549:            outb(hdwbase+IFWD_REG_5,
                   2550:                 (inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK)
                   2551:                 | IFWD_MEM16ENB | IFWD_LAN16ENB);
                   2552:         else
                   2553:             outb(hdwbase+IFWD_REG_5, (IFWD_MEM16ENB | IFWD_LAN16ENB |
                   2554:                                      IFWD_LA19));
                   2555: }
                   2556: 
                   2557: /*
                   2558:   This resets bit 7 (0 justified) of register offset 0x05. It will disable
                   2559:   the host from accessing shared RAM 16 bits at a time. It will maintain the
                   2560:   LAN16BIT bit high in addition, this routine maintains address bit 19
                   2561:   (previous cards assumed this bit high...we must do it manually)
                   2562: 
                   2563:   note: this is a write only register
                   2564: */
                   2565: 
                   2566: dis_16bit_access (hdwbase, board_id)
                   2567:        caddr_t hdwbase;
                   2568:        long board_id;
                   2569: {
                   2570:        if (board_id & IFWD_INTERFACE_CHIP)
                   2571:            outb(hdwbase+IFWD_REG_5,
                   2572:                 ((inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK) |
                   2573:                  IFWD_LAN16ENB));
                   2574:        else
                   2575:            outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19));
                   2576: }
                   2577: 
                   2578: #endif

unix.superglobalmegacorp.com

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