Annotation of Gnu-Mach/i386/i386at/if_3c501.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: /*
                     27:  *     File:   if_3c501.c
                     28:  *     Author: Philippe Bernadat
                     29:  *     Date:   1989
                     30:  *     Copyright (c) 1989 OSF Research Institute 
                     31:  *
                     32:  *     3COM Etherlink 3C501 Mach Ethernet drvier
                     33:  */
                     34: /*
                     35:   Copyright 1990 by Open Software Foundation,
                     36: Cambridge, MA.
                     37: 
                     38:                All Rights Reserved
                     39: 
                     40:   Permission to use, copy, modify, and distribute this software and
                     41: its documentation for any purpose and without fee is hereby granted,
                     42: provided that the above copyright notice appears in all copies and
                     43: that both the copyright notice and this permission notice appear in
                     44: supporting documentation, and that the name of OSF or Open Software
                     45: Foundation not be used in advertising or publicity pertaining to
                     46: distribution of the software without specific, written prior
                     47: permission.
                     48: 
                     49:   OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
                     50: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
                     51: IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
                     52: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                     53: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
                     54: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
                     55: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     56: */
                     57: 
                     58: #include <at3c501.h>
                     59: 
                     60: #ifdef MACH_KERNEL
                     61: #include       <kern/time_out.h>
                     62: #include       <device/device_types.h>
                     63: #include       <device/errno.h>
                     64: #include       <device/io_req.h>
                     65: #include       <device/if_hdr.h>
                     66: #include       <device/if_ether.h>
                     67: #include       <device/net_status.h>
                     68: #include       <device/net_io.h>
                     69: #else  MACH_KERNEL
                     70: #include       <sys/param.h>
                     71: #include       <mach/machine/vm_param.h>
                     72: #include       <sys/systm.h>
                     73: #include       <sys/mbuf.h>
                     74: #include       <sys/buf.h>
                     75: #include       <sys/protosw.h>
                     76: #include       <sys/socket.h>
                     77: #include       <sys/vmmac.h>
                     78: #include       <sys/ioctl.h>
                     79: #include       <sys/errno.h>
                     80: #include       <sys/syslog.h>
                     81: 
                     82: #include       <net/if.h>
                     83: #include       <net/netisr.h>
                     84: #include       <net/route.h>
                     85: 
                     86: #ifdef INET
                     87: #include       <netinet/in.h>
                     88: #include       <netinet/in_systm.h>
                     89: #include       <netinet/in_var.h>
                     90: #include       <netinet/ip.h>
                     91: #include       <netinet/if_ether.h>
                     92: #endif
                     93: 
                     94: #ifdef NS
                     95: #include       <netns/ns.h>
                     96: #include       <netns/ns_if.h>
                     97: #endif
                     98: #endif MACH_KERNEL
                     99: 
                    100: #include       <i386/ipl.h>
                    101: #include       <chips/busses.h>
                    102: #include       <i386at/if_3c501.h>
                    103: 
                    104: #define        SPLNET  spl6
                    105: 
                    106: int    at3c501probe();
                    107: void   at3c501attach();
                    108: int    at3c501intr();
                    109: int    at3c501init();
                    110: int    at3c501output();
                    111: int    at3c501ioctl();
                    112: int    at3c501reset();
                    113: int    at3c501watch();
                    114: 
                    115: static vm_offset_t at3c501_std[NAT3C501] = { 0 };
                    116: static struct bus_device *at3c501_info[NAT3C501];
                    117: struct bus_driver      at3c501driver = 
                    118:        {at3c501probe, 0, at3c501attach, 0, at3c501_std, "et", at3c501_info, };
                    119: 
                    120: int    watchdog_id;
                    121: 
                    122: typedef struct { 
                    123: #ifdef MACH_KERNEL
                    124:        struct  ifnet   ds_if;          /* generic interface header */
                    125:        u_char  ds_addr[6];             /* Ethernet hardware address */
                    126: #else  MACH_KERNEL
                    127:        struct  arpcom  at3c501_ac;
                    128: #define        ds_if   at3c501_ac.ac_if
                    129: #define        ds_addr at3c501_ac.ac_enaddr
                    130: #endif MACH_KERNEL
                    131:        int     flags;
                    132:         int     timer;
                    133:        char    *base;
                    134:         u_char   address[ETHER_ADD_SIZE];
                    135:        short   mode;
                    136:        int     badxmt;
                    137:        int     badrcv;
                    138:        int     spurious;
                    139:        int     rcv;
                    140:        int     xmt;
                    141: } at3c501_softc_t;
                    142: 
                    143: at3c501_softc_t        at3c501_softc[NAT3C501];
                    144: 
                    145: /*
                    146:  * at3c501probe:
                    147:  *
                    148:  *     This function "probes" or checks for the 3c501 board on the bus to see
                    149:  *     if it is there.  As far as I can tell, the best break between this
                    150:  *     routine and the attach code is to simply determine whether the board
                    151:  *     is configured in properly.  Currently my approach to this is to write
                    152:  *     and read a string from the Packet Buffer on the board being probed.
                    153:  *     If the string comes back properly then we assume the board is there.
                    154:  *     The config code expects to see a successful return from the probe
                    155:  *     routine before  attach will be called.
                    156:  *
                    157:  * input       : address device is mapped to, and unit # being checked
                    158:  * output      : a '1' is returned if the board exists, and a 0 otherwise
                    159:  *
                    160:  */
                    161: at3c501probe(port, dev)
                    162: struct bus_device      *dev;
                    163: {
                    164:        caddr_t         base = (caddr_t)dev->address;
                    165:        int             unit = dev->unit;
                    166:        char            inbuf[50];
                    167:        char            *str = "3c501 ethernet board %d out of range\n";
                    168:        int             strsize = strlen(str);
                    169: 
                    170:        if ((unit < 0) || (unit >= NAT3C501)) {
                    171:                printf(str, unit);
                    172:                return(0);
                    173:        }
                    174: 
                    175:        /* reset */
                    176:        outb(IE_CSR(base), IE_RESET);
                    177: 
                    178:        /* write a string to the packet buffer */
                    179: 
                    180:        outb(IE_CSR(base), IE_RIDE | IE_SYSBFR);
                    181:        outw(IE_GP(base), 0);
                    182:        loutb(IE_BFR(base), str, strsize);
                    183: 
                    184:        /* read it back */
                    185: 
                    186:        outb(IE_CSR(base), IE_RIDE | IE_SYSBFR);
                    187:        outw(IE_GP(base), 0);
                    188:        linb(IE_BFR(base), inbuf, strsize);
                    189:        /* compare them */
                    190: 
                    191: #ifdef MACH_KERNEL
                    192:        if (strncmp(str, inbuf, strsize))
                    193: #else  MACH_KERNEL
                    194:        if (bcmp(str, inbuf, strsize))
                    195: #endif MACH_KERNEL
                    196:        {
                    197:                return(0);
                    198:        }
                    199:        at3c501_softc[unit].base = base;
                    200: 
                    201:        return(1);
                    202: }
                    203: 
                    204: /*
                    205:  * at3c501attach:
                    206:  *
                    207:  *     This function attaches a 3C501 board to the "system".  The rest of
                    208:  *     runtime structures are initialized here (this routine is called after
                    209:  *     a successful probe of the board).  Once the ethernet address is read
                    210:  *     and stored, the board's ifnet structure is attached and readied.
                    211:  *
                    212:  * input       : bus_device structure setup in autoconfig
                    213:  * output      : board structs and ifnet is setup
                    214:  *
                    215:  */
                    216: void at3c501attach(dev)
                    217: struct bus_device      *dev;
                    218: {
                    219:        at3c501_softc_t *sp;
                    220:        struct  ifnet   *ifp;
                    221:        u_char  unit;
                    222:        caddr_t         base;
                    223: #ifdef MACH_KERNEL
                    224: #else  MACH_KERNEL
                    225:        extern int      tcp_recvspace;
                    226:        tcp_recvspace = 0x300;          /* empircal messure */
                    227: #endif MACH_KERNEL
                    228: 
                    229:        take_dev_irq(dev);
                    230:        unit = (u_char)dev->unit;       
                    231:        printf(", port = %x, spl = %d, pic = %d. ",
                    232:                dev->address, dev->sysdep, dev->sysdep1);
                    233: 
                    234:        sp = &at3c501_softc[unit];
                    235:        base = sp->base;
                    236:        if (base != (caddr_t)dev->address) {
                    237:                printf("3C501 board %d attach address error\n", unit);
                    238:                return;
                    239:        }
                    240:        sp->timer = -1;
                    241:        sp->flags = 0;
                    242:        sp->mode = 0;
                    243:        outb(IE_CSR(sp->base), IE_RESET);
                    244:        at3c501geteh(base, sp->ds_addr);
                    245:        at3c501geteh(base, sp->address);
                    246:        at3c501seteh(base, sp->address);
                    247:        printf("ethernet id [%x:%x:%x:%x:%x:%x]",
                    248:                sp->address[0],sp->address[1],sp->address[2], 
                    249:                sp->address[3],sp->address[4],sp->address[5]);
                    250:        ifp = &(sp->ds_if);
                    251:        ifp->if_unit = unit;
                    252:        ifp->if_mtu = ETHERMTU;
                    253:        ifp->if_flags = IFF_BROADCAST;
                    254: #ifdef MACH_KERNEL
                    255:        ifp->if_header_size = sizeof(struct ether_header);
                    256:        ifp->if_header_format = HDR_ETHERNET;
                    257:        ifp->if_address_size = 6;
                    258:        ifp->if_address = (char *)&sp->address[0];
                    259:        if_init_queues(ifp);
                    260: #else  MACH_KERNEL
                    261:        ifp->if_name = "et";
                    262:        ifp->if_init = at3c501init;
                    263:        ifp->if_output = at3c501output;
                    264:        ifp->if_ioctl = at3c501ioctl;
                    265:        ifp->if_reset = at3c501reset;
                    266:        ifp->if_next = NULL;
                    267:        if_attach(ifp);
                    268: #ifdef notdef
                    269:        watchdog_id = timeout(at3c501watch, &(ifp->if_unit), 20*HZ);
                    270: #endif
                    271: #endif MACH_KERNEL
                    272: }
                    273: 
                    274: /*
                    275:  * at3c501watch():
                    276:  *
                    277:  */
                    278: at3c501watch(b_ptr)
                    279: 
                    280: caddr_t        b_ptr;
                    281: 
                    282: {
                    283:        int     x,
                    284:                y,
                    285:                opri,
                    286:                unit;
                    287:        at3c501_softc_t *is;
                    288: 
                    289:        unit = *b_ptr;
                    290: #ifdef MACH_KERNEL
                    291:        timeout(at3c501watch,b_ptr,20*hz);
                    292: #else  MACH_KERNEL
                    293:        watchdog_id = timeout(at3c501watch,b_ptr,20*HZ);
                    294: #endif MACH_KERNEL
                    295:        is = &at3c501_softc[unit];
                    296:        printf("\nxmt/bad       rcv/bad spurious\n");
                    297:        printf("%d/%d           %d/%d   %d\n", is->xmt, is->badxmt, \
                    298:                is->rcv, is->badrcv, is->spurious);
                    299:        is->rcv=is->badrcv=is->xmt=is->badxmt=is->spurious=0;
                    300: }
                    301: 
                    302: /*
                    303:  * at3c501geteh:
                    304:  *
                    305:  *     This function gets the ethernet address (array of 6 unsigned
                    306:  *     bytes) from the 3c501 board prom. 
                    307:  *
                    308:  */
                    309: 
                    310: at3c501geteh(base, ep)
                    311: caddr_t        base;
                    312: char *ep;
                    313: {
                    314:        int     i;
                    315: 
                    316:        for (i = 0; i < ETHER_ADD_SIZE; i++) {
                    317:                outw(IE_GP(base), i);
                    318:                *ep++ = inb(IE_SAPROM(base));
                    319:        }
                    320: }
                    321: 
                    322: /*
                    323:  * at3c501seteh:
                    324:  *
                    325:  *     This function sets the ethernet address (array of 6 unsigned
                    326:  *     bytes) on the 3c501 board. 
                    327:  *
                    328:  */
                    329: 
                    330: at3c501seteh(base, ep)
                    331: caddr_t        base;
                    332: char *ep;
                    333: {
                    334:        int     i;
                    335: 
                    336:        for (i = 0; i < ETHER_ADD_SIZE; i++) {
                    337:                outb(EDLC_ADDR(base) + i, *ep++);
                    338:        }
                    339: }
                    340: 
                    341: #ifdef MACH_KERNEL
                    342: int at3c501start();    /* forward */
                    343: 
                    344: at3c501output(dev, ior)
                    345:        dev_t           dev;
                    346:        io_req_t        ior;
                    347: {
                    348:        register int    unit = minor(dev);
                    349: 
                    350:        if (unit < 0 || unit >= NAT3C501 ||
                    351:                at3c501_softc[unit].base == 0)
                    352:            return (ENXIO);
                    353: 
                    354:        return (net_write(&at3c501_softc[unit].ds_if, at3c501start, ior));
                    355: }
                    356: 
                    357: at3c501setinput(dev, receive_port, priority, filter, filter_count)
                    358:        dev_t           dev;
                    359:        mach_port_t     receive_port;
                    360:        int             priority;
                    361:        filter_t        filter[];
                    362:        u_int           filter_count;
                    363: {
                    364:        register int unit = minor(dev);
                    365: 
                    366:        if (unit < 0 || unit >= NAT3C501 ||
                    367:                at3c501_softc[unit].base == 0)
                    368:            return (ENXIO);
                    369: 
                    370:        return (net_set_filter(&at3c501_softc[unit].ds_if,
                    371:                        receive_port, priority,
                    372:                        filter, filter_count));
                    373: }
                    374: 
                    375: #else  MACH_KERNEL
                    376: /*
                    377:  * at3c501output:
                    378:  *
                    379:  *     This routine is called by the "if" layer to output a packet to
                    380:  *     the network.  This code resolves the local ethernet address, and
                    381:  *     puts it into the mbuf if there is room.  If not, then a new mbuf
                    382:  *     is allocated with the header information and precedes the data
                    383:  *     to be transmitted.
                    384:  *
                    385:  * input:      ifnet structure pointer, an mbuf with data, and address
                    386:  *             to be resolved
                    387:  * output:     mbuf is updated to hold enet address, or a new mbuf
                    388:  *             with the address is added
                    389:  *
                    390:  */
                    391: at3c501output(ifp, m0, dst)
                    392: struct ifnet   *ifp;
                    393: struct mbuf    *m0;
                    394: struct sockaddr *dst;
                    395: {
                    396:        int                             type, error;
                    397:        spl_t                           opri;
                    398:        u_char                          edst[6];
                    399:        struct in_addr                  idst;
                    400:        register at3c501_softc_t        *is;
                    401:        register struct mbuf            *m = m0;
                    402:        register struct ether_header    *eh;
                    403:        register int                     off;
                    404:        int                             usetrailers;
                    405: 
                    406:        is = &at3c501_softc[ifp->if_unit];
                    407:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
                    408:                printf("3C501 Turning off board %d\n", ifp->if_unit);
                    409:                at3c501intoff(ifp->if_unit);
                    410:                error = ENETDOWN;
                    411:                goto bad;
                    412:        }
                    413:        switch (dst->sa_family) {
                    414: 
                    415: #ifdef INET
                    416:        case AF_INET:
                    417:                idst = ((struct sockaddr_in *)dst)->sin_addr;
                    418:                if (!arpresolve(&is->at3c501_ac, m, &idst, edst, &usetrailers)){
                    419:                        return (0);     /* if not yet resolved */
                    420:                }
                    421:                off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
                    422: 
                    423:                if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
                    424:                    m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
                    425:                        type = ETHERTYPE_TRAIL + (off>>9);
                    426:                        m->m_off -= 2 * sizeof (u_short);
                    427:                        m->m_len += 2 * sizeof (u_short);
                    428:                        *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
                    429:                        *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
                    430:                        goto gottrailertype;
                    431:                }
                    432:                type = ETHERTYPE_IP;
                    433:                off = 0;
                    434:                goto gottype;
                    435: #endif
                    436: #ifdef NS
                    437:        case AF_NS:
                    438:                type = ETHERTYPE_NS;
                    439:                bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
                    440:                (caddr_t)edst, sizeof (edst));
                    441:                off = 0;
                    442:                goto gottype;
                    443: #endif
                    444: 
                    445:        case AF_UNSPEC:
                    446:                eh = (struct ether_header *)dst->sa_data;
                    447:                bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
                    448:                type = eh->ether_type;
                    449:                goto gottype;
                    450: 
                    451:        default:
                    452:                printf("at3c501%d: can't handle af%d\n", ifp->if_unit,
                    453:                        dst->sa_family);
                    454:                error = EAFNOSUPPORT;
                    455:                goto bad;
                    456:        }
                    457: 
                    458: gottrailertype:
                    459:        /*
                    460:         * Packet to be sent as trailer: move first packet
                    461:         * (control information) to end of chain.
                    462:         */
                    463:        while (m->m_next)
                    464:                m = m->m_next;
                    465:        m->m_next = m0;
                    466:        m = m0->m_next;
                    467:        m0->m_next = 0;
                    468:        m0 = m;
                    469: 
                    470: gottype:
                    471:        /*
                    472:         * Add local net header.  If no space in first mbuf,
                    473:         * allocate another.
                    474:         */
                    475:        if (m->m_off > MMAXOFF ||
                    476:            MMINOFF + sizeof (struct ether_header) > m->m_off) {
                    477:                m = m_get(M_DONTWAIT, MT_HEADER);
                    478:                if (m == 0) {
                    479:                        error = ENOBUFS;
                    480:                        goto bad;
                    481:                }
                    482:                m->m_next = m0;
                    483:                m->m_off = MMINOFF;
                    484:                m->m_len = sizeof (struct ether_header);
                    485:        } else {
                    486:                m->m_off -= sizeof (struct ether_header);
                    487:                m->m_len += sizeof (struct ether_header);
                    488:        }
                    489:        eh = mtod(m, struct ether_header *);
                    490:        eh->ether_type = htons((u_short)type);
                    491:        bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
                    492:        bcopy((caddr_t)is->address,(caddr_t)eh->ether_shost,
                    493:                                                                sizeof(edst));
                    494:        /*
                    495:         * Queue message on interface, and start output if interface
                    496:         * not yet active.
                    497:         */
                    498:        opri = SPLNET();
                    499:        if (IF_QFULL(&ifp->if_snd)) {
                    500:                IF_DROP(&ifp->if_snd);
                    501:                splx(opri);
                    502:                m_freem(m);
                    503:                return (ENOBUFS);
                    504:        }
                    505:        IF_ENQUEUE(&ifp->if_snd, m);
                    506:        /*
                    507:         * Some action needs to be added here for checking whether the
                    508:         * board is already transmitting.  If it is, we don't want to
                    509:         * start it up (ie call at3c501start()).  We will attempt to send
                    510:         * packets that are queued up after an interrupt occurs.  Some
                    511:         * flag checking action has to happen here and/or in the start
                    512:         * routine.  This note is here to remind me that some thought
                    513:         * is needed and there is a potential problem here.
                    514:         *
                    515:         */
                    516:        at3c501start(ifp->if_unit);
                    517:        splx(opri);
                    518:        return (0);
                    519: 
                    520: bad:
                    521:        m_freem(m0);
                    522:        return (error);
                    523: }
                    524: #endif MACH_KERNEL
                    525: 
                    526: /*
                    527:  * at3c501reset:
                    528:  *
                    529:  *     This routine is in part an entry point for the "if" code.  Since most 
                    530:  *     of the actual initialization has already (we hope already) been done
                    531:  *     by calling at3c501attach().
                    532:  *
                    533:  * input       : unit number or board number to reset
                    534:  * output      : board is reset
                    535:  *
                    536:  */
                    537: at3c501reset(unit)
                    538: int    unit;
                    539: {
                    540:        at3c501_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
                    541:        return(at3c501init(unit));
                    542: }
                    543: 
                    544: 
                    545: 
                    546: /*
                    547:  * at3c501init:
                    548:  *
                    549:  *     Another routine that interfaces the "if" layer to this driver.  
                    550:  *     Simply resets the structures that are used by "upper layers".  
                    551:  *     As well as calling at3c501hwrst that does reset the at3c501 board.
                    552:  *
                    553:  * input       : board number
                    554:  * output      : structures (if structs) and board are reset
                    555:  *
                    556:  */    
                    557: at3c501init(unit)
                    558: int    unit;
                    559: {
                    560:        struct  ifnet   *ifp;
                    561:        int             stat;
                    562:        spl_t           oldpri;
                    563: 
                    564:        ifp = &(at3c501_softc[unit].ds_if);
                    565: #ifdef MACH_KERNEL
                    566: #else  MACH_KERNEL
                    567:        if (ifp->if_addrlist == (struct ifaddr *)0) {
                    568:                return;
                    569:        }
                    570: #endif MACH_KERNEL
                    571:        oldpri = SPLNET();
                    572:        if ((stat = at3c501hwrst(unit)) == TRUE) {
                    573:                at3c501_softc[unit].ds_if.if_flags |= IFF_RUNNING;
                    574:                at3c501_softc[unit].flags |= DSF_RUNNING;
                    575:                at3c501start(unit);
                    576:        }
                    577:        else
                    578:                printf("3C501 trouble resetting board %d\n", unit);
                    579:        at3c501_softc[unit].timer = 5;
                    580:        splx(oldpri);
                    581:        return(stat);
                    582: 
                    583: }
                    584: 
                    585: #ifdef MACH_KERNEL
                    586: /*ARGSUSED*/
                    587: at3c501open(dev, flag)
                    588:        dev_t   dev;
                    589:        int     flag;
                    590: {
                    591:        register int    unit = minor(dev);
                    592: 
                    593:        if (unit < 0 || unit >= NAT3C501 ||
                    594:                at3c501_softc[unit].base == 0)
                    595:            return (ENXIO);
                    596: 
                    597:        at3c501_softc[unit].ds_if.if_flags |= IFF_UP;
                    598:        at3c501init(unit);
                    599:        return(0);
                    600: }
                    601: #endif MACH_KERNEL
                    602: 
                    603: /*
                    604:  * at3c501start:
                    605:  *
                    606:  *     This is yet another interface routine that simply tries to output a
                    607:  *     in an mbuf after a reset.
                    608:  *
                    609:  * input       : board number
                    610:  * output      : stuff sent to board if any there
                    611:  *
                    612:  */
                    613: at3c501start(unit)
                    614: int    unit;
                    615: 
                    616: {
                    617: #ifdef MACH_KERNEL
                    618:        io_req_t        m;
                    619: #else  MACH_KERNEL
                    620:        struct  mbuf    *m;
                    621: #endif MACH_KERNEL
                    622:        struct  ifnet   *ifp;
                    623: 
                    624:        ifp = &(at3c501_softc[unit].ds_if);
                    625:        for(;;) {
                    626:                IF_DEQUEUE(&ifp->if_snd, m);
                    627: #ifdef MACH_KERNEL
                    628:                if (m != 0)
                    629: #else  MACH_KERNEL
                    630:                if (m != (struct mbuf *)0)
                    631: #endif MACH_KERNEL
                    632:                        at3c501xmt(unit, m);
                    633:                else
                    634:                        return;
                    635:        }
                    636: }
                    637: 
                    638: #ifdef MACH_KERNEL
                    639: /*ARGSUSED*/
                    640: at3c501getstat(dev, flavor, status, count)
                    641:        dev_t           dev;
                    642:        int             flavor;
                    643:        dev_status_t    status;         /* pointer to OUT array */
                    644:        u_int           *count;         /* out */
                    645: {
                    646:        register int    unit = minor(dev);
                    647: 
                    648:        if (unit < 0 || unit >= NAT3C501 ||
                    649:                at3c501_softc[unit].base == 0)
                    650:            return (ENXIO);
                    651: 
                    652:        return (net_getstat(&at3c501_softc[unit].ds_if,
                    653:                            flavor,
                    654:                            status,
                    655:                            count));
                    656: }
                    657: 
                    658: at3c501setstat(dev, flavor, status, count)
                    659:        dev_t           dev;
                    660:        int             flavor;
                    661:        dev_status_t    status;
                    662:        u_int           count;
                    663: {
                    664:        register int    unit = minor(dev);
                    665:        register at3c501_softc_t *sp;
                    666: 
                    667:        if (unit < 0 || unit >= NAT3C501 ||
                    668:                at3c501_softc[unit].base == 0)
                    669:            return (ENXIO);
                    670: 
                    671:        sp = &at3c501_softc[unit];
                    672: 
                    673:        switch (flavor) {
                    674:            case NET_STATUS:
                    675:            {
                    676:                /*
                    677:                 * All we can change are flags, and not many of those.
                    678:                 */
                    679:                register struct net_status *ns = (struct net_status *)status;
                    680:                int     mode = 0;
                    681: 
                    682:                if (count < NET_STATUS_COUNT)
                    683:                    return (D_INVALID_SIZE);
                    684: 
                    685:                if (ns->flags & IFF_ALLMULTI)
                    686:                    mode |= MOD_ENAL;
                    687:                if (ns->flags & IFF_PROMISC)
                    688:                    mode |= MOD_PROM;
                    689: 
                    690:                /*
                    691:                 * Force a compilete reset if the receive mode changes
                    692:                 * so that these take effect immediately.
                    693:                 */
                    694:                if (sp->mode != mode) {
                    695:                    sp->mode = mode;
                    696:                    if (sp->flags & DSF_RUNNING) {
                    697:                        sp->flags &= ~(DSF_LOCK | DSF_RUNNING);
                    698:                        at3c501init(unit);
                    699:                    }
                    700:                }
                    701:                break;
                    702:            }
                    703:            case NET_ADDRESS:
                    704:            {
                    705:                register union ether_cvt {
                    706:                    char        addr[6];
                    707:                    int         lwd[2];
                    708:                } *ec = (union ether_cvt *)status;
                    709: 
                    710:                if (count < sizeof(*ec)/sizeof(int))
                    711:                    return (D_INVALID_SIZE);
                    712: 
                    713:                ec->lwd[0] = ntohl(ec->lwd[0]);
                    714:                ec->lwd[1] = ntohl(ec->lwd[1]);
                    715:                at3c501seteh(sp->base, ec->addr);
                    716:                break;
                    717:            }
                    718: 
                    719:            default:
                    720:                return (D_INVALID_OPERATION);
                    721:        }
                    722:        return (D_SUCCESS);
                    723: }
                    724: #else  MACH_KERNEL
                    725: 
                    726: /*
                    727:  * at3c501ioctl:
                    728:  *
                    729:  *     This routine processes an ioctl request from the "if" layer
                    730:  *     above.
                    731:  *
                    732:  * input       : pointer the appropriate "if" struct, command, and data
                    733:  * output      : based on command appropriate action is taken on the
                    734:  *               at3c501 board(s) or related structures
                    735:  * return      : error is returned containing exit conditions
                    736:  *
                    737:  */
                    738: int            curr_ipl;
                    739: u_short        curr_pic_mask;
                    740: u_short        pic_mask[];
                    741: 
                    742: at3c501ioctl(ifp, cmd, data)
                    743: struct ifnet   *ifp;
                    744: int    cmd;
                    745: caddr_t        data;
                    746: {
                    747:        register struct ifaddr          *ifa = (struct ifaddr *)data;
                    748:        register at3c501_softc_t        *is;
                    749:        int                             error;
                    750:        spl_t                           opri;
                    751:        short                           mode = 0;
                    752: 
                    753:        is = &at3c501_softc[ifp->if_unit];
                    754:        opri = SPLNET();
                    755:        error = 0;
                    756:        switch (cmd) {
                    757:                case SIOCSIFADDR:
                    758:                        ifp->if_flags |= IFF_UP;
                    759:                        at3c501init(ifp->if_unit);
                    760:                        switch (ifa->ifa_addr.sa_family) {
                    761: #ifdef INET
                    762:                                case AF_INET:
                    763:                                        ((struct arpcom *)ifp)->ac_ipaddr =
                    764:                                                IA_SIN(ifa)->sin_addr;
                    765:                                        arpwhohas((struct arpcom *)ifp, 
                    766:                                                  &IA_SIN(ifa)->sin_addr);
                    767:                                        break;
                    768: #endif
                    769: #ifdef NS
                    770:                                case AF_NS:
                    771:                                        {
                    772:                                        register struct ns_addr *ina = 
                    773:                                        &(IA_SNS(ifa)->sns_addr);
                    774:                                        if (ns_nullhost(*ina))
                    775:                                                ina->x_host = 
                    776:                                                *(union ns_host *)(ds->ds_addr);
                    777:                                        else
                    778:                                                at3c501seteh(ina->x_host.c_host,
                    779:                                                at3c501_softc[ifp->if_unit].base);
                    780:                                        break;
                    781:                                        }
                    782: #endif
                    783:                        }
                    784:                        break;
                    785:                case SIOCSIFFLAGS:
                    786:                        if (ifp->if_flags & IFF_ALLMULTI)
                    787:                                mode |= MOD_ENAL;
                    788:                        if (ifp->if_flags & IFF_PROMISC)
                    789:                                mode |= MOD_PROM;
                    790:                        /*
                    791:                         * force a complete reset if the receive multicast/
                    792:                         * promiscuous mode changes so that these take 
                    793:                         * effect immediately.
                    794:                         *
                    795:                         */
                    796:                        if (is->mode != mode) {
                    797:                                is->mode = mode;
                    798:                                if (is->flags & DSF_RUNNING) {
                    799:                                        is->flags &=
                    800:                                                ~(DSF_LOCK|DSF_RUNNING);
                    801:                                        at3c501init(ifp->if_unit);
                    802:                                }
                    803:                        }
                    804:                        if ((ifp->if_flags & IFF_UP) == 0 &&
                    805:                            is->flags & DSF_RUNNING) {
                    806:                                printf("AT3C501 ioctl: turning off board %d\n", 
                    807:                                       ifp->if_unit);
                    808:                                is->flags &= ~(DSF_LOCK | DSF_RUNNING);
                    809:                                is->timer = -1;
                    810:                                at3c501intoff(ifp->if_unit);
                    811:                        } else 
                    812:                        if (ifp->if_flags & IFF_UP &&
                    813:                            (is->flags & DSF_RUNNING) == 0)
                    814:                                at3c501init(ifp->if_unit);
                    815:                        break;
                    816:        default:
                    817:                error = EINVAL;
                    818:        }
                    819:        splx(opri);
                    820:        return (error);
                    821: }
                    822: #endif MACH_KERNEL
                    823: 
                    824: 
                    825: /*
                    826:  * at3c501hwrst:
                    827:  *
                    828:  *     This routine resets the at3c501 board that corresponds to the 
                    829:  *     board number passed in.
                    830:  *
                    831:  * input       : board number to do a hardware reset
                    832:  * output      : board is reset
                    833:  *
                    834:  */
                    835: #define XMT_STAT (EDLC_16|EDLC_JAM|EDLC_UNDER|EDLC_IDLE)
                    836: #define RCV_STAT (EDLC_STALE|EDLC_ANY|EDLC_SHORT|EDLC_DRIBBLE|EDLC_OVER|EDLC_FCS)
                    837: int 
                    838: at3c501hwrst(unit)
                    839: int unit;
                    840: {
                    841:        u_char  stat;
                    842:        caddr_t base = at3c501_softc[unit].base;
                    843: 
                    844:        outb(IE_CSR(base), IE_RESET);
                    845:        outb(IE_CSR(base), 0);
                    846:        at3c501seteh(base, at3c501_softc[unit].address);
                    847:        if ((stat = inb(IE_CSR(base))) != IE_RESET) {
                    848:                printf("at3c501reset: can't reset CSR: %x\n", stat);
                    849:                return(FALSE);
                    850:        }
                    851:        if ((stat = inb(EDLC_XMT(base))) & XMT_STAT) {
                    852:                printf("at3c501reset: can't reset XMT: %x\n", stat);
                    853:                return(FALSE);
                    854:        }
                    855:        if (((stat = inb(EDLC_RCV(base))) & RCV_STAT) != EDLC_STALE) {
                    856:                printf("at3c501reset: can't reset RCV: %x\n", stat);
                    857:                return(FALSE);
                    858:        }
                    859:        if (at3c501config(unit) == FALSE) {
                    860:                printf("at3c501hwrst(): failed to config\n");
                    861:                return(FALSE);
                    862:        }
                    863:        outb(IE_RP(base), 0);
                    864:        outb(IE_CSR(base), IE_RIDE|IE_RCVEDLC);
                    865:        return(TRUE);
                    866: }
                    867: 
                    868: /*
                    869:  * at3c501intr:
                    870:  *
                    871:  *     This function is the interrupt handler for the at3c501 ethernet
                    872:  *     board.  This routine will be called whenever either a packet
                    873:  *     is received, or a packet has successfully been transfered and
                    874:  *     the unit is ready to transmit another packet.
                    875:  *
                    876:  * input       : board number that interrupted
                    877:  * output      : either a packet is received, or a packet is transfered
                    878:  *
                    879:  */
                    880: at3c501intr(unit)
                    881: int unit;
                    882: {
                    883:        at3c501rcv(unit);
                    884:        at3c501start(unit);
                    885: 
                    886:        return(0);
                    887: }
                    888: 
                    889: 
                    890: /*
                    891:  * at3c501rcv:
                    892:  *
                    893:  *     This routine is called by the interrupt handler to initiate a
                    894:  *     packet transfer from the board to the "if" layer above this
                    895:  *     driver.  This routine checks if a buffer has been successfully
                    896:  *     received by the at3c501.  If so, the routine at3c501read is called
                    897:  *     to do the actual transfer of the board data (including the
                    898:  *     ethernet header) into a packet (consisting of an mbuf chain).
                    899:  *
                    900:  * input       : number of the board to check
                    901:  * output      : if a packet is available, it is "sent up"
                    902:  *
                    903:  */
                    904: at3c501rcv(unit)
                    905: int    unit;
                    906: {
                    907:        int stat;
                    908:        caddr_t base;
                    909: #ifdef MACH_KERNEL
                    910:        ipc_kmsg_t      new_kmsg;
                    911:        struct ether_header *ehp;
                    912:        struct packet_header *pkt;
                    913: #else  MACH_KERNEL
                    914:        struct  mbuf    *m,     *tm;
                    915: #endif MACH_KERNEL
                    916:        u_short len;
                    917:        register struct ifnet *ifp;
                    918:        struct ether_header header;
                    919:        int     tlen;
                    920:        register at3c501_softc_t        *is;
                    921:        register struct ifqueue         *inq;
                    922:        spl_t   opri;
                    923:        struct  ether_header eh;
                    924: 
                    925:        is = &at3c501_softc[unit];
                    926:        ifp = &is->ds_if;
                    927:        base = at3c501_softc[unit].base;
                    928:        is->rcv++;
                    929:        if (inb(IE_CSR(base)) & IE_RCVBSY)
                    930:                is->spurious++;
                    931:        while (!((stat=inb(EDLC_RCV(base))) & EDLC_STALE)) {
                    932:                outb(IE_CSR(base), IE_SYSBFR);
                    933:                if (!(stat & EDLC_ANY)) {
                    934:                        outw(IE_GP(base), 0);
                    935:                        len = inw(IE_RP(base))-sizeof(struct ether_header);
                    936:                        outb(IE_RP(base), 0);
                    937:                        outb(IE_CSR(base), IE_RIDE|IE_RCVEDLC);
                    938:                        is->badrcv++;
                    939: #ifdef DEBUG
                    940:                        printf("at3c501rcv: received %d bad bytes", len);
                    941:                        if (stat & EDLC_SHORT)
                    942:                                printf(" Short frame");
                    943:                        if (stat & EDLC_OVER) 
                    944:                                printf(" Data overflow");
                    945:                        if (stat & EDLC_DRIBBLE)
                    946:                                printf(" Dribble error");
                    947:                        if (stat & EDLC_FCS)
                    948:                                printf(" CRC error");
                    949:                        printf("\n");
                    950: #endif DEBUG
                    951:                } else {
                    952:                        outw(IE_GP(base), 0);
                    953:                        len = inw(IE_RP(base));
                    954:                        if (len < 60) {
                    955:                                outb(IE_RP(base), 0);
                    956:                                outb(IE_CSR(base), IE_RIDE|IE_RCVEDLC);
                    957:                                return;
                    958:                        }
                    959:                        linb(IE_BFR(base), &eh, sizeof(struct ether_header));
                    960: #ifdef MACH_KERNEL
                    961:                        new_kmsg = net_kmsg_get();
                    962:                        if (new_kmsg == IKM_NULL) {
                    963:                            /*
                    964:                             * Drop the packet.
                    965:                             */
                    966:                            is->ds_if.if_rcvdrops++;
                    967: 
                    968:                            outb(IE_RP(base), 0);
                    969:                            outb(IE_CSR(base), IE_RIDE|IE_RCVEDLC);
                    970:                            return;
                    971:                        }
                    972: 
                    973:                        ehp = (struct ether_header *)
                    974:                                (&net_kmsg(new_kmsg)->header[0]);
                    975:                        pkt = (struct packet_header *)
                    976:                                (&net_kmsg(new_kmsg)->packet[0]);
                    977: 
                    978:                        /*
                    979:                         * Get header.
                    980:                         */
                    981:                        *ehp = eh;
                    982: 
                    983:                        /*
                    984:                         * Get body
                    985:                         */
                    986:                        linb(IE_BFR(base),
                    987:                             (char *)(pkt + 1),
                    988:                             len - sizeof(struct ether_header));
                    989: 
                    990:                        outb(IE_RP(base), 0);
                    991:                        outb(IE_CSR(base), IE_RIDE|IE_RCVEDLC);
                    992: 
                    993:                        pkt->type = ehp->ether_type;
                    994:                        pkt->length = len - sizeof(struct ether_header)
                    995:                                          + sizeof(struct packet_header);
                    996: 
                    997:                        /*
                    998:                         * Hand the packet to the network module.
                    999:                         */
                   1000:                        net_packet(ifp, new_kmsg, pkt->length,
                   1001:                                   ethernet_priority(new_kmsg));
                   1002: 
                   1003: #else  MACH_KERNEL
                   1004:                        eh.ether_type = htons(eh.ether_type);
                   1005:                        m =(struct mbuf *)0;
                   1006: #ifdef DEBUG
                   1007:                        printf("received %d bytes\n", len);
                   1008: #endif DEBUG
                   1009:                        len -= sizeof(struct ether_header);
                   1010:                        while ( len ) {
                   1011:                                if (m == (struct mbuf *)0) {
                   1012:                                        m = m_get(M_DONTWAIT, MT_DATA);
                   1013:                                        if (m == (struct mbuf *)0) {
                   1014:                                                printf("at3c501rcv: Lost frame\n");
                   1015:                                                outb(IE_RP(base), 0);
                   1016:                                                outb(IE_CSR(base), IE_RIDE|IE_RCVEDLC);
                   1017: 
                   1018:                                                return;
                   1019:                                        }
                   1020:                                        tm = m;
                   1021:                                        tm->m_off = MMINOFF;
                   1022:                        /*
                   1023:                         * first mbuf in the packet must contain a pointer to the
                   1024:                         * ifnet structure.  other mbufs that follow and make up
                   1025:                         * the packet do not need this pointer in the mbuf.
                   1026:                         *
                   1027:                         */
                   1028:                                        *(mtod(tm, struct ifnet **)) = ifp;
                   1029:                                        tm->m_len = sizeof(struct ifnet **);
                   1030:                                }
                   1031:                                else {
                   1032:                                        tm->m_next = m_get(M_DONTWAIT, MT_DATA);
                   1033:                                        tm = tm->m_next;
                   1034:                                        tm->m_off = MMINOFF;
                   1035:                                        tm->m_len = 0;
                   1036:                                        if (tm == (struct mbuf *)0) {
                   1037:                                                m_freem(m);
                   1038:                                                printf("at3c501rcv: No mbufs, lost frame\n");
                   1039:                                                outb(IE_RP(base), 0);
                   1040:                                                outb(IE_CSR(base), IE_RIDE|IE_RCVEDLC);
                   1041:                                                return;
                   1042:                                        }
                   1043:                                }
                   1044:                                tlen = MIN( MLEN - tm->m_len, len );
                   1045:                                tm->m_next = (struct mbuf *)0;
                   1046:                                linb(IE_BFR(base), mtod(tm, char *)+tm->m_len, tlen );
                   1047:                                tm->m_len += tlen;
                   1048:                                len -= tlen;
                   1049:                        }
                   1050:                        outb(IE_RP(base), 0);
                   1051:                        outb(IE_CSR(base), IE_RIDE|IE_RCVEDLC);
                   1052:                        /*
                   1053:                         * received packet is now in a chain of mbuf's.  next step is
                   1054:                         * to pass the packet upwards.
                   1055:                         *
                   1056:                         */
                   1057:                        switch (eh.ether_type) {
                   1058: #ifdef INET
                   1059:                                case ETHERTYPE_IP:
                   1060:                                        schednetisr(NETISR_IP);
                   1061:                                        inq = &ipintrq;
                   1062:                                        break;
                   1063:                                case ETHERTYPE_ARP:
                   1064:                                        arpinput(&is->at3c501_ac, m);
                   1065:                                        return;
                   1066: #endif
                   1067: #ifdef NS
                   1068:                                case ETHERTYPE_NS:
                   1069:                                        schednetisr(NETISR_NS);
                   1070:                                        inq = &nsintrq;
                   1071:                                        break;
                   1072: #endif
                   1073:                                default:
                   1074:                                        m_freem(m);
                   1075:                                        return;
                   1076:                        }
                   1077:                        opri = SPLNET();
                   1078:                        if (IF_QFULL(inq)) {
                   1079:                                IF_DROP(inq);
                   1080:                                splx(opri);
                   1081:                                m_freem(m);
                   1082:                                return;
                   1083:                        }
                   1084:                        IF_ENQUEUE(inq, m);
                   1085:                        splx(opri);
                   1086: #endif MACH_KERNEL
                   1087:                }
                   1088:        }
                   1089: }
                   1090: 
                   1091: 
                   1092: /*
                   1093:  * at3c501xmt:
                   1094:  *
                   1095:  *     This routine fills in the appropriate registers and memory
                   1096:  *     locations on the 3C501 board and starts the board off on
                   1097:  *     the transmit.
                   1098:  *
                   1099:  * input       : board number of interest, and a pointer to the mbuf
                   1100:  * output      : board memory and registers are set for xfer and attention
                   1101:  *
                   1102:  */
                   1103: at3c501xmt(unit, m)
                   1104: int    unit;
                   1105: #ifdef MACH_KERNEL
                   1106: io_req_t       m;
                   1107: #else  MACH_KERNEL
                   1108: struct mbuf    *m;
                   1109: #endif MACH_KERNEL
                   1110: {
                   1111: #ifdef MACH_KERNEL
                   1112: #else  MACH_KERNEL
                   1113:        register struct mbuf    *tm_p;
                   1114: #endif MACH_KERNEL
                   1115:        int                     i;
                   1116:        at3c501_softc_t         *is = &at3c501_softc[unit];
                   1117:        caddr_t                 base = is->base;
                   1118:        u_short                 count = 0;
                   1119:        u_short                 bytes_in_msg;
                   1120: 
                   1121:        is->xmt++;
                   1122:        outb(IE_CSR(base), IE_SYSBFR);
                   1123: #ifdef MACH_KERNEL
                   1124:        count = m->io_count;
                   1125: #define        max(a,b)        (((a) > (b)) ? (a) : (b))
                   1126:        bytes_in_msg = max(count,
                   1127:                           ETHERMIN + sizeof(struct ether_header));
                   1128: #else  MACH_KERNEL
                   1129:        bytes_in_msg = max(m_length(m), ETHERMIN + sizeof(struct ether_header));
                   1130: #endif MACH_KERNEL
                   1131:        outw(IE_GP(base), BFRSIZ-bytes_in_msg);
                   1132: #ifdef MACH_KERNEL
                   1133:        loutb(IE_BFR(base), m->io_data, count);
                   1134: #else  MACH_KERNEL
                   1135:        for (tm_p = m; tm_p != (struct mbuf *)0; tm_p = tm_p->m_next) {
                   1136:                if (count + tm_p->m_len > ETHERMTU + sizeof(struct ether_header))
                   1137:                        break;
                   1138:                if (tm_p->m_len == 0)
                   1139:                        continue;
                   1140:                loutb(IE_BFR(base), mtod(tm_p, caddr_t), tm_p->m_len);
                   1141:                count += tm_p->m_len;
                   1142:        }
                   1143: #endif MACH_KERNEL
                   1144:        while (count < bytes_in_msg) {
                   1145:                outb(IE_BFR(base), 0);
                   1146:                count++;
                   1147:        }
                   1148:        do {
                   1149:                if (!(int)m) {
                   1150:                        outb(IE_CSR(base), IE_SYSBFR);
                   1151:                }
                   1152:                outw(IE_GP(base), BFRSIZ-bytes_in_msg);
                   1153:                outb(IE_CSR(base), IE_RIDE|IE_XMTEDLC);
                   1154:                if (m) {
                   1155: #ifdef MACH_KERNEL
                   1156:                        iodone(m);
                   1157:                        m = 0;
                   1158: #else  MACH_KERNEL
                   1159:                        m_freem(m);
                   1160:                        m = (struct mbuf *) 0;
                   1161: #endif MACH_KERNEL
                   1162:                }
                   1163:                for (i=0; inb(IE_CSR(base)) & IE_XMTBSY; i++);
                   1164:                if ((i=inb(EDLC_XMT(base))) & EDLC_JAM) {
                   1165:                        is->badxmt++;
                   1166: #ifdef DEBUG
                   1167:                        printf("at3c501xmt jam\n");
                   1168: #endif DEBUG
                   1169:                }
                   1170:        } while ((i & EDLC_JAM) && !(i & EDLC_16));
                   1171: 
                   1172:        if (i & EDLC_16) {
                   1173:                printf("%");
                   1174:        }
                   1175:        return;
                   1176: 
                   1177: }
                   1178: 
                   1179: /*
                   1180:  * at3c501config:
                   1181:  *
                   1182:  *     This routine does a standard config of the at3c501 board.
                   1183:  *
                   1184:  */
                   1185: at3c501config(unit)
                   1186: int    unit;
                   1187: {
                   1188:        caddr_t base = at3c501_softc[unit].base;
                   1189:        u_char  stat;
                   1190: 
                   1191:        /* Enable DMA & Interrupts */
                   1192: 
                   1193:        outb(IE_CSR(base), IE_RIDE|IE_SYSBFR);
                   1194: 
                   1195:        /* No Transmit Interrupts */
                   1196: 
                   1197:        outb(EDLC_XMT(base), 0);
                   1198:        inb(EDLC_XMT(base));
                   1199: 
                   1200:        /* Setup Receive Interrupts */
                   1201: 
                   1202:        outb(EDLC_RCV(base), EDLC_BROAD|EDLC_SHORT|EDLC_GOOD|EDLC_DRIBBLE|EDLC_OVER);
                   1203:        inb(EDLC_RCV(base));
                   1204: 
                   1205:        outb(IE_CSR(base), IE_RIDE|IE_SYSBFR);
                   1206:        outb(IE_RP(base), 0);
                   1207:        outb(IE_CSR(base), IE_RIDE|IE_RCVEDLC);
                   1208:        return(TRUE);
                   1209: }
                   1210: 
                   1211: /*
                   1212:  * at3c501intoff:
                   1213:  *
                   1214:  *     This function turns interrupts off for the at3c501 board indicated.
                   1215:  *
                   1216:  */
                   1217: at3c501intoff(unit)
                   1218: int unit;
                   1219: {
                   1220:        caddr_t base = at3c501_softc[unit].base;
                   1221:        outb(IE_CSR(base), 0);
                   1222: }
                   1223: 
                   1224: #ifdef MACH_KERNEL
                   1225: #else  MACH_KERNEL
                   1226: /*
                   1227:  * The length of an mbuf chain
                   1228:  */
                   1229: m_length(m)
                   1230:        register struct mbuf *m;
                   1231: {
                   1232:        register int len = 0;
                   1233:        
                   1234:        while (m) {
                   1235:                len += m->m_len;
                   1236:                m = m->m_next;
                   1237:        }
                   1238:        return len;
                   1239: }
                   1240: #endif MACH_KERNEL

unix.superglobalmegacorp.com

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