Annotation of Gnu-Mach/i386/i386at/gpl/if_hpp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:         Written 1994 by Donald Becker.
                      3: 
                      4:         This driver is for the Hewlett Packard PC LAN (27***) plus ethercards.
                      5:         These cards are sold under several model numbers, usually 2724*.
                      6: 
                      7:         This software may be used and distributed according to the terms
                      8:         of the GNU Public License, incorporated herein by reference.
                      9: 
                     10:         The author may be reached as [email protected], or C/O
                     11: 
                     12:         Center of Excellence in Space Data and Information Sciences
                     13:                 Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
                     14: 
                     15:         As is often the case, a great deal of credit is owed to Russ Nelson.
                     16:         The Crynwr packet driver was my primary source of HP-specific
                     17:         programming information.
                     18: */
                     19: 
                     20: /*
                     21:  * Ported to mach by Stephen Clawson, [email protected]
                     22:  * University of Utah CSL.
                     23:  *
                     24:  * Derived from the Linux driver by Donald Becker.
                     25:  * 
                     26:  * Also uses code Shantanu Goel adapted from Donald Becker
                     27:  * for ns8930 support.
                     28:  *
                     29:  */
                     30: 
                     31: #include <hpp.h>
                     32: #if NHPP > 0
                     33: 
                     34: #include <sys/types.h>
                     35: #include "vm_param.h"
                     36: #include <kern/time_out.h>
                     37: #include <device/device_types.h>
                     38: #include <device/errno.h>
                     39: #include <device/io_req.h>
                     40: #include <device/if_hdr.h>
                     41: #include <device/if_ether.h>
                     42: #include <device/net_status.h>
                     43: #include <device/net_io.h>
                     44: #include <chips/busses.h>
                     45: #include <i386/ipl.h>
                     46: #include <i386/pio.h>
                     47: #include <i386at/gpl/if_nsreg.h>
                     48: 
                     49: 
                     50: /*
                     51:  * XXX - This is some gross glue garbage.  The io instructions really
                     52:  * should be integrated into pio.h...
                     53:  */
                     54: #define IO_DELAY __asm__ __volatile__("outb %al,$0x80")
                     55: #define outb_p(p, v)    { outb(p, v); IO_DELAY; }
                     56: #define inb_p(p)        ({ unsigned char _v; _v = inb(p); IO_DELAY; _v; })
                     57: 
                     58: 
                     59: static __inline void
                     60: insw(u_short port, void *addr, int cnt)
                     61: {
                     62:         __asm __volatile("cld\n\trepne\n\tinsw" :
                     63:                          : "d" (port), "D" (addr), "c" (cnt) : "%edi", "%ecx");
                     64: }
                     65: 
                     66: static __inline void
                     67: outsw(u_short port, void *addr, int cnt)
                     68: {
                     69:         __asm __volatile("cld\n\trepne\n\toutsw" :
                     70:                          : "d" (port), "S" (addr), "c" (cnt) : "%esi", "%ecx");
                     71: }
                     72: 
                     73: 
                     74: /*
                     75:    The HP EtherTwist chip implementation is a fairly routine DP8390
                     76:    implementation.  It allows both shared memory and programmed-I/O buffer
                     77:    access, using a custom interface for both.  The programmed-I/O mode is
                     78:    entirely implemented in the HP EtherTwist chip, bypassing the problem
                     79:    ridden built-in 8390 facilities used on NE2000 designs.  The shared
                     80:    memory mode is likewise special, with an offset register used to make
                     81:    packets appear at the shared memory base.  Both modes use a base and bounds
                     82:    page register to hide the Rx ring buffer wrap -- a packet that spans the
                     83:    end of physical buffer memory appears continuous to the driver. (c.f. the
                     84:    3c503 and Cabletron E2100)
                     85: 
                     86:    A special note: the internal buffer of the board is only 8 bits wide.
                     87:    This lays several nasty traps for the unaware:
                     88:    - the 8390 must be programmed for byte-wide operations
                     89:    - all I/O and memory operations must work on whole words (the access
                     90:      latches are serially preloaded and have no byte-swapping ability).
                     91: 
                     92:    This board is laid out in I/O space much like the earlier HP boards:
                     93:    the first 16 locations are for the board registers, and the second 16 are
                     94:    for the 8390.  The board is easy to identify, with both a dedicated 16 bit
                     95:    ID register and a constant 0x530* value in the upper bits of the paging
                     96:    register.
                     97: */
                     98: 
                     99: #define HP_ID                  0x00    /* ID register, always 0x4850. */
                    100: #define HP_PAGING              0x02    /* Registers visible @ 8-f, see PageName. */ 
                    101: #define HPP_OPTION             0x04    /* Bitmapped options, see HP_Option.*/
                    102: #define HPP_OUT_ADDR           0x08    /* I/O output location in Perf_Page.*/
                    103: #define HPP_IN_ADDR            0x0A    /* I/O input location in Perf_Page.*/
                    104: #define HP_DATAPORT            0x0c    /* I/O data transfer in Perf_Page.*/
                    105: #define HPP_NIC_OFFSET         0x10    /* Offset to the 8390 registers.*/
                    106: #define HP_IO_EXTENT           32
                    107: 
                    108: #define HP_START_PG            0x00    /* First page of TX buffer */
                    109: #define HP_STOP_PG             0x80    /* Last page +1 of RX ring */
                    110: /*#define HP_STOP_PG           0x1f
                    111: 
                    112: /* The register set selected in HP_PAGING. */
                    113: enum PageName {
                    114:        Perf_Page       = 0,            /* Normal operation. */
                    115:        MAC_Page        = 1,            /* The ethernet address (+checksum). */
                    116:        HW_Page         = 2,            /* EEPROM-loaded hw parameters. */
                    117:        LAN_Page        = 4,            /* Transciever type, testing, etc. */
                    118:        ID_Page         = 6 }; 
                    119: 
                    120: /* The bit definitions for the HPP_OPTION register. */
                    121: enum HP_Option {
                    122:        NICReset        = 1,            /* Active low, really UNreset. */
                    123:        ChipReset       = 2, 
                    124:        EnableIRQ       = 4, 
                    125:        FakeIntr        = 8, 
                    126:        BootROMEnb      = 0x10, 
                    127:        IOEnb           = 0x20,
                    128:        MemEnable       = 0x40, 
                    129:        ZeroWait        = 0x80, 
                    130:        MemDisable      = 0x1000, };
                    131: 
                    132: 
                    133: void hpp_reset_8390(struct nssoftc *ns);
                    134: 
                    135: void hpp_mem_block_input(struct nssoftc *ns, int, char *, int);
                    136: int hpp_mem_block_output(struct nssoftc *ns, int, char *, int);
                    137: void hpp_io_block_input(struct nssoftc *ns, int, char *, int);
                    138: int hpp_io_block_output(struct nssoftc *ns, int,char *, int);
                    139: 
                    140: 
                    141: /*
                    142:  * Watchdog timer.
                    143:  */
                    144: int    hppwstart = 0;
                    145: void   hppwatch(void);
                    146: 
                    147: 
                    148: /* 
                    149:  * Autoconfig structures.
                    150:  */
                    151: int hpp_std[] = { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0 };
                    152: struct         bus_device *hpp_info[NHPP];
                    153: int    hpp_probe();
                    154: void   hpp_attach();
                    155: struct         bus_driver hppdriver = {
                    156:        hpp_probe, 0, hpp_attach, 0, hpp_std, "hpp", hpp_info, 0, 0, 0
                    157: };
                    158: 
                    159: 
                    160: /* 
                    161:  * ns8390 state.
                    162:  */
                    163: struct nssoftc hppnssoftc[NHPP];
                    164: 
                    165: 
                    166: /*
                    167:  * hpp state.
                    168:  */
                    169: struct hppsoftc {
                    170:        unsigned long   rmem_start;     /* shmem "recv" start */
                    171:        unsigned long   rmem_end;       /* shmem "recv" end */
                    172:        unsigned long   mem_start;      /* shared mem start */
                    173:        unsigned long   mem_end;        /* shared mem end */
                    174: } hppsoftc[NHPP];
                    175: 
                    176: 
                    177: /* 
                    178:  * Probe a list of addresses for the card.
                    179:  *
                    180:  */
                    181: int hpp_probe(port, dev)
                    182:        int     port;
                    183:        struct  bus_device *dev;
                    184: {
                    185:        int unit = dev->unit;
                    186:        char *str = "hp-plus ethernet board %d out of range.\n";
                    187:        caddr_t base = (caddr_t) (dev ? dev->address : 0);
                    188:        int i;
                    189: 
                    190:        if ((unit < 0) || (unit >= NHPP)) {
                    191:                printf(str, unit);
                    192:                return(0);
                    193:        }
                    194: 
                    195:        /* Check a single specified location. */
                    196:        if (base > (caddr_t) 0x1ff)   
                    197:                return hpp_probe1(dev, base);
                    198:        else if (base != 0)                             /* Don't probe at all. */
                    199:                return 0;
                    200: 
                    201:        for (i = 0; hpp_std[i]; i++) {
                    202:                int ioaddr = hpp_std[i];
                    203: 
                    204:                if ( ioaddr > 0 && hpp_probe1(dev, ioaddr) ) {
                    205:                        dev->address = ioaddr;
                    206:                        hpp_std[i] = -1;                /* Mark address used */
                    207:                        return(1);
                    208:                }
                    209:        }
                    210: 
                    211:        return 0;
                    212: }
                    213: 
                    214: 
                    215: 
                    216: /* 
                    217:  * Do the interesting part of the probe at a single address. 
                    218:  *
                    219:  */
                    220: int hpp_probe1(dev, ioaddr)
                    221:        struct bus_device *dev;
                    222:        int ioaddr;
                    223: {
                    224:        int i;
                    225:        u_char checksum = 0;
                    226:        int mem_start;
                    227:        
                    228:        struct hppsoftc *hpp = &hppsoftc[dev->unit];
                    229:        struct nssoftc  *ns  = &hppnssoftc[dev->unit];
                    230:        struct ifnet *ifp = &ns->sc_if;
                    231: 
                    232:        /* Check for the HP+ signature, 50 48 0x 53. */
                    233:        if (inw(ioaddr + HP_ID) != 0x4850
                    234:                || (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300)
                    235:                return 0;
                    236: 
                    237: 
                    238:        printf("%s%d: HP PClan plus at %#3x,", dev->name, dev->unit, ioaddr); 
                    239:        /* Retrieve and checksum the station address. */
                    240:        outw(ioaddr + HP_PAGING, MAC_Page);
                    241: 
                    242:        printf("MAC_Page = %d, ioaddr = %x\n", MAC_Page, ioaddr);
                    243: 
                    244:        for(i = 0; i < ETHER_ADDR_LEN; i++) {
                    245:                u_char inval = inb(ioaddr + 8 + i);
                    246:                ns->sc_addr[i] = inval;  
                    247:                checksum += inval;
                    248:                printf(" %2.2x", inval);
                    249:        }
                    250:        checksum += inb(ioaddr + 14);
                    251: 
                    252:        if (checksum != 0xff) {
                    253:                printf(" bad checksum %2.2x.\n", checksum);
                    254:                return 0;
                    255:        } else {
                    256:                /* Point at the Software Configuration Flags. */
                    257:                outw(ioaddr + HP_PAGING, ID_Page);
                    258:                printf(" ID %4.4x", inw(ioaddr + 12));
                    259:        }
                    260: 
                    261: 
                    262:        /* Read the IRQ line. */
                    263:        outw(ioaddr + HP_PAGING, HW_Page);
                    264:        {
                    265:                int irq = inb(ioaddr + 13) & 0x0f;
                    266:                int option = inw(ioaddr + HPP_OPTION);
                    267: 
                    268:                dev->sysdep1 = irq;
                    269:                take_dev_irq(dev);
                    270: 
                    271:                if (option & MemEnable) {
                    272:                        mem_start = inw(ioaddr + 9) << 8;
                    273:                        printf(", IRQ %d, memory address %#x.\n", irq, mem_start);
                    274:                } else {
                    275:                        mem_start = 0;
                    276:                        printf(", IRQ %d, programmed-I/O mode.\n", irq);
                    277:                }
                    278:        }
                    279: 
                    280:        /* Set the wrap registers for string I/O reads.   */
                    281:        outw( ioaddr + 14, (HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8));
                    282: 
                    283:        /* Set the base address to point to the NIC, not the "real" base! */
                    284:        ns->sc_port = ioaddr + HPP_NIC_OFFSET;
                    285: 
                    286:        ns->sc_name = dev->name;
                    287:        ns->sc_unit = dev->unit;
                    288:        ns->sc_pingpong = 0;            /* turn off pingpong mode */
                    289:        ns->sc_word16 = 0;              /* Agggghhhhh! Debug time: 2 days! */
                    290:        ns->sc_txstrtpg = HP_START_PG;
                    291:        ns->sc_rxstrtpg = HP_START_PG + TX_2X_PAGES;
                    292:        ns->sc_stoppg = HP_STOP_PG;
                    293:        
                    294: 
                    295:        ns->sc_reset = hpp_reset_8390;
                    296:        ns->sc_input = hpp_io_block_input;
                    297:        ns->sc_output = hpp_io_block_output;
                    298: 
                    299:        /* Check if the memory_enable flag is set in the option register. */
                    300:        if (mem_start) {
                    301:                ns->sc_input = hpp_mem_block_input;
                    302:                ns->sc_output = hpp_mem_block_output;
                    303:                hpp->mem_start = mem_start;
                    304:                hpp->rmem_start = hpp->mem_start + TX_2X_PAGES * 256;
                    305:                hpp->mem_end = hpp->rmem_end
                    306:                        = hpp->mem_start + (HP_STOP_PG - HP_START_PG) * 256;
                    307:        }
                    308: 
                    309:        outw(ioaddr + HP_PAGING, Perf_Page);
                    310: 
                    311:        /* Leave the 8390 and HP chip reset. */
                    312:        outw( ioaddr + HPP_OPTION, inw(ioaddr + HPP_OPTION) & ~EnableIRQ );
                    313: 
                    314:        /*
                    315:         * Initialize interface header.
                    316:         */
                    317:        ifp->if_unit = dev->unit;
                    318:        ifp->if_mtu = ETHERMTU;
                    319:        ifp->if_flags = IFF_BROADCAST;
                    320:        ifp->if_header_size = sizeof(struct ether_header);
                    321:        ifp->if_header_format = HDR_ETHERNET;
                    322:        ifp->if_address_size = ETHER_ADDR_LEN;
                    323:        ifp->if_address = ns->sc_addr;
                    324:        if_init_queues(ifp);
                    325: 
                    326:        return (1);
                    327: }
                    328: 
                    329: /*  
                    330:  * XXX
                    331:  *
                    332:  * this routine really should do the invasive part of the setup.
                    333:  */
                    334: void
                    335: hpp_attach(dev)
                    336:        struct bus_device *dev;
                    337: {
                    338:        /* NULL */
                    339: }
                    340: 
                    341: 
                    342: 
                    343: int
                    344: hppopen(dev, flag)
                    345:        dev_t   dev;
                    346:        int     flag;
                    347: {
                    348:        int s, unit = minor(dev);
                    349:        struct bus_device       *bd;
                    350:        struct hppsoftc         *hpp;
                    351:        struct nssoftc          *ns = &hppnssoftc[unit];
                    352: 
                    353:        int ioaddr = ns->sc_port - HPP_NIC_OFFSET;
                    354:        int option_reg;
                    355: 
                    356:        if (unit < 0 || unit >= NHPP ||
                    357:            (bd = hpp_info[unit]) == 0 || !(bd->alive))
                    358:                return ENXIO;
                    359: 
                    360:        /*
                    361:         * Start watchdog.
                    362:         */
                    363:        if (!hppwstart) {
                    364:                hppwstart++;
                    365:                timeout(hppwatch, 0, hz);
                    366:        }
                    367:        hpp = &hppsoftc[unit];
                    368:        ns->sc_if.if_flags |= IFF_UP;
                    369: 
                    370:        s = splimp();
                    371: 
                    372:        /* Reset the 8390 and HP chip. */
                    373:        option_reg = inw(ioaddr + HPP_OPTION);
                    374:        outw( ioaddr + HPP_OPTION, option_reg & ~(NICReset + ChipReset) );
                    375:        IO_DELAY; IO_DELAY;
                    376: 
                    377:        /* Unreset the board and enable interrupts. */
                    378:        outw( ioaddr + HPP_OPTION, option_reg | (EnableIRQ + NICReset + ChipReset));
                    379: 
                    380:        /* Set the wrap registers for programmed-I/O operation.   */
                    381:        outw( ioaddr + HP_PAGING, HW_Page );
                    382:        outw( ioaddr + 14, (HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8) );
                    383: 
                    384:        /* Select the operational page. */
                    385:        outw( ioaddr + HP_PAGING, Perf_Page );
                    386:        nsinit(ns);
                    387: 
                    388:        splx(s);
                    389: 
                    390:        return (0);
                    391: }
                    392: 
                    393: /* 
                    394:  * needs to be called at splimp()?
                    395:  *
                    396:  */
                    397: void
                    398: hpp_reset_8390(ns)
                    399:        struct nssoftc *ns;
                    400: {
                    401:        int ioaddr = ns->sc_port - HPP_NIC_OFFSET;
                    402:        int option_reg = inw(ioaddr + HPP_OPTION);
                    403: 
                    404:        outw( ioaddr + HPP_OPTION, option_reg & ~(NICReset + ChipReset) );
                    405:        /* Pause a few cycles for the hardware reset to take place. */
                    406:        IO_DELAY;
                    407:        IO_DELAY;
                    408:        ns->sc_txing = 0;
                    409:        outw( ioaddr + HPP_OPTION, option_reg | (EnableIRQ + NICReset + ChipReset) );
                    410: 
                    411:        /*  
                    412:         * XXX - I'm not sure there needs to be this many IO_DELAY's...
                    413:         */
                    414:        IO_DELAY; IO_DELAY;
                    415:        IO_DELAY; IO_DELAY;
                    416: 
                    417:        if ((inb_p(ioaddr + HPP_NIC_OFFSET + EN0_ISR) & ENISR_RESET) == 0)
                    418:                printf("%s: hp_reset_8390() did not complete.\n", ns->sc_name);
                    419: 
                    420:        return;
                    421: }
                    422: 
                    423: 
                    424: /* 
                    425:  * Block input and output, similar to the Crynwr packet driver.
                    426:  * Note that transfer with the EtherTwist+ must be on word boundaries. 
                    427:  */
                    428: void
                    429: hpp_io_block_input(ns, count, buf, ring_offset)
                    430:        struct nssoftc *ns;
                    431:        int count;
                    432:        char *buf;
                    433:        int ring_offset;
                    434: {
                    435:        int ioaddr = ns->sc_port - HPP_NIC_OFFSET;
                    436: 
                    437:        outw(ioaddr + HPP_IN_ADDR, ring_offset);
                    438: 
                    439:        insw(ioaddr + HP_DATAPORT, buf, count >> 1 );
                    440: 
                    441:        if (count & 0x01)
                    442:                  buf[count-1] = (char) inw(ioaddr + HP_DATAPORT);
                    443: 
                    444: }
                    445: 
                    446: void
                    447: hpp_mem_block_input(ns, count, buf, ring_offset)
                    448:        struct nssoftc *ns;
                    449:        int count;
                    450:        char *buf;
                    451:        int ring_offset;
                    452: {
                    453:        int ioaddr = ns->sc_port - HPP_NIC_OFFSET;
                    454:        int option_reg = inw(ioaddr + HPP_OPTION);
                    455:        char *mem_start = (char *)phystokv(hppsoftc[ns->sc_unit].mem_start);
                    456:        
                    457:        outw(ioaddr + HPP_IN_ADDR, ring_offset);
                    458:        outw(ioaddr + HPP_OPTION, option_reg & ~(MemDisable + BootROMEnb));
                    459: 
                    460:        /* copy as much as we can straight through */
                    461:        bcopy16(mem_start, buf, count & ~1);
                    462: 
                    463:        /* Now we copy that last byte. */
                    464:        if (count & 0x01) {
                    465:                u_short savebyte[2];
                    466: 
                    467:                bcopy16(mem_start + (count & ~1), savebyte, 2);
                    468:                buf[count-1] = savebyte[0];
                    469:        }
                    470: 
                    471:        outw(ioaddr + HPP_OPTION, option_reg);
                    472: }
                    473: 
                    474: 
                    475: /*
                    476:  * output data into NIC buffers.
                    477:  *
                    478:  * NOTE: All transfers must be on word boundaries.
                    479:  */
                    480: int
                    481: hpp_io_block_output(ns, count, buf, start_page)
                    482:        struct nssoftc *ns;
                    483:        int count;
                    484:        char *buf;
                    485:        int start_page;
                    486: {
                    487:        int ioaddr = ns->sc_port - HPP_NIC_OFFSET;
                    488: 
                    489:        outw(ioaddr + HPP_OUT_ADDR, start_page << 8) ;
                    490: 
                    491:        if (count > 1) {
                    492:                outsw(ioaddr + HP_DATAPORT, buf, count >> 1);
                    493:        }
                    494: 
                    495:        if ( (count & 1) == 1 ) {
                    496:                u_char savebyte[2];
                    497: 
                    498:                savebyte[1] = 0;
                    499:                savebyte[0] = buf[count - 1];
                    500:                outw(ioaddr + HP_DATAPORT, *(u_short *)savebyte); 
                    501:        }
                    502: 
                    503:        if (count < (ETHERMIN + sizeof( struct ether_header )))
                    504:                count = ETHERMIN + sizeof( struct ether_header );
                    505: 
                    506: 
                    507:        return (count) ;
                    508: }
                    509: 
                    510: 
                    511: /* XXX
                    512:  *
                    513:  * I take great pains to not try and bcopy past the end of the buffer,
                    514:  * does this matter?  Are the io request buffers the exact byte size?
                    515:  */
                    516: int
                    517: hpp_mem_block_output(ns, count, buf, start_page )
                    518:        struct nssoftc *ns;
                    519:        int count;
                    520:        char *buf;
                    521:        int start_page;
                    522: {
                    523:        int ioaddr = ns->sc_port - HPP_NIC_OFFSET;
                    524:        int option_reg = inw(ioaddr + HPP_OPTION);
                    525:        struct hppsoftc *hpp = &hppsoftc[ns->sc_unit];
                    526:        char *shmem;
                    527: 
                    528:        outw(ioaddr + HPP_OUT_ADDR, start_page << 8);
                    529:        outw(ioaddr + HPP_OPTION, option_reg & ~(MemDisable + BootROMEnb));
                    530: 
                    531:        shmem = (char *)phystokv(hpp->mem_start);
                    532:        bcopy16(buf, shmem, count & ~1);
                    533: 
                    534:        if ( (count & 1) == 1 ) {
                    535:                u_char savebyte[2];
                    536:                
                    537:                savebyte[1] = 0;
                    538:                savebyte[0] = buf[count - 1];
                    539:                bcopy16(savebyte, shmem + (count & ~1), 2);
                    540:        }
                    541: 
                    542:        while (count < ETHERMIN + sizeof(struct ether_header)) {
                    543:                *(shmem + count) = 0;
                    544:                count++;
                    545:        }
                    546: 
                    547:        outw(ioaddr + HPP_OPTION, option_reg);
                    548: 
                    549:        return count;
                    550: }
                    551: 
                    552: 
                    553: int
                    554: hppintr(unit)
                    555:        int unit;
                    556: {
                    557:        nsintr(&hppnssoftc[unit]);
                    558:        
                    559:        return(0);
                    560: }
                    561: 
                    562: void
                    563: hppstart(unit)
                    564:        int unit;
                    565: {
                    566:        nsstart(&hppnssoftc[unit]);
                    567: }
                    568: 
                    569: int hppoutput();
                    570: 
                    571: int
                    572: hppoutput(dev, ior)
                    573:        dev_t dev;
                    574:        io_req_t ior;
                    575: {
                    576:        int unit = minor(dev);
                    577:        struct bus_device *ui;
                    578: 
                    579:        if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0)
                    580:                return (ENXIO);
                    581: 
                    582:        return (net_write(&hppnssoftc[unit].sc_if, hppstart, ior));
                    583: }
                    584: 
                    585: 
                    586: int
                    587: hppsetinput(dev, receive_port, priority, filter, filter_count)
                    588:        dev_t dev;
                    589:        mach_port_t receive_port;
                    590:        int priority;
                    591:        filter_t *filter;
                    592:        unsigned filter_count;
                    593: {
                    594:        int unit = minor(dev);
                    595:        struct bus_device *ui;
                    596: 
                    597:        if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0)
                    598:                return (ENXIO);
                    599: 
                    600:        return (net_set_filter(&hppnssoftc[unit].sc_if, receive_port,
                    601:                               priority, filter, filter_count));
                    602: }
                    603: 
                    604: 
                    605: int
                    606: hppgetstat(dev, flavor, status, count)
                    607:        dev_t dev;
                    608:        int flavor;
                    609:        dev_status_t status;
                    610:        unsigned *count;
                    611: {
                    612:        int unit = minor(dev);
                    613:        struct bus_device *ui;
                    614: 
                    615:        if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0)
                    616:                return (ENXIO);
                    617: 
                    618:        return (net_getstat(&hppnssoftc[unit].sc_if, flavor, status, count));
                    619: }
                    620: 
                    621: 
                    622: int
                    623: hppsetstat(dev, flavor, status, count)
                    624:        dev_t dev;
                    625:        int flavor;
                    626:        dev_status_t status;
                    627:        unsigned count;
                    628: {
                    629:        int unit = minor(dev), oflags, s;
                    630:        struct bus_device *ui;
                    631:        struct ifnet *ifp;
                    632:        struct net_status *ns;
                    633: 
                    634:        if (unit >= NHPP || (ui = hpp_info[unit]) == 0 || ui->alive == 0)
                    635:                return (ENXIO);
                    636: 
                    637:        ifp = &hppnssoftc[unit].sc_if;
                    638: 
                    639:        switch (flavor) {
                    640: 
                    641:        case NET_STATUS:
                    642:                if (count < NET_STATUS_COUNT)
                    643:                        return (D_INVALID_SIZE);
                    644:                ns = (struct net_status *)status;
                    645:                oflags = ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC);
                    646:                ifp->if_flags &= ~(IFF_ALLMULTI|IFF_PROMISC);
                    647:                ifp->if_flags |= ns->flags & (IFF_ALLMULTI|IFF_PROMISC);
                    648:                if ((ifp->if_flags & (IFF_ALLMULTI|IFF_PROMISC)) != oflags) {
                    649:                        s = splimp();
                    650:                        nsinit(&hppnssoftc[unit]);
                    651:                        splx(s);
                    652:                }
                    653:                break;
                    654: 
                    655:        default:
                    656:                return (D_INVALID_OPERATION);
                    657:        }
                    658:        return (D_SUCCESS);
                    659: }
                    660: 
                    661: /*
                    662:  * Watchdog.
                    663:  * Check for hung transmissions.
                    664:  */
                    665: void
                    666: hppwatch()
                    667: {
                    668:        int unit, s;
                    669:        struct nssoftc *ns;
                    670: 
                    671:        timeout(hppwatch, 0, hz);
                    672: 
                    673:        s = splimp();
                    674:        for (unit = 0; unit < NHPP; unit++) {
                    675:                if (hpp_info[unit] == 0 || hpp_info[unit]->alive == 0)
                    676:                        continue;
                    677:                ns = &hppnssoftc[unit];
                    678:                if (ns->sc_timer && --ns->sc_timer == 0) {
                    679:                        printf("hpp%d: transmission timeout\n", unit);
                    680:                        (*ns->sc_reset)(ns);
                    681:                        nsinit(ns);
                    682:                }
                    683:        }
                    684:        splx(s);
                    685: }
                    686: 
                    687: 
                    688: #endif /* NHPP > 0 */
                    689: 
                    690: 

unix.superglobalmegacorp.com

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