Annotation of Net2/arch/i386/isa/if_hp.c, revision 1.1.1.1

1.1       root        1: /*-
                      2:  * Copyright (c) 1990, 1991 William F. Jolitz.
                      3:  * Copyright (c) 1990 The Regents of the University of California.
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  * 3. All advertising materials mentioning features or use of this software
                     15:  *    must display the following acknowledgement:
                     16:  *     This product includes software developed by the University of
                     17:  *     California, Berkeley and its contributors.
                     18:  * 4. Neither the name of the University nor the names of its contributors
                     19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  *
                     34:  *     if_hp.c,v 1.9 1993/07/13 21:53:06 mycroft Exp
                     35:  */
                     36: 
                     37: /*
                     38:  * HP LAN Ethernet driver
                     39:  *
                     40:  * Parts inspired from Tim Tucker's if_wd driver for the wd8003,
                     41:  * insight on the ne2000 gained from Robert Clements PC/FTP driver.
                     42:  *
                     43:  * receive bottom end totally rewritten by Curt Mayer, Dec 1992.
                     44:  * no longer loses back to back packets.
                     45:  * note to driver writers: RTFM!
                     46:  *
                     47:  * hooks for packet filter added by Charles Hannum, 29DEC1992.
                     48:  *
                     49:  * Mostly rewritten for HP-labelled EISA controllers by Charles Hannum,
                     50:  * 18JAN1993.
                     51:  */
                     52: 
                     53: #include "hp.h"
                     54: #if NHP > 0
                     55: 
                     56: #include "param.h"
                     57: #include "systm.h"
                     58: #include "mbuf.h"
                     59: #include "buf.h"
                     60: #include "protosw.h"
                     61: #include "socket.h"
                     62: #include "ioctl.h"
                     63: #include "errno.h"
                     64: #include "syslog.h"
                     65: 
                     66: #include "net/if.h"
                     67: #include "net/netisr.h"
                     68: #include "net/route.h"
                     69: 
                     70: #ifdef INET
                     71: #include "netinet/in.h"
                     72: #include "netinet/in_systm.h"
                     73: #include "netinet/in_var.h"
                     74: #include "netinet/ip.h"
                     75: #include "netinet/if_ether.h"
                     76: #endif
                     77: 
                     78: #ifdef NS
                     79: #include "netns/ns.h"
                     80: #include "netns/ns_if.h"
                     81: #endif
                     82: 
                     83: #include "bpfilter.h"
                     84: #if NBPFILTER > 0
                     85: #include "net/bpf.h"
                     86: #include "net/bpfdesc.h"
                     87: #endif
                     88: 
                     89: #include "machine/cpufunc.h"
                     90: #include "i386/isa/isa_device.h"
                     91: #include "i386/isa/if_nereg.h"
                     92: #include "i386/isa/icu.h"
                     93: 
                     94: int hpprobe (), hpattach (), hpintr ();
                     95: int hpstart (), hpinit (), ether_output (), hpioctl ();
                     96: 
                     97: struct isa_driver hpdriver =
                     98: {
                     99:   hpprobe, hpattach, "hp",
                    100: };
                    101: 
                    102: struct mbuf *hpget ();
                    103: 
                    104: #define ETHER_MIN_LEN 64
                    105: #define ETHER_MAX_LEN 1536
                    106: 
                    107: /*
                    108:  * Ethernet software status per interface.
                    109:  *
                    110:  * Each interface is referenced by a network interface structure,
                    111:  * ns_if, which the routing code uses to locate the interface.
                    112:  * This structure contains the output queue for the interface, its address, ...
                    113:  */
                    114: struct hp_softc
                    115:   {
                    116:     struct arpcom ns_ac;       /* Ethernet common part */
                    117: #define        ns_if   ns_ac.ac_if     /* network-visible interface */
                    118: #define        ns_addr ns_ac.ac_enaddr /* hardware Ethernet address */
                    119:     int ns_flags;
                    120: #define        DSF_LOCK        1       /* block re-entering enstart */
                    121:     int ns_oactive;
                    122:     int ns_mask;
                    123:     struct prhdr ns_ph;                /* hardware header of incoming packet*/
                    124:     u_char ns_pb[2048];
                    125:     u_char ns_txstart;         /* transmitter buffer start */
                    126:     u_char ns_rxstart;         /* receiver buffer start */
                    127:     u_char ns_rxend;           /* receiver buffer end */
                    128:     u_char hp_type;            /* HP board type */
                    129:     u_char hp_irq;             /* interrupt vector */
                    130:     short ns_port;             /* i/o port base */
                    131:     short ns_mode;             /* word/byte mode */
                    132:     short ns_rcr;
                    133: #if NBPFILTER > 0
                    134:     caddr_t ns_bpf;
                    135: #endif
                    136:   }
                    137: 
                    138: hp_softc[NHP];
                    139: #define        ENBUFSIZE       (sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN)
                    140: 
                    141: #define        PAT(n)  (0xa55a + 37*(n))
                    142: 
                    143: u_short boarddata[16];
                    144: 
                    145: #define hp_option (-8)
                    146: #define hp_data (-4)
                    147: #define HP_RUN (0x01)
                    148: #define HP_DATA (0x10)
                    149: 
                    150: hpprobe (dvp)
                    151:      struct isa_device *dvp;
                    152: {
                    153:   int val, i, s, sum, pat;
                    154:   register struct hp_softc *ns = &hp_softc[0];
                    155:   register hpc;
                    156: 
                    157: #ifdef lint
                    158:   hpintr (0);
                    159: #endif
                    160: 
                    161:   hpc = (ns->ns_port = dvp->id_iobase + 0x10);
                    162:   s = splnet ();
                    163: 
                    164:   ns->hp_irq = ffs(dvp->id_irq) - 1;
                    165: 
                    166:   /* Extract board address */
                    167:   for (i = 0; i < 6; i++)
                    168:     ns->ns_addr[i] = inb (hpc - 0x10 + i);
                    169:   ns->hp_type = inb (hpc - 0x10 + 7);
                    170: 
                    171:   if (ns->ns_addr[0] != 0x08 ||
                    172:       ns->ns_addr[1] != 0x00 ||
                    173:       ns->ns_addr[2] != 0x09) {
                    174:     splx (s);
                    175:     return 0;
                    176:   }
                    177: 
                    178:   /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
                    179:   /* On this board, WTS means 32-bit transfers, which is still
                    180:      experimental.  - mycroft, 18JAN93 */
                    181: #ifdef HP_32BIT
                    182:   ns->ns_mode = DSDC_WTS | DSDC_BMS | DSDC_FT1;
                    183: #else
                    184:   ns->ns_mode = DSDC_BMS | DSDC_FT1;
                    185: #endif
                    186:   ns->ns_txstart =  0 * 1024 / DS_PGSIZE;
                    187:   ns->ns_rxend   = 32 * 1024 / DS_PGSIZE;
                    188: 
                    189:   ns->ns_rxstart = ns->ns_txstart + (PKTSZ / DS_PGSIZE);
                    190: 
                    191:   outb (hpc + hp_option, HP_RUN);
                    192: 
                    193: #if 0
                    194:   outb (hpc + ds0_isr, 0xff);
                    195:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_STOP);
                    196:   DELAY (1000);
                    197: 
                    198:   /* Check cmd reg and fail if not right */
                    199:   if ((i = inb (hpc + ds_cmd)) != (DSCM_NODMA | DSCM_PG0 | DSCM_STOP)) {
                    200:     splx (s);
                    201:     return (0);
                    202:   }
                    203: #endif
                    204: 
                    205:   outb (hpc + hp_option, 0);
                    206: 
                    207:   splx (s);
                    208:   return (32);
                    209: }
                    210: 
                    211: /*
                    212:  * Fetch from onboard ROM/RAM
                    213:  */
                    214: hpfetch (ns, up, ad, len)
                    215:      struct hp_softc *ns;
                    216:      caddr_t up;
                    217: {
                    218:   u_char cmd;
                    219:   register hpc = ns->ns_port;
                    220:   int counter = 100000;
                    221: 
                    222:   outb (hpc + hp_option, inb (hpc + hp_option) | HP_DATA);
                    223: 
                    224:   cmd = inb (hpc + ds_cmd);
                    225:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
                    226: 
                    227:   /* Setup remote dma */
                    228:   outb (hpc + ds0_isr, DSIS_RDC);
                    229: 
                    230:   if (ns->ns_mode & DSDC_WTS)
                    231:     len = (len + 3) & ~3;
                    232:   else
                    233:     len = (len + 1) & ~1;
                    234: 
                    235:   outb (hpc + ds0_rbcr0, len);
                    236:   outb (hpc + ds0_rbcr1, len >> 8);
                    237:   outb (hpc + ds0_rsar0, ad);
                    238:   outb (hpc + ds0_rsar1, ad >> 8);
                    239: 
                    240: #ifdef HP_DEBUG
                    241:   printf ("hpfetch: len=%d ioaddr=0x%03x addr=0x%04x option=0x%02x %d-bit\n",
                    242:          len, hpc+hp_data, ad, inb (hpc + hp_option),
                    243:          ns->ns_mode & DSDC_WTS ? 32 : 16);
                    244:   printf ("hpfetch: cmd=0x%02x isr=0x%02x ",
                    245:          inb (hpc + ds_cmd), inb (hpc + ds0_isr));
                    246:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG2 | DSCM_START);
                    247:   printf ("imr=0x%02x rcr=0x%02x tcr=0x%02x dcr=0x%02x\n",
                    248:          inb (hpc + ds0_imr), inb (hpc + ds0_rcr), inb (hpc + ds0_tcr),
                    249:          inb (hpc + ds0_dcr));
                    250: #endif
                    251: 
                    252:   /* Execute & extract from card */
                    253:   outb (hpc + ds_cmd, DSCM_RREAD | DSCM_PG0 | DSCM_START);
                    254: 
                    255: #ifdef HP_32BIT
                    256:   if (ns->ns_mode & DSDC_WTS)
                    257:     len = (caddr_t) insd (hpc + hp_data, up, len >> 2) - up;
                    258:   else
                    259: #endif
                    260:     len = (caddr_t) insw (hpc + hp_data, up, len >> 1) - up;
                    261: 
                    262: #ifdef HP_DEBUG
                    263:   printf ("hpfetch: done len=%d\n", len);
                    264: #endif
                    265: 
                    266:   /* Wait till done, then shutdown feature */
                    267:   while ((inb (hpc + ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
                    268:     ;
                    269:   outb (hpc + ds0_isr, DSIS_RDC);
                    270:   outb (hpc + ds_cmd, cmd);
                    271: 
                    272:   outb (hpc + hp_option, inb (hpc + hp_option) & ~HP_DATA);
                    273: }
                    274: 
                    275: /*
                    276:  * Put to onboard RAM
                    277:  */
                    278: hpput (ns, up, ad, len)
                    279:      struct hp_softc *ns;
                    280:      caddr_t up;
                    281: {
                    282:   u_char cmd;
                    283:   register hpc = ns->ns_port;
                    284:   int counter = 100000;
                    285: 
                    286:   outb (hpc + hp_option, inb (hpc + hp_option) | HP_DATA);
                    287: 
                    288:   cmd = inb (hpc + ds_cmd);
                    289:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
                    290: 
                    291:   /* Setup for remote dma */
                    292:   outb (hpc + ds0_isr, DSIS_RDC);
                    293: 
                    294:   if (ns->ns_mode & DSDC_WTS)
                    295:     len = (len + 3) & ~3;
                    296:   else
                    297:     len = (len + 1) & ~1;
                    298: 
                    299: #ifdef HP_DEBUG
                    300:   printf ("hpput: len=%d ioaddr=0x%03x addr=0x%04x option=0x%02x %d-bit\n",
                    301:          len, hpc+hp_data, ad, inb (hpc + hp_option),
                    302:          ns->ns_mode & DSDC_WTS ? 32 : 16);
                    303:   printf ("hpput: cmd=0x%02x isr=0x%02x ",
                    304:          inb (hpc + ds_cmd), inb (hpc + ds0_isr));
                    305:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG2 | DSCM_START);
                    306:   printf ("imr=0x%02x rcr=0x%02x tcr=0x%02x dcr=0x%02x\n",
                    307:          inb (hpc + ds0_imr), inb (hpc + ds0_rcr), inb (hpc + ds0_tcr),
                    308:          inb (hpc + ds0_dcr));
                    309:   {
                    310:     unsigned char *p = (unsigned char *) up;
                    311:     int n = len;
                    312:     printf ("hpput:");
                    313:     while (n--)
                    314:       printf (" %02x", *(p++));
                    315:     printf ("\n");
                    316:   }
                    317: #endif
                    318: 
                    319:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
                    320:   outb (hpc + ds0_rbcr0, 0xff);
                    321:   outb (hpc + ds_cmd, DSCM_RREAD | DSCM_PG0 | DSCM_START);
                    322: 
                    323:   outb (hpc + ds0_rbcr0, len);
                    324:   outb (hpc + ds0_rbcr1, len >> 8);
                    325:   outb (hpc + ds0_rsar0, ad);
                    326:   outb (hpc + ds0_rsar1, ad >> 8);
                    327: 
                    328:   /* Execute & stuff to card */
                    329:   outb (hpc + ds_cmd, DSCM_RWRITE | DSCM_PG0 | DSCM_START);
                    330: 
                    331: #ifdef HP_32BIT
                    332:   if (ns->ns_mode & DSDC_WTS)
                    333:     len = (caddr_t) outsd (hpc + hp_data, up, len >> 2) - up;
                    334:   else
                    335: #endif
                    336:     len = (caddr_t) outsw (hpc + hp_data, up, len >> 1) - up;
                    337: 
                    338: #ifdef HP_DEBUG
                    339:   printf ("hpput: done len=%d\n", len);
                    340: #endif
                    341: 
                    342:   /* Wait till done, then shutdown feature */
                    343:   while ((inb (hpc + ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
                    344:     ;
                    345:   outb (hpc + ds0_isr, DSIS_RDC);
                    346:   outb (hpc + ds_cmd, cmd);
                    347: 
                    348:   outb (hpc + hp_option, inb (hpc + hp_option) & ~HP_DATA);
                    349: }
                    350: 
                    351: /*
                    352:  * Reset of interface.
                    353:  */
                    354: hpreset (unit, uban)
                    355:      int unit, uban;
                    356: {
                    357:   register struct hp_softc *ns = &hp_softc[unit];
                    358:   register hpc = ns->ns_port;
                    359:   if (unit >= NHP)
                    360:     return;
                    361:   printf ("hp%d: reset\n", unit);
                    362:   outb (hpc + hp_option, 0);
                    363:   ns->ns_flags &= ~DSF_LOCK;
                    364:   hpinit (unit);
                    365: }
                    366: 
                    367: static char *
                    368: hp_id (type)
                    369:      u_char type;
                    370: {
                    371:   static struct
                    372:     {
                    373:       u_char type;
                    374:       char *name;
                    375:     }
                    376:   boards[] =
                    377:   { { 0x00, "hp27240" } ,
                    378:     { 0x10, "hp24240" } ,
                    379:     { 0x01, "hp27245" } ,
                    380:     { 0x02, "hp27250" } ,
                    381:     { 0x81, "hp27247" } ,
                    382:     { 0x91, "hp27247r1" } };
                    383:   int n = sizeof (boards) / sizeof (boards[0]);
                    384: 
                    385:   while (n)
                    386:     if (boards[--n].type == type)
                    387:       return boards[n].name;
                    388: 
                    389:   return "UNKNOWN";
                    390: }
                    391: 
                    392: /*
                    393:  * Interface exists: make available by filling in network interface
                    394:  * record.  System will initialize the interface when it is ready
                    395:  * to accept packets.  We get the ethernet address here.
                    396:  */
                    397: hpattach (dvp)
                    398:      struct isa_device *dvp;
                    399: {
                    400:   int unit = dvp->id_unit;
                    401:   register struct hp_softc *ns = &hp_softc[unit];
                    402:   register struct ifnet *ifp = &ns->ns_if;
                    403: 
                    404:   ifp->if_unit = unit;
                    405:   ifp->if_name = hpdriver.name;
                    406:   ifp->if_mtu = ETHERMTU;
                    407:   printf ("hp%d: %s %d-bit ethernet address %s\n", unit,
                    408:          hp_id (ns->hp_type), ns->ns_mode & DSDC_WTS ? 32 : 16,
                    409:          ether_sprintf (ns->ns_addr));
                    410:   ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
                    411:   ifp->if_init = hpinit;
                    412:   ifp->if_output = ether_output;
                    413:   ifp->if_start = hpstart;
                    414:   ifp->if_ioctl = hpioctl;
                    415:   ifp->if_reset = hpreset;
                    416:   ifp->if_watchdog = 0;
                    417:   if_attach (ifp);
                    418: 
                    419: #if NBPFILTER > 0
                    420:   bpfattach (&ns->ns_bpf, ifp, DLT_EN10MB,
                    421:             sizeof (struct ether_header));
                    422: #endif
                    423: }
                    424: 
                    425: /*
                    426:  * Initialization of interface; set up initialization block
                    427:  * and transmit/receive descriptor rings.
                    428:  */
                    429: hpinit (unit)
                    430:      int unit;
                    431: {
                    432:   register struct hp_softc *ns = &hp_softc[unit];
                    433:   struct ifnet *ifp = &ns->ns_if;
                    434:   int s;
                    435:   int i;
                    436:   char *cp;
                    437:   register hpc = ns->ns_port;
                    438: 
                    439:   if (ifp->if_addrlist == (struct ifaddr *) 0)
                    440:     return;
                    441:   if (ifp->if_flags & IFF_RUNNING)
                    442:     return;
                    443: 
                    444:   s = splnet ();
                    445: 
                    446: #ifdef HP_DEBUG
                    447:   printf ("hpinit: hp%d at 0x%x irq %d\n", unit, hpc, (int) ns->hp_irq);
                    448:   printf ("hpinit: promiscuous mode %s\n",
                    449:          ns->ns_if.if_flags & IFF_PROMISC ? "on" : "off");
                    450: #endif
                    451: 
                    452:   ns->ns_rcr = (ns->ns_if.if_flags & IFF_BROADCAST ? DSRC_AB  : 0) |
                    453:               (ns->ns_if.if_flags & IFF_PROMISC   ? DSRC_PRO : 0);
                    454: #ifdef HP_LOG_ERRORS
                    455:   ns->ns_rcr |= DSRC_SEP;
                    456: #endif
                    457: 
                    458:   /* set irq and turn on board */
                    459:   outb (hpc + hp_option, HP_RUN | (ns->hp_irq << 1));
                    460: 
                    461:   /* init regs */
                    462:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_STOP);
                    463:   outb (hpc + ds0_dcr, 0);
                    464:   outb (hpc + ds0_rbcr0, 0);
                    465:   outb (hpc + ds0_rbcr1, 0);
                    466:   outb (hpc + ds0_rcr, DSRC_MON);
                    467:   outb (hpc + ds0_tpsr, ns->ns_txstart);
                    468:   outb (hpc + ds0_imr, 0);
                    469:   outb (hpc + ds0_tcr, DSTC_LB0);
                    470:   outb (hpc + ds0_pstart, ns->ns_rxstart);
                    471:   outb (hpc + ds0_bnry, ns->ns_rxend-1);
                    472:   outb (hpc + ds0_pstop, ns->ns_rxend);
                    473:   outb (hpc + ds0_isr, 0xff);
                    474:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG1 | DSCM_STOP);
                    475:   outb (hpc + ds1_curr, ns->ns_rxstart);
                    476: 
                    477:   /* set physical address on ethernet */
                    478:   for (i = 0; i < 6; i++)
                    479:     outb (hpc + ds1_par0 + i, ns->ns_addr[i]);
                    480: 
                    481:   /* clr logical address hash filter for now */
                    482:   for (i = 0; i < 8; i++)
                    483:     outb (hpc + ds1_mar0 + i, 0xff);
                    484: 
                    485:   /* fire it up */
                    486:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
                    487:   outb (hpc + ds0_dcr, ns->ns_mode);
                    488:   outb (hpc + ds0_rcr, ns->ns_rcr);
                    489:   outb (hpc + ds0_tcr, 0);
                    490:   outb (hpc + ds0_imr, 0xff);
                    491: 
                    492:   ns->ns_if.if_flags |= IFF_RUNNING;
                    493:   ns->ns_flags &= ~DSF_LOCK;
                    494:   ns->ns_oactive = 0;
                    495:   ns->ns_mask = ~0;
                    496:   hpstart (ifp);
                    497: 
                    498: #ifdef HP_DEBUG
                    499:   printf ("hpinit: done\n", unit, hpc);
                    500: #endif
                    501: 
                    502:   splx (s);
                    503: }
                    504: 
                    505: /*
                    506:  * Setup output on interface.
                    507:  * Get another datagram to send off of the interface queue,
                    508:  * and map it to the interface before starting the output.
                    509:  * called only at splnet or interrupt level.
                    510:  */
                    511: hpstart (ifp)
                    512:      struct ifnet *ifp;
                    513: {
                    514:   register struct hp_softc *ns = &hp_softc[ifp->if_unit];
                    515:   struct mbuf *m0, *m;
                    516:   int buffer;
                    517:   int len = 0, i, total, t;
                    518:   register hpc = ns->ns_port;
                    519: 
                    520:   /*
                    521:         * The DS8390 has only one transmit buffer, if it is busy we
                    522:         * must wait until the transmit interrupt completes.
                    523:         */
                    524:   if (ns->ns_flags & DSF_LOCK)
                    525:     return;
                    526: 
                    527:   if (inb (hpc + ds_cmd) & DSCM_TRANS)
                    528:     return;
                    529: 
                    530:   if ((ns->ns_if.if_flags & IFF_RUNNING) == 0)
                    531:     return;
                    532: 
                    533:   IF_DEQUEUE (&ns->ns_if.if_snd, m);
                    534: 
                    535:   if (m == 0)
                    536:     return;
                    537: 
                    538:   /*
                    539:         * Copy the mbuf chain into the transmit buffer
                    540:         */
                    541: 
                    542:   ns->ns_flags |= DSF_LOCK;    /* prevent entering hpstart */
                    543:   buffer = ns->ns_txstart * DS_PGSIZE;
                    544:   len = i = 0;
                    545:   t = 0;
                    546:   for (m0 = m; m != 0; m = m->m_next)
                    547:     t += m->m_len;
                    548: 
                    549:   m = m0;
                    550:   total = t;
                    551: 
                    552: #ifdef HP_DEBUG
                    553:   printf ("hpstart: len=%d\n", total);
                    554: #endif
                    555: 
                    556: #if NBPFILTER > 0
                    557:   if (ns->ns_bpf)
                    558:     bpf_mtap (ns->ns_bpf, m);
                    559: #endif
                    560: 
                    561:   for (m0 = m; m != 0;)
                    562:     {
                    563:       if (m->m_len & 1 && t > m->m_len)
                    564:        {
                    565:          m->m_len -= 1;
                    566:          hpput (ns, mtod (m, caddr_t), buffer, m->m_len);
                    567:          t -= m->m_len;
                    568:          buffer += m->m_len;
                    569:          m->m_data += m->m_len;
                    570:          m->m_len = 1;
                    571:          m = m_pullup (m, 2);
                    572:        }
                    573:       else
                    574:        {
                    575:          hpput (ns, mtod (m, caddr_t), buffer, m->m_len);
                    576:          t -= m->m_len;
                    577:          buffer += m->m_len;
                    578:          MFREE (m, m0);
                    579:          m = m0;
                    580:        }
                    581:     }
                    582: 
                    583:   /*
                    584:         * Init transmit length registers, and set transmit start flag.
                    585:         */
                    586: 
                    587:   len = total;
                    588:   if (len < ETHER_MIN_LEN)
                    589:     len = ETHER_MIN_LEN;
                    590:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
                    591:   outb (hpc + ds0_tbcr0, len & 0xff);
                    592:   outb (hpc + ds0_tbcr1, (len >> 8) & 0xff);
                    593:   outb (hpc + ds0_tpsr, ns->ns_txstart);
                    594:   outb (hpc + ds_cmd, DSCM_TRANS | DSCM_NODMA | DSCM_PG0 | DSCM_START);
                    595: 
                    596: #ifdef HP_DEBUG
                    597:   printf ("hpstart: done\n", hpc);
                    598: #endif
                    599: }
                    600: 
                    601: /*
                    602:  * Controller interrupt.
                    603:  */
                    604: hpintr (unit)
                    605: {
                    606:   register struct hp_softc *ns = &hp_softc[unit];
                    607:   u_char cmd, isr;
                    608:   register hpc = ns->ns_port;
                    609:   u_char err;
                    610: 
                    611:   /* Save cmd, clear interrupt */
                    612:   cmd = inb (hpc + ds_cmd);
                    613: loop:
                    614:   isr = inb (hpc + ds0_isr);
                    615:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
                    616:   outb (hpc + ds0_isr, isr);
                    617: 
                    618:   /* Receiver error */
                    619:   if (isr & DSIS_RXE)
                    620:     {
                    621:       /* need to read these registers to clear status */
                    622:       err = inb (hpc + ds0_rsr);
                    623:       (void) inb (hpc + 0xD);
                    624:       (void) inb (hpc + 0xE);
                    625:       (void) inb (hpc + 0xF);
                    626:       ns->ns_if.if_ierrors++;
                    627: #ifdef HP_LOG_ERRORS
                    628:       isr |= DSIS_RX;
                    629: #endif
                    630:     }
                    631: 
                    632:   /* We received something */
                    633:   if (isr & DSIS_RX)
                    634:     {
                    635:       u_char bnry;
                    636:       u_char curr;
                    637:       u_short addr;
                    638:       int len;
                    639:       int i;
                    640:       unsigned char c;
                    641: 
                    642:       while (1)
                    643:        {
                    644:          outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
                    645:          bnry = inb (hpc + ds0_bnry);
                    646:          outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG1);
                    647:          curr = inb (hpc + ds1_curr);
                    648: 
                    649: #ifdef HP_DEBUG
                    650:          printf ("hpintr: receive isr=0x%02x bnry=0x%02x curr=0x%02x\n",
                    651:                  isr, bnry, curr);
                    652: #endif
                    653: 
                    654:          if (++bnry >= ns->ns_rxend)
                    655:            bnry = ns->ns_rxstart;
                    656: 
                    657:          /* if ring empty, done! */
                    658:          if (bnry == curr)
                    659:            break;
                    660: 
                    661:          addr = bnry * DS_PGSIZE;
                    662: 
                    663:          outb (hpc + hp_option, inb (hpc + hp_option) | HP_DATA);
                    664: 
                    665: #if 0
                    666:          /* send packet with auto packet release */
                    667:          outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
                    668:          outb (hpc + ds0_rbcr1, 0x0f);
                    669:          outb (hpc + ds0_dcr, ns->ns_mode | DSDC_AR);
                    670:          outb (hpc + ds_cmd, DSCM_SENDP | DSCM_PG0 | DSCM_START);
                    671: #endif
                    672: 
                    673:          /* get length */
                    674:          hpfetch (ns, (caddr_t) &ns->ns_ph, addr, sizeof ns->ns_ph);
                    675:          addr += sizeof ns->ns_ph;
                    676: 
                    677: #ifdef HP_DEBUG
                    678:          printf ("hpintr: sendp packet hdr: %x %x %x %x\n",
                    679:                  ns->ns_ph.pr_status,
                    680:                  ns->ns_ph.pr_nxtpg,
                    681:                  ns->ns_ph.pr_sz0,
                    682:                  ns->ns_ph.pr_sz1);
                    683: #endif
                    684: 
                    685: #ifdef HP_LOG_ERRORS
                    686:          if (ns->ns_ph.pr_status & (DSRS_CRC|DSRS_FO|DSRS_DFR))
                    687:            {
                    688:              /* Get packet header */
                    689:              if (len > 14)
                    690:                len = 14;
                    691:              hpfetch (ns, (caddr_t) (ns->ns_pb), addr, len);
                    692: 
                    693:              /* move boundary up */
                    694:              bnry = ns->ns_ph.pr_nxtpg;
                    695:              if (--bnry < ns->ns_rxstart)
                    696:                bnry = ns->ns_rxend-1;
                    697:              outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
                    698:              outb (hpc + ds0_bnry, bnry);
                    699: 
                    700:              printf ("hp%d: receive error status=0x%02x\n", unit,
                    701:                      ns->ns_ph.pr_status);
                    702:              printf ("hp%d: packet header:", unit);
                    703:              {
                    704:                int n;
                    705:                for (n = 0; n < len; n++)
                    706:                  printf (" %02x", ns->ns_pb[n]);
                    707:              }
                    708:              printf ("\n");
                    709: 
                    710:              continue;
                    711:            }
                    712: #endif
                    713: 
                    714:          ns->ns_if.if_ipackets++;
                    715:          len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1 << 8);
                    716:          if (len < ETHER_MIN_LEN || len > ETHER_MAX_LEN)
                    717:            {
                    718:              printf ("hpintr: bnry %x curr %x\n", bnry, curr);
                    719:              printf ("hpintr: packet hdr: %x %x %x %x\n",
                    720:                      ns->ns_ph.pr_status,
                    721:                      ns->ns_ph.pr_nxtpg,
                    722:                      ns->ns_ph.pr_sz0,
                    723:                      ns->ns_ph.pr_sz1);
                    724:              printf ("isr = 0x%x reg_isr=0x%x\n",
                    725:                      isr, inb (hpc + ds0_isr));
                    726:              outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
                    727:              bnry = inb (hpc + ds0_bnry);
                    728:              outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG1);
                    729:              curr = inb (hpc + ds1_curr);
                    730:              printf ("hpintr: new bnry %x curr %x\n", bnry, curr);
                    731:              printf ("hpintr: bad len %d\n-hanging-\n",
                    732:                      len);
                    733:              while (1);
                    734:            }
                    735: 
                    736:          /* read packet */
                    737:          hpfetch (ns, (caddr_t) (ns->ns_pb), addr, len);
                    738: 
                    739:          /* move boundary up */
                    740:          bnry = ns->ns_ph.pr_nxtpg;
                    741:          if (--bnry < ns->ns_rxstart)
                    742:            bnry = ns->ns_rxend-1;
                    743:          outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
                    744:          outb (hpc + ds0_bnry, bnry);
                    745: 
                    746: #ifdef HP_DEBUG
                    747:          printf ("hpintr: receive done bnry=0x%02x\n", bnry);
                    748: #endif
                    749: 
                    750:          outb (hpc + hp_option, inb (hpc + hp_option) & ~HP_DATA);
                    751: 
                    752:          /* adjust for ether header and checksum */
                    753:          len -= sizeof (struct ether_header) + sizeof (long);
                    754: 
                    755:          /* process packet */
                    756:          hpread (ns, (caddr_t) (ns->ns_pb), len);
                    757:        }
                    758:     }
                    759: 
                    760:   /* Transmit error */
                    761:   if (isr & DSIS_TXE)
                    762:     {
                    763:       ns->ns_flags &= ~DSF_LOCK;
                    764:       /* Need to read these registers to clear status */
                    765:       ns->ns_if.if_collisions += inb (hpc + ds0_tbcr0);
                    766:       ns->ns_if.if_oerrors++;
                    767:     }
                    768: 
                    769:   /* Packet Transmitted */
                    770:   if (isr & DSIS_TX)
                    771:     {
                    772:       ns->ns_flags &= ~DSF_LOCK;
                    773:       ++ns->ns_if.if_opackets;
                    774:       ns->ns_if.if_collisions += inb (hpc + ds0_tbcr0);
                    775:     }
                    776: 
                    777:   /* Receiver ovverun? */
                    778:   if (isr & DSIS_ROVRN)
                    779:     {
                    780:       log (LOG_ERR, "hp%d: error: isr %x\n", ns - hp_softc, isr
                    781:           /*, DSIS_BITS*/ );
                    782:       outb (hpc + ds0_rbcr0, 0);
                    783:       outb (hpc + ds0_rbcr1, 0);
                    784:       outb (hpc + ds0_tcr, DSTC_LB0);
                    785:       outb (hpc + ds0_rcr, DSRC_MON);
                    786:       outb (hpc + ds_cmd, DSCM_START | DSCM_NODMA);
                    787:       outb (hpc + ds0_rcr, ns->ns_rcr);
                    788:       outb (hpc + ds0_tcr, 0);
                    789:     }
                    790: 
                    791:   /* Any more to send? */
                    792:   outb (hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
                    793:   hpstart (&ns->ns_if);
                    794:   outb (hpc + ds_cmd, cmd);
                    795:   outb (hpc + ds0_imr, 0xff);
                    796: 
                    797:   /* Still more to do? */
                    798:   isr = inb (hpc + ds0_isr);
                    799:   if (isr)
                    800:     goto loop;
                    801: }
                    802: 
                    803: /*
                    804:  * Pass a packet to the higher levels.
                    805:  * We deal with the trailer protocol here.
                    806:  */
                    807: hpread (ns, buf, len)
                    808:      register struct hp_softc *ns;
                    809:      char *buf;
                    810:      int len;
                    811: {
                    812:   register struct ether_header *eh;
                    813:   struct mbuf *m;
                    814:   int off, resid;
                    815:   register struct ifqueue *inq;
                    816: 
                    817:   /*
                    818:         * Deal with trailer protocol: if type is trailer type
                    819:         * get true type from first 16-bit word past data.
                    820:         * Remember that type was trailer by setting off.
                    821:         */
                    822:   eh = (struct ether_header *) buf;
                    823:   eh->ether_type = ntohs ((u_short) eh->ether_type);
                    824: #define        hpdataaddr(eh, off, type)       ((type)(((caddr_t)((eh)+1)+(off))))
                    825:   if (eh->ether_type >= ETHERTYPE_TRAIL &&
                    826:       eh->ether_type < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER)
                    827:     {
                    828:       off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;
                    829:       if (off >= ETHERMTU)
                    830:        return;                 /* sanity */
                    831:       eh->ether_type = ntohs (*hpdataaddr (eh, off, u_short *));
                    832:       resid = ntohs (*(hpdataaddr (eh, off + 2, u_short *)));
                    833:       if (off + resid > len)
                    834:        return;                 /* sanity */
                    835:       len = off + resid;
                    836:     }
                    837:   else
                    838:     off = 0;
                    839: 
                    840:   if (len == 0)
                    841:     return;
                    842: 
                    843: #if NBPFILTER > 0
                    844:   if (ns->ns_bpf)
                    845:     bpf_tap (ns->ns_bpf, buf, len + sizeof (struct ether_header));
                    846: #endif
                    847: 
                    848:   if ((ns->ns_if.if_flags & IFF_PROMISC)
                    849:       && bcmp (eh->ether_dhost, ns->ns_addr,
                    850:               sizeof (eh->ether_dhost)) != 0
                    851:       && bcmp (eh->ether_dhost, etherbroadcastaddr,
                    852:               sizeof (eh->ether_dhost)) != 0)
                    853:     return;
                    854: 
                    855:   /*
                    856:         * Pull packet off interface.  Off is nonzero if packet
                    857:         * has trailing header; hpget will then force this header
                    858:         * information to be at the front, but we still have to drop
                    859:         * the type and length which are at the front of any trailer data.
                    860:         */
                    861:   m = hpget (buf, len, off, &ns->ns_if);
                    862:   if (m == 0)
                    863:     return;
                    864: 
                    865:   ether_input (&ns->ns_if, eh, m);
                    866: }
                    867: 
                    868: /*
                    869:  * Supporting routines
                    870:  */
                    871: 
                    872: /*
                    873:  * Pull read data off a interface.
                    874:  * Len is length of data, with local net header stripped.
                    875:  * Off is non-zero if a trailer protocol was used, and
                    876:  * gives the offset of the trailer information.
                    877:  * We copy the trailer information and then all the normal
                    878:  * data into mbufs.  When full cluster sized units are present
                    879:  * we copy into clusters.
                    880:  */
                    881: struct mbuf *
                    882: hpget (buf, totlen, off0, ifp)
                    883:      caddr_t buf;
                    884:      int totlen, off0;
                    885:      struct ifnet *ifp;
                    886: {
                    887:   struct mbuf *top, **mp, *m, *p;
                    888:   int off = off0, len;
                    889:   register caddr_t cp = buf;
                    890:   char *epkt;
                    891: 
                    892:   buf += sizeof (struct ether_header);
                    893:   cp = buf;
                    894:   epkt = cp + totlen;
                    895: 
                    896: 
                    897:   if (off)
                    898:     {
                    899:       cp += off + 2 * sizeof (u_short);
                    900:       totlen -= 2 * sizeof (u_short);
                    901:     }
                    902: 
                    903:   MGETHDR (m, M_DONTWAIT, MT_DATA);
                    904:   if (m == 0)
                    905:     return (0);
                    906:   m->m_pkthdr.rcvif = ifp;
                    907:   m->m_pkthdr.len = totlen;
                    908:   m->m_len = MHLEN;
                    909: 
                    910:   top = 0;
                    911:   mp = &top;
                    912:   while (totlen > 0)
                    913:     {
                    914:       if (top)
                    915:        {
                    916:          MGET (m, M_DONTWAIT, MT_DATA);
                    917:          if (m == 0)
                    918:            {
                    919:              m_freem (top);
                    920:              return (0);
                    921:            }
                    922:          m->m_len = MLEN;
                    923:        }
                    924:       len = min (totlen, epkt - cp);
                    925:       if (len >= MINCLSIZE)
                    926:        {
                    927:          MCLGET (m, M_DONTWAIT);
                    928:          if (m->m_flags & M_EXT)
                    929:            m->m_len = len = min (len, MCLBYTES);
                    930:          else
                    931:            len = m->m_len;
                    932:        }
                    933:       else
                    934:        {
                    935:          /*
                    936:                         * Place initial small packet/header at end of mbuf.
                    937:                         */
                    938:          if (len < m->m_len)
                    939:            {
                    940:              if (top == 0 && len + max_linkhdr <= m->m_len)
                    941:                m->m_data += max_linkhdr;
                    942:              m->m_len = len;
                    943:            }
                    944:          else
                    945:            len = m->m_len;
                    946:        }
                    947:       bcopy (cp, mtod (m, caddr_t), (unsigned) len);
                    948:       cp += len;
                    949:       *mp = m;
                    950:       mp = &m->m_next;
                    951:       totlen -= len;
                    952:       if (cp == epkt)
                    953:        cp = buf;
                    954:     }
                    955:   return (top);
                    956: }
                    957: 
                    958: /*
                    959:  * Process an ioctl request.
                    960:  */
                    961: hpioctl (ifp, cmd, data)
                    962:      register struct ifnet *ifp;
                    963:      int cmd;
                    964:      caddr_t data;
                    965: {
                    966:   register struct ifaddr *ifa = (struct ifaddr *) data;
                    967:   struct hp_softc *ns = &hp_softc[ifp->if_unit];
                    968:   struct ifreq *ifr = (struct ifreq *) data;
                    969:   int s = splnet (), error = 0;
                    970: 
                    971: 
                    972:   switch (cmd)
                    973:     {
                    974: 
                    975:     case SIOCSIFADDR:
                    976:       ifp->if_flags |= IFF_UP;
                    977: 
                    978:       switch (ifa->ifa_addr->sa_family)
                    979:        {
                    980: #ifdef INET
                    981:        case AF_INET:
                    982:          hpinit (ifp->if_unit);/* before arpwhohas */
                    983:          ((struct arpcom *) ifp)->ac_ipaddr =
                    984:            IA_SIN (ifa)->sin_addr;
                    985:          arpwhohas ((struct arpcom *) ifp, &IA_SIN (ifa)->sin_addr);
                    986:          break;
                    987: #endif
                    988: #ifdef NS
                    989:        case AF_NS:
                    990:          {
                    991:            register struct ns_addr *ina = &(IA_SNS (ifa)->sns_addr);
                    992: 
                    993:            if (ns_nullhost (*ina))
                    994:              ina->x_host = *(union ns_host *) (ns->ns_addr);
                    995:            else
                    996:              {
                    997:                /*
                    998:                                 * The manual says we can't change the address
                    999:                                 * while the receiver is armed,
                   1000:                                 * so reset everything
                   1001:                                 */
                   1002:                ifp->if_flags &= ~IFF_RUNNING;
                   1003:                bcopy ((caddr_t) ina->x_host.c_host,
                   1004:                       (caddr_t) ns->ns_addr, sizeof (ns->ns_addr));
                   1005:              }
                   1006:            hpinit (ifp->if_unit);      /* does hp_setaddr() */
                   1007:            break;
                   1008:          }
                   1009: #endif
                   1010:        default:
                   1011:          hpinit (ifp->if_unit);
                   1012:          break;
                   1013:        }
                   1014:       break;
                   1015: 
                   1016:     case SIOCSIFFLAGS:
                   1017: #ifdef HP_DEBUG
                   1018:       printf ("hp: setting flags, up: %s, running: %s\n",
                   1019:              ifp->if_flags & IFF_UP ? "yes" : "no",
                   1020:              ifp->if_flags & IFF_RUNNING ? "yes" : "no");
                   1021: #endif
                   1022:       if ((ifp->if_flags & IFF_UP) == 0 &&
                   1023:          ifp->if_flags & IFF_RUNNING)
                   1024:        {
                   1025:          ifp->if_flags &= ~IFF_RUNNING;
                   1026:          outb (ns->ns_port + ds_cmd, DSCM_STOP | DSCM_NODMA);
                   1027:        }
                   1028:       else if (ifp->if_flags & IFF_UP &&
                   1029:               (ifp->if_flags & IFF_RUNNING) == 0)
                   1030:        hpinit (ifp->if_unit);
                   1031:       break;
                   1032: 
                   1033: #ifdef notdef
                   1034:     case SIOCGHWADDR:
                   1035:       bcopy ((caddr_t) ns->ns_addr, (caddr_t) & ifr->ifr_data,
                   1036:             sizeof (ns->ns_addr));
                   1037:       break;
                   1038: #endif
                   1039: 
                   1040:     default:
                   1041:       error = EINVAL;
                   1042:     }
                   1043:   splx (s);
                   1044:   return (error);
                   1045: }
                   1046: 
                   1047: #endif

unix.superglobalmegacorp.com

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