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

1.1     ! root        1: /* 
        !             2:  * Copyright (c) 1994 Shantanu Goel
        !             3:  * All Rights Reserved.
        !             4:  * 
        !             5:  * Permission to use, copy, modify and distribute this software and its
        !             6:  * documentation is hereby granted, provided that both the copyright
        !             7:  * notice and this permission notice appear in all copies of the
        !             8:  * software, derivative works or modified versions, and any portions
        !             9:  * thereof, and that both notices appear in supporting documentation.
        !            10:  * 
        !            11:  * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            12:  * CONDITION.  THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            13:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            14:  */
        !            15: 
        !            16: /*
        !            17:  * Written 1993 by Donald Becker.
        !            18:  * 
        !            19:  * Copyright 1993 United States Government as represented by the
        !            20:  * Director, National Security Agency.  This software may be used and
        !            21:  * distributed according to the terms of the GNU Public License,
        !            22:  * incorporated herein by reference.
        !            23:  *
        !            24:  * The Author may be reached as [email protected] or
        !            25:  * C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
        !            26:  */
        !            27: 
        !            28: #include <wd.h>
        !            29: #if NWD > 0
        !            30: /*
        !            31:  * Driver for SMC/Western Digital Ethernet adaptors.
        !            32:  * Derived from the Linux driver by Donald Becker.
        !            33:  *
        !            34:  * Shantanu Goel ([email protected])
        !            35:  */
        !            36: #include <mach/sa/sys/types.h>
        !            37: #include "vm_param.h"
        !            38: #include <kern/time_out.h>
        !            39: #include <device/device_types.h>
        !            40: #include <device/errno.h>
        !            41: #include <device/io_req.h>
        !            42: #include <device/if_hdr.h>
        !            43: #include <device/if_ether.h>
        !            44: #include <device/net_status.h>
        !            45: #include <device/net_io.h>
        !            46: #include <chips/busses.h>
        !            47: #include <i386/machspl.h>
        !            48: #include <i386/pio.h>
        !            49: #include <i386at/gpl/if_nsreg.h>
        !            50: 
        !            51: #define WD_START_PG    0x00    /* first page of TX buffer */
        !            52: #define WD03_STOP_PG   0x20    /* last page +1 of RX ring */
        !            53: #define WD13_STOP_PG   0x40    /* last page +1 of RX ring */
        !            54: 
        !            55: #define WD_CMDREG      0       /* offset of ASIC command register */
        !            56: #define  WD_RESET      0x80    /* board reset in WDTRA_CMDREG */
        !            57: #define  WD_MEMEN      0x40    /* enable shared memory */
        !            58: #define WD_CMDREG5     5       /* offset of 16-bit-only ASIC register 5 */
        !            59: #define  ISA16         0x80    /* enable 16 bit access from the ISA bus */
        !            60: #define  NIC16         0x40    /* enable 16 bit access from the 8390 */
        !            61: #define WD_NIC_OFF     16      /* NIC register offset */
        !            62: 
        !            63: #define wdunit(dev)    minor(dev)
        !            64: 
        !            65: /*
        !            66:  * Autoconfiguration stuff.
        !            67:  */
        !            68: int    wdprobe();
        !            69: void   wdattach();
        !            70: int    wdstd[] = { 0x300, 0x280, 0x380, 0x240, 0 };
        !            71: struct bus_device *wdinfo[NWD];
        !            72: struct bus_driver wddriver = {
        !            73:        wdprobe, 0, wdattach, 0, wdstd, "wd", wdinfo, 0, 0, 0
        !            74: };
        !            75: 
        !            76: /*
        !            77:  * NS8390 state.
        !            78:  */
        !            79: struct nssoftc wdnssoftc[NWD];
        !            80: 
        !            81: /*
        !            82:  * Board state.
        !            83:  */
        !            84: struct wdsoftc {
        !            85:        int     sc_mstart;      /* start of board's RAM */
        !            86:        int     sc_mend;        /* end of board's RAM */
        !            87:        int     sc_rmstart;     /* start of receive RAM */
        !            88:        int     sc_rmend;       /* end of receive RAM */
        !            89:        int     sc_reg0;        /* copy of register 0 of ASIC */
        !            90:        int     sc_reg5;        /* copy of register 5 of ASIC */
        !            91: } wdsoftc[NWD];
        !            92: 
        !            93: void   wdstart(int);
        !            94: void   wd_reset(struct nssoftc *sc);
        !            95: void   wd_input(struct nssoftc *sc, int, char *, int);
        !            96: int    wd_output(struct nssoftc *sc, int, char *, int);
        !            97: 
        !            98: /*
        !            99:  * Watchdog.
        !           100:  */
        !           101: int    wdwstart = 0;
        !           102: void   wdwatch(void);
        !           103: 
        !           104: #define WDDEBUG
        !           105: #ifdef WDDEBUG
        !           106: int    wddebug = 0;
        !           107: #define DEBUGF(stmt)   { if (wddebug) stmt; }
        !           108: #else
        !           109: #define DEBUGF(stmt)
        !           110: #endif
        !           111: 
        !           112: /*
        !           113:  * Probe for the WD8003 and WD8013.
        !           114:  * These cards have the station address PROM at I/O ports <base>+8
        !           115:  * to <base>+13, with a checksum following.  A Soundblaster can have
        !           116:  * the same checksum as a WD ethercard, so we have an extra exclusionary
        !           117:  * check for it.
        !           118:  */
        !           119: int
        !           120: wdprobe(xxx, ui)
        !           121:        int xxx;
        !           122:        struct bus_device *ui;
        !           123: {
        !           124:        int *port;
        !           125: 
        !           126:        if (ui->unit >= NWD) {
        !           127:                printf("wd%d: not configured\n", ui->unit);
        !           128:                return (0);
        !           129:        }
        !           130:        for (port = wdstd; *port; port++) {
        !           131:                if (*port < 0)
        !           132:                        continue;
        !           133:                if (inb(*port + 8) != 0xff
        !           134:                    && inb(*port + 9) != 0xff
        !           135:                    && wdprobe1(*port, ui)) {
        !           136:                        ui->address = *port;
        !           137:                        *port = -1;
        !           138:                        return (1);
        !           139:                }
        !           140:        }
        !           141:        return (0);
        !           142: }
        !           143: 
        !           144: int
        !           145: wdprobe1(port, ui)
        !           146:        int port;
        !           147:        struct bus_device *ui;
        !           148: {
        !           149: 
        !           150:        int i, irq = 0, checksum = 0, ancient = 0, word16 = 0;
        !           151:        struct wdsoftc *wd = &wdsoftc[ui->unit];
        !           152:        struct nssoftc *ns = &wdnssoftc[ui->unit];
        !           153:        struct ifnet *ifp = &ns->sc_if;
        !           154: 
        !           155:        for (i = 0; i < 8; i++)
        !           156:                checksum += inb(port + 8 + i);
        !           157:        if ((checksum & 0xff) != 0xff)
        !           158:                return (0);
        !           159: 
        !           160:        printf("wd%d: WD80x3 at 0x%03x, ", ui->unit, port);
        !           161:        for (i = 0; i < ETHER_ADDR_LEN; i++) {
        !           162:                if (i == 0)
        !           163:                        printf("%02x", ns->sc_addr[i] = inb(port + 8 + i));
        !           164:                else
        !           165:                        printf(":%02x", ns->sc_addr[i] = inb(port + 8 + i));
        !           166:        }
        !           167:        /*
        !           168:         * Check for PureData.
        !           169:         */
        !           170:        if (inb(port) == 'P' && inb(port + 1) == 'D') {
        !           171:                u_char reg5 = inb(port + 5);
        !           172: 
        !           173:                switch (inb(port + 2)) {
        !           174: 
        !           175:                case 0x03:
        !           176:                case 0x05:
        !           177:                        word16 = 0;
        !           178:                        break;
        !           179: 
        !           180:                case 0x0a:
        !           181:                        word16 = 1;
        !           182:                        break;
        !           183: 
        !           184:                default:
        !           185:                        word16 = 0;
        !           186:                        break;
        !           187:                }
        !           188:                wd->sc_mstart = ((reg5 & 0x1c) + 0xc0) << 12;
        !           189:                irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1;
        !           190:        } else {
        !           191:                /*
        !           192:                 * Check for 8 bit vs 16 bit card.
        !           193:                 */
        !           194:                for (i = 0; i < ETHER_ADDR_LEN; i++)
        !           195:                        if (inb(port + i) != inb(port + 8 + i))
        !           196:                                break;
        !           197:                if (i >= ETHER_ADDR_LEN) {
        !           198:                        ancient = 1;
        !           199:                        word16 = 0;
        !           200:                } else {
        !           201:                        int tmp = inb(port + 1);
        !           202: 
        !           203:                        /*
        !           204:                         * Attempt to clear 16bit bit.
        !           205:                         */
        !           206:                        outb(port + 1, tmp ^ 0x01);
        !           207:                        if (((inb(port + 1) & 0x01) == 0x01)    /* 16 bit */
        !           208:                            && (tmp & 0x01) == 0x01) {  /* in 16 bit slot */
        !           209:                                int asic_reg5 = inb(port + WD_CMDREG5);
        !           210: 
        !           211:                                /*
        !           212:                                 * Magic to set ASIC to word-wide mode.
        !           213:                                 */
        !           214:                                outb(port+WD_CMDREG5, NIC16|(asic_reg5&0x1f));
        !           215:                                outb(port + 1, tmp);
        !           216:                                word16 = 1;
        !           217:                        } else
        !           218:                                word16 = 0;
        !           219:                        outb(port + 1, tmp);
        !           220:                }
        !           221:                if (!ancient && (inb(port + 1) & 0x01) != (word16 & 0x01))
        !           222:                        printf("\nwd%d: bus width conflict, "
        !           223:                               "%d (probe) != %d (reg report)", ui->unit,
        !           224:                               word16 ? 16 : 8, (inb(port+1) & 0x01) ? 16 : 8);
        !           225:        }
        !           226:        /*
        !           227:         * Determine board's RAM location.
        !           228:         */
        !           229:        if (wd->sc_mstart == 0) {
        !           230:                int reg0 = inb(port);
        !           231: 
        !           232:                if (reg0 == 0xff || reg0 == 0)
        !           233:                        wd->sc_mstart = 0xd0000;
        !           234:                else {
        !           235:                        int high_addr_bits = inb(port + WD_CMDREG5) & 0x1f;
        !           236: 
        !           237:                        if (high_addr_bits == 0x1f || word16 == 0)
        !           238:                                high_addr_bits = 0x01;
        !           239:                        wd->sc_mstart = ((reg0&0x3f)<<13)+(high_addr_bits<<19);
        !           240:                }
        !           241:        }
        !           242:        /*
        !           243:         * Determine irq.
        !           244:         */
        !           245:        if (irq == 0) {
        !           246:                int irqmap[] = { 9, 3, 5, 7, 10, 11, 15, 4 };
        !           247:                int reg1 = inb(port + 1);
        !           248:                int reg4 = inb(port + 4);
        !           249: 
        !           250:                /*
        !           251:                 * For old card, irq must be supplied.
        !           252:                 */
        !           253:                if (ancient || reg1 == 0xff) {
        !           254:                        if (ui->sysdep1 == 0) {
        !           255:                                printf("\nwd%d: must specify IRQ for card\n",
        !           256:                                       ui->unit);
        !           257:                                return (0);
        !           258:                        }
        !           259:                        irq = ui->sysdep1;
        !           260:                } else {
        !           261:                        DEBUGF({
        !           262:                                int i = ((reg4 >> 5) & 0x03) + (reg1 & 0x04);
        !           263: 
        !           264:                                printf("\nwd%d: irq index %d\n", ui->unit, i);
        !           265:                                printf("wd%d:", ui->unit);
        !           266:                        })
        !           267:                        irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)];
        !           268:                }
        !           269:        } else if (irq == 2)
        !           270:                irq = 9;
        !           271:        ui->sysdep1 = irq;
        !           272:        take_dev_irq(ui);
        !           273:        printf(", irq %d", irq);
        !           274: 
        !           275:        /*
        !           276:         * Initialize 8390 state.
        !           277:         */
        !           278:        ns->sc_name = ui->name;
        !           279:        ns->sc_unit = ui->unit;
        !           280:        ns->sc_port = port + WD_NIC_OFF;
        !           281:        ns->sc_reset = wd_reset;
        !           282:        ns->sc_input = wd_input;
        !           283:        ns->sc_output = wd_output;
        !           284:        ns->sc_pingpong = 1;
        !           285:        ns->sc_word16 = word16;
        !           286:        ns->sc_txstrtpg = WD_START_PG;
        !           287:        ns->sc_rxstrtpg = WD_START_PG + TX_PAGES(ns);
        !           288:        ns->sc_stoppg = word16 ? WD13_STOP_PG : WD03_STOP_PG;
        !           289: 
        !           290:        wd->sc_rmstart = wd->sc_mstart + TX_PAGES(ns) * 256;
        !           291:        wd->sc_mend = wd->sc_rmend
        !           292:                = wd->sc_mstart + (ns->sc_stoppg - WD_START_PG) * 256;
        !           293:        printf(", memory 0x%05x-0x%05x", wd->sc_mstart, wd->sc_mend);
        !           294: 
        !           295:        if (word16)
        !           296:                printf(", 16 bit");
        !           297:        printf("\n");
        !           298: 
        !           299:        DEBUGF(printf("wd%d: txstrtpg %d rxstrtpg %d num_pages %d\n",
        !           300:                      ui->unit, ns->sc_txstrtpg, ns->sc_rxstrtpg,
        !           301:                      (wd->sc_mend - wd->sc_mstart) / 256));
        !           302: 
        !           303:        /*
        !           304:         * Initialize interface header.
        !           305:         */
        !           306:        ifp->if_unit = ui->unit;
        !           307:        ifp->if_mtu = ETHERMTU;
        !           308:        ifp->if_flags = IFF_BROADCAST;
        !           309:        ifp->if_header_size = sizeof(struct ether_header);
        !           310:        ifp->if_header_format = HDR_ETHERNET;
        !           311:        ifp->if_address_size = ETHER_ADDR_LEN;
        !           312:        ifp->if_address = ns->sc_addr;
        !           313:        if_init_queues(ifp);
        !           314: 
        !           315:        return (1);
        !           316: }
        !           317: 
        !           318: void
        !           319: wdattach(ui)
        !           320:        struct bus_device *ui;
        !           321: {
        !           322:        /*
        !           323:         * void
        !           324:         */
        !           325: }
        !           326: 
        !           327: int
        !           328: wdopen(dev, flag)
        !           329:        dev_t dev;
        !           330:        int flag;
        !           331: {
        !           332:        int unit = wdunit(dev), s;
        !           333:        struct bus_device *ui;
        !           334:        struct wdsoftc *wd;
        !           335:        struct nssoftc *ns;
        !           336: 
        !           337:        if (unit >= NWD || (ui = wdinfo[unit]) == 0 || ui->alive == 0)
        !           338:                return (ENXIO);
        !           339: 
        !           340:        /*
        !           341:         * Start watchdog.
        !           342:         */
        !           343:        if (!wdwstart) {
        !           344:                wdwstart++;
        !           345:                timeout(wdwatch, 0, hz);
        !           346:        }
        !           347:        wd = &wdsoftc[unit];
        !           348:        ns = &wdnssoftc[unit];
        !           349:        ns->sc_if.if_flags |= IFF_UP;
        !           350:        s = splimp();
        !           351:        wd->sc_reg0 = ((wd->sc_mstart >> 13) & 0x3f) | WD_MEMEN;
        !           352:        wd->sc_reg5 = ((wd->sc_mstart >> 19) & 0x1f) | NIC16;
        !           353:        if (ns->sc_word16)
        !           354:                outb(ui->address + WD_CMDREG5, wd->sc_reg5);
        !           355:        outb(ui->address, wd->sc_reg0);
        !           356:        nsinit(ns);
        !           357:        splx(s);
        !           358:        return (0);
        !           359: }
        !           360: 
        !           361: int
        !           362: wdoutput(dev, ior)
        !           363:        dev_t dev;
        !           364:        io_req_t ior;
        !           365: {
        !           366:        int unit = wdunit(dev);
        !           367:        struct bus_device *ui;
        !           368: 
        !           369:        if (unit >= NWD || (ui = wdinfo[unit]) == 0 || ui->alive == 0)
        !           370:                return (ENXIO);
        !           371: 
        !           372:        return (net_write(&wdnssoftc[unit].sc_if, wdstart, ior));
        !           373: }
        !           374: 
        !           375: int
        !           376: wdsetinput(dev, receive_port, priority, filter, filter_count)
        !           377:        dev_t dev;
        !           378:        mach_port_t receive_port;
        !           379:        int priority;
        !           380:        filter_t *filter;
        !           381:        unsigned filter_count;
        !           382: {
        !           383:        int unit = wdunit(dev);
        !           384:        struct bus_device *ui;
        !           385: 
        !           386:        if (unit >= NWD || (ui = wdinfo[unit]) == 0 || ui->alive == 0)
        !           387:                return (ENXIO);
        !           388: 
        !           389:        return (net_set_filter(&wdnssoftc[unit].sc_if, receive_port,
        !           390:                               priority, filter, filter_count));
        !           391: }
        !           392: 
        !           393: int
        !           394: wdgetstat(dev, flavor, status, count)
        !           395:        dev_t dev;
        !           396:        int flavor;
        !           397:        dev_status_t status;
        !           398:        unsigned *count;
        !           399: {
        !           400:        int unit = wdunit(dev);
        !           401:        struct bus_device *ui;
        !           402: 
        !           403:        if (unit >= NWD || (ui = wdinfo[unit]) == 0 || ui->alive == 0)
        !           404:                return (ENXIO);
        !           405: 
        !           406:        return (net_getstat(&wdnssoftc[unit].sc_if, flavor, status, count));
        !           407: }
        !           408: 
        !           409: int
        !           410: wdsetstat(dev, flavor, status, count)
        !           411:        dev_t dev;
        !           412:        int flavor;
        !           413:        dev_status_t status;
        !           414:        unsigned count;
        !           415: {
        !           416:        int unit = wdunit(dev), oflags, s;
        !           417:        struct bus_device *ui;
        !           418:        struct ifnet *ifp;
        !           419:        struct net_status *ns;
        !           420: 
        !           421:        if (unit >= NWD || (ui = wdinfo[unit]) == 0 || ui->alive == 0)
        !           422:                return (ENXIO);
        !           423: 
        !           424:        ifp = &wdnssoftc[unit].sc_if;
        !           425: 
        !           426:        switch (flavor) {
        !           427: 
        !           428:        case NET_STATUS:
        !           429:                if (count < NET_STATUS_COUNT)
        !           430:                        return (D_INVALID_SIZE);
        !           431:                ns = (struct net_status *)status;
        !           432:                oflags = ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC);
        !           433:                ifp->if_flags &= ~(IFF_ALLMULTI|IFF_PROMISC);
        !           434:                ifp->if_flags |= ns->flags & (IFF_ALLMULTI|IFF_PROMISC);
        !           435:                if ((ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) != oflags) {
        !           436:                        s = splimp();
        !           437:                        nsinit(&wdnssoftc[unit]);
        !           438:                        splx(s);
        !           439:                }
        !           440:                break;
        !           441: 
        !           442:        default:
        !           443:                return (D_INVALID_OPERATION);
        !           444:        }
        !           445:        return (D_SUCCESS);
        !           446: }
        !           447: 
        !           448: void
        !           449: wdintr(unit)
        !           450:        int unit;
        !           451: {
        !           452:        nsintr(&wdnssoftc[unit]);
        !           453: }
        !           454: 
        !           455: void
        !           456: wdstart(unit)
        !           457:        int unit;
        !           458: {
        !           459:        nsstart(&wdnssoftc[unit]);
        !           460: }
        !           461: 
        !           462: void
        !           463: wd_reset(ns)
        !           464:        struct nssoftc *ns;
        !           465: {
        !           466:        int port = ns->sc_port - WD_NIC_OFF;    /* ASIC base address */
        !           467:        struct wdsoftc *wd = &wdsoftc[ns->sc_unit];
        !           468: 
        !           469:        outb(port, WD_RESET);
        !           470:        outb(0x80, 0);          /* I/O delay */
        !           471:        /*
        !           472:         * Set up the ASIC registers, just in case something changed them.
        !           473:         */
        !           474:        outb(port, ((wd->sc_mstart >> 13) & 0x3f) | WD_MEMEN);
        !           475:        if (ns->sc_word16)
        !           476:                outb(port + WD_CMDREG5, NIC16 | ((wd->sc_mstart>>19) & 0x1f));
        !           477: }
        !           478: 
        !           479: void
        !           480: wd_input(ns, count, buf, ring_offset)
        !           481:        struct nssoftc *ns;
        !           482:        int count;
        !           483:        char *buf;
        !           484:        int ring_offset;
        !           485: {
        !           486:        int port = ns->sc_port - WD_NIC_OFF;
        !           487:        int xfer_start;
        !           488:        struct wdsoftc *wd = &wdsoftc[ns->sc_unit];
        !           489: 
        !           490:        DEBUGF(printf("wd%d: ring_offset = %d\n", ns->sc_unit, ring_offset));
        !           491: 
        !           492:        xfer_start = wd->sc_mstart + ring_offset - (WD_START_PG << 8);
        !           493: 
        !           494:        /*
        !           495:         * The NIC driver calls us 3 times.  Once to read the NIC 4 byte
        !           496:         * header, next to read the Ethernet header and finally to read
        !           497:         * the actual data.  We enable 16 bit mode before the NIC header
        !           498:         * and disable it after the packet body.
        !           499:         */
        !           500:        if (count == 4) {
        !           501:                if (ns->sc_word16)
        !           502:                        outb(port + WD_CMDREG5, ISA16 | wd->sc_reg5);
        !           503:                ((int *)buf)[0] = ((int *)phystokv(xfer_start))[0];
        !           504:                return;
        !           505:        }
        !           506:        if (count == sizeof(struct ether_header)) {
        !           507:                xfer_start = (int)phystokv(xfer_start);
        !           508:                ((int *)buf)[0] = ((int *)xfer_start)[0];
        !           509:                ((int *)buf)[1] = ((int *)xfer_start)[1];
        !           510:                ((int *)buf)[2] = ((int *)xfer_start)[2];
        !           511:                ((short *)(buf + 12))[0] = ((short *)(xfer_start + 12))[0];
        !           512:                return;
        !           513:        }
        !           514:        if (xfer_start + count > wd->sc_rmend) {
        !           515:                int semi_count = wd->sc_rmend - xfer_start;
        !           516: 
        !           517:                /*
        !           518:                 * Input move must be wrapped.
        !           519:                 */
        !           520:                bcopy((char *)phystokv(xfer_start), buf, semi_count);
        !           521:                count -= semi_count;
        !           522:                bcopy((char *)phystokv(wd->sc_rmstart),buf+semi_count,count);
        !           523:        } else
        !           524:                bcopy((char *)phystokv(xfer_start), buf, count);
        !           525:        if (ns->sc_word16)
        !           526:                outb(port + WD_CMDREG5, wd->sc_reg5);
        !           527: }
        !           528: 
        !           529: int
        !           530: wd_output(ns, count, buf, start_page)
        !           531:        struct nssoftc *ns;
        !           532:        int count;
        !           533:        char *buf;
        !           534:        int start_page;
        !           535: {
        !           536:        char *shmem;
        !           537:        int i, port = ns->sc_port - WD_NIC_OFF;
        !           538:        struct wdsoftc *wd = &wdsoftc[ns->sc_unit];
        !           539: 
        !           540:        DEBUGF(printf("wd%d: start_page = %d\n", ns->sc_unit, start_page));
        !           541: 
        !           542:        shmem = (char *)phystokv(wd->sc_mstart+((start_page-WD_START_PG)<<8));
        !           543:        if (ns->sc_word16) {
        !           544:                outb(port + WD_CMDREG5, ISA16 | wd->sc_reg5);
        !           545:                bcopy(buf, shmem, count);
        !           546:                outb(port + WD_CMDREG5, wd->sc_reg5);
        !           547:        } else
        !           548:                bcopy(buf, shmem, count);
        !           549:        while (count <  ETHERMIN + sizeof(struct ether_header)) {
        !           550:                *(shmem + count) = 0;
        !           551:                count++;
        !           552:        }
        !           553:        return (count);
        !           554: }
        !           555: 
        !           556: /*
        !           557:  * Watchdog.
        !           558:  * Check for hung transmissions.
        !           559:  */
        !           560: void
        !           561: wdwatch()
        !           562: {
        !           563:        int unit, s;
        !           564:        struct nssoftc *ns;
        !           565: 
        !           566:        timeout(wdwatch, 0, hz);
        !           567: 
        !           568:        s = splimp();
        !           569:        for (unit = 0; unit < NWD; unit++) {
        !           570:                if (wdinfo[unit] == 0 || wdinfo[unit]->alive == 0)
        !           571:                        continue;
        !           572:                ns = &wdnssoftc[unit];
        !           573:                if (ns->sc_timer && --ns->sc_timer == 0) {
        !           574:                        printf("wd%d: transmission timeout\n", unit);
        !           575:                        nsinit(ns);
        !           576:                }
        !           577:        }
        !           578:        splx(s);
        !           579: }
        !           580: 
        !           581: #endif /* NWD > 0 */

unix.superglobalmegacorp.com

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