|
|
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 = ⊤ ! 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.