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

1.1     ! root        1: /* 
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  * 
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            23:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: /*
        !            27:  *     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.