Annotation of Net2/arch/i386/isa/if_hp.c, revision 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.