|
|
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_ne.c 7.4 (Berkeley) 5/21/91 ! 35: */ ! 36: ! 37: /* ! 38: * NE2000 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: ! 44: #include "ne.h" ! 45: #if NNE > 0 ! 46: ! 47: #include "param.h" ! 48: #include "systm.h" ! 49: #include "mbuf.h" ! 50: #include "buf.h" ! 51: #include "protosw.h" ! 52: #include "socket.h" ! 53: #include "ioctl.h" ! 54: #include "errno.h" ! 55: #include "syslog.h" ! 56: ! 57: #include "net/if.h" ! 58: #include "net/netisr.h" ! 59: #include "net/route.h" ! 60: ! 61: #ifdef INET ! 62: #include "netinet/in.h" ! 63: #include "netinet/in_systm.h" ! 64: #include "netinet/in_var.h" ! 65: #include "netinet/ip.h" ! 66: #include "netinet/if_ether.h" ! 67: #endif ! 68: ! 69: #ifdef NS ! 70: #include "netns/ns.h" ! 71: #include "netns/ns_if.h" ! 72: #endif ! 73: ! 74: #include "i386/isa/isa_device.h" ! 75: #include "i386/isa/if_nereg.h" ! 76: #include "i386/isa/icu.h" ! 77: ! 78: int neprobe(), neattach(), neintr(); ! 79: int nestart(),neinit(), ether_output(), neioctl(); ! 80: ! 81: struct isa_driver nedriver = { ! 82: neprobe, neattach, "ne", ! 83: }; ! 84: ! 85: struct mbuf *neget(); ! 86: ! 87: #define ETHER_MIN_LEN 64 ! 88: #define ETHER_MAX_LEN 1536 ! 89: ! 90: /* ! 91: * Ethernet software status per interface. ! 92: * ! 93: * Each interface is referenced by a network interface structure, ! 94: * ns_if, which the routing code uses to locate the interface. ! 95: * This structure contains the output queue for the interface, its address, ... ! 96: */ ! 97: struct ne_softc { ! 98: struct arpcom ns_ac; /* Ethernet common part */ ! 99: #define ns_if ns_ac.ac_if /* network-visible interface */ ! 100: #define ns_addr ns_ac.ac_enaddr /* hardware Ethernet address */ ! 101: int ns_flags; ! 102: #define DSF_LOCK 1 /* block re-entering enstart */ ! 103: int ns_oactive ; ! 104: int ns_mask ; ! 105: int ns_ba; /* byte addr in buffer ram of inc pkt */ ! 106: int ns_cur; /* current page being filled */ ! 107: struct prhdr ns_ph; /* hardware header of incoming packet*/ ! 108: struct ether_header ns_eh; /* header of incoming packet */ ! 109: u_char ns_pb[2048 /*ETHERMTU+sizeof(long)*/]; ! 110: } ne_softc[NNE] ; ! 111: #define ENBUFSIZE (sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN) ! 112: ! 113: int nec; ! 114: ! 115: u_short boarddata[16]; ! 116: ! 117: neprobe(dvp) ! 118: struct isa_device *dvp; ! 119: { ! 120: int val,i,s; ! 121: register struct ne_softc *ns = &ne_softc[0]; ! 122: ! 123: #ifdef lint ! 124: neintr(0); ! 125: #endif ! 126: ! 127: nec = dvp->id_iobase; ! 128: s = splimp(); ! 129: ! 130: /* Reset the bastard */ ! 131: val = inb(nec+ne_reset); ! 132: DELAY(2000000); ! 133: outb(nec+ne_reset,val); ! 134: ! 135: outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA); ! 136: ! 137: i = 1000000; ! 138: while ((inb(nec+ds0_isr)&DSIS_RESET) == 0 && i-- > 0); ! 139: if (i < 0) return (0); ! 140: ! 141: outb(nec+ds0_isr, 0xff); ! 142: ! 143: /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */ ! 144: outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1); ! 145: ! 146: outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); ! 147: DELAY(10000); ! 148: ! 149: /* Check cmd reg and fail if not right */ ! 150: if ((i=inb(nec+ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP)) ! 151: return(0); ! 152: ! 153: outb(nec+ds0_tcr, 0); ! 154: outb(nec+ds0_rcr, DSRC_MON); ! 155: outb(nec+ds0_pstart, RBUF/DS_PGSIZE); ! 156: outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE); ! 157: outb(nec+ds0_bnry, RBUFEND/DS_PGSIZE); ! 158: outb(nec+ds0_imr, 0); ! 159: outb(nec+ds0_isr, 0); ! 160: outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); ! 161: outb(nec+ds1_curr, RBUF/DS_PGSIZE); ! 162: outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); ! 163: ! 164: #ifdef NEDEBUG ! 165: #define PAT(n) (0xa55a + 37*(n)) ! 166: #define RCON 37 ! 167: { int i, rom, pat; ! 168: ! 169: rom=1; ! 170: printf("ne ram "); ! 171: ! 172: for (i = 0; i < 0xfff0; i+=4) { ! 173: pat = PAT(i); ! 174: neput(&pat,i,4); ! 175: nefetch(&pat,i,4); ! 176: if (pat == PAT(i)) { ! 177: if (rom) { ! 178: rom=0; ! 179: printf(" %x", i); ! 180: } ! 181: } else { ! 182: if (!rom) { ! 183: rom=1; ! 184: printf("..%x ", i); ! 185: } ! 186: } ! 187: pat=0; ! 188: neput(&pat,i,4); ! 189: } ! 190: printf("\n"); ! 191: } ! 192: #endif ! 193: ! 194: /* Extract board address */ ! 195: nefetch ((caddr_t)boarddata, 0, sizeof(boarddata)); ! 196: for(i=0; i < 6; i++) ns->ns_addr[i] = boarddata[i]; ! 197: splx(s); ! 198: return (1); ! 199: } ! 200: ! 201: /* ! 202: * Fetch from onboard ROM/RAM ! 203: */ ! 204: nefetch (up, ad, len) caddr_t up; { ! 205: u_char cmd; ! 206: ! 207: cmd = inb(nec+ds_cmd); ! 208: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); ! 209: ! 210: /* Setup remote dma */ ! 211: outb (nec+ds0_isr, DSIS_RDC); ! 212: outb (nec+ds0_rbcr0, len); ! 213: outb (nec+ds0_rbcr1, len>>8); ! 214: outb (nec+ds0_rsar0, ad); ! 215: outb (nec+ds0_rsar1, ad>>8); ! 216: ! 217: /* Execute & extract from card */ ! 218: outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START); ! 219: insw (nec+ne_data, up, len/2); ! 220: ! 221: /* Wait till done, then shutdown feature */ ! 222: while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) ; ! 223: outb (nec+ds0_isr, DSIS_RDC); ! 224: outb (nec+ds_cmd, cmd); ! 225: } ! 226: ! 227: /* ! 228: * Put to onboard RAM ! 229: */ ! 230: neput (up, ad, len) caddr_t up; { ! 231: u_char cmd; ! 232: ! 233: cmd = inb(nec+ds_cmd); ! 234: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); ! 235: ! 236: /* Setup for remote dma */ ! 237: outb (nec+ds0_isr, DSIS_RDC); ! 238: if(len&1) len++; /* roundup to words */ ! 239: outb (nec+ds0_rbcr0, len); ! 240: outb (nec+ds0_rbcr1, len>>8); ! 241: outb (nec+ds0_rsar0, ad); ! 242: outb (nec+ds0_rsar1, ad>>8); ! 243: ! 244: /* Execute & stuff to card */ ! 245: outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START); ! 246: outsw (nec+ne_data, up, len/2); ! 247: ! 248: /* Wait till done, then shutdown feature */ ! 249: while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) ; ! 250: outb (nec+ds0_isr, DSIS_RDC); ! 251: outb (nec+ds_cmd, cmd); ! 252: } ! 253: ! 254: /* ! 255: * Reset of interface. ! 256: */ ! 257: nereset(unit, uban) ! 258: int unit, uban; ! 259: { ! 260: if (unit >= NNE) ! 261: return; ! 262: printf("ne%d: reset\n", unit); ! 263: ne_softc[unit].ns_flags &= ~DSF_LOCK; ! 264: neinit(unit); ! 265: } ! 266: ! 267: /* ! 268: * Interface exists: make available by filling in network interface ! 269: * record. System will initialize the interface when it is ready ! 270: * to accept packets. We get the ethernet address here. ! 271: */ ! 272: neattach(dvp) ! 273: struct isa_device *dvp; ! 274: { ! 275: int unit = dvp->id_unit; ! 276: register struct ne_softc *ns = &ne_softc[unit]; ! 277: register struct ifnet *ifp = &ns->ns_if; ! 278: ! 279: ifp->if_unit = unit; ! 280: ifp->if_name = nedriver.name ; ! 281: ifp->if_mtu = ETHERMTU; ! 282: printf (" ethernet address %s", ether_sprintf(ns->ns_addr)) ; ! 283: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; ! 284: ifp->if_init = neinit; ! 285: ifp->if_output = ether_output; ! 286: ifp->if_start = nestart; ! 287: ifp->if_ioctl = neioctl; ! 288: ifp->if_reset = nereset; ! 289: ifp->if_watchdog = 0; ! 290: if_attach(ifp); ! 291: } ! 292: ! 293: /* ! 294: * Initialization of interface; set up initialization block ! 295: * and transmit/receive descriptor rings. ! 296: */ ! 297: neinit(unit) ! 298: int unit; ! 299: { ! 300: register struct ne_softc *ns = &ne_softc[unit]; ! 301: struct ifnet *ifp = &ns->ns_if; ! 302: int s; ! 303: register i; char *cp; ! 304: ! 305: if (ifp->if_addrlist == (struct ifaddr *)0) return; ! 306: if (ifp->if_flags & IFF_RUNNING) return; ! 307: ! 308: s = splimp(); ! 309: ! 310: /* set physical address on ethernet */ ! 311: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); ! 312: for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ns_addr[i]); ! 313: ! 314: /* clr logical address hash filter for now */ ! 315: for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff); ! 316: ! 317: /* init regs */ ! 318: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); ! 319: outb (nec+ds0_rbcr0, 0); ! 320: outb (nec+ds0_rbcr1, 0); ! 321: outb (nec+ds0_imr, 0); ! 322: outb (nec+ds0_isr, 0xff); ! 323: ! 324: /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */ ! 325: outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1); ! 326: outb(nec+ds0_tcr, 0); ! 327: outb (nec+ds0_rcr, DSRC_MON); ! 328: outb (nec+ds0_tpsr, 0); ! 329: outb(nec+ds0_pstart, RBUF/DS_PGSIZE); ! 330: outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE); ! 331: outb(nec+ds0_bnry, RBUF/DS_PGSIZE); ! 332: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); ! 333: outb(nec+ds1_curr, RBUF/DS_PGSIZE); ! 334: ns->ns_cur = RBUF/DS_PGSIZE; ! 335: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); ! 336: outb (nec+ds0_rcr, DSRC_AB); ! 337: outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1); ! 338: outb (nec+ds0_imr, 0xff); ! 339: ! 340: ns->ns_if.if_flags |= IFF_RUNNING; ! 341: ns->ns_oactive = 0; ns->ns_mask = ~0; ! 342: nestart(ifp); ! 343: splx(s); ! 344: } ! 345: ! 346: /* ! 347: * Setup output on interface. ! 348: * Get another datagram to send off of the interface queue, ! 349: * and map it to the interface before starting the output. ! 350: * called only at splimp or interrupt level. ! 351: */ ! 352: nestart(ifp) ! 353: struct ifnet *ifp; ! 354: { ! 355: register struct ne_softc *ns = &ne_softc[ifp->if_unit]; ! 356: struct mbuf *m0, *m; ! 357: int buffer; ! 358: int len = 0, i, total,t; ! 359: ! 360: /* ! 361: * The DS8390 has only one transmit buffer, if it is busy we ! 362: * must wait until the transmit interrupt completes. ! 363: */ ! 364: outb(nec+ds_cmd,DSCM_NODMA|DSCM_START); ! 365: ! 366: if (ns->ns_flags & DSF_LOCK) ! 367: return; ! 368: ! 369: if (inb(nec+ds_cmd) & DSCM_TRANS) ! 370: return; ! 371: ! 372: if ((ns->ns_if.if_flags & IFF_RUNNING) == 0) ! 373: return; ! 374: ! 375: IF_DEQUEUE(&ns->ns_if.if_snd, m); ! 376: ! 377: if (m == 0) ! 378: return; ! 379: ! 380: /* ! 381: * Copy the mbuf chain into the transmit buffer ! 382: */ ! 383: ! 384: ns->ns_flags |= DSF_LOCK; /* prevent entering nestart */ ! 385: buffer = TBUF; len = i = 0; ! 386: t = 0; ! 387: for (m0 = m; m != 0; m = m->m_next) ! 388: t += m->m_len; ! 389: ! 390: m = m0; ! 391: total = t; ! 392: for (m0 = m; m != 0; ) { ! 393: ! 394: if (m->m_len&1 && t > m->m_len) { ! 395: neput(mtod(m, caddr_t), buffer, m->m_len - 1); ! 396: t -= m->m_len - 1; ! 397: buffer += m->m_len - 1; ! 398: m->m_data += m->m_len - 1; ! 399: m->m_len = 1; ! 400: m = m_pullup(m, 2); ! 401: } else { ! 402: neput(mtod(m, caddr_t), buffer, m->m_len); ! 403: buffer += m->m_len; ! 404: t -= m->m_len; ! 405: MFREE(m, m0); ! 406: m = m0; ! 407: } ! 408: } ! 409: ! 410: /* ! 411: * Init transmit length registers, and set transmit start flag. ! 412: */ ! 413: ! 414: len = total; ! 415: if (len < ETHER_MIN_LEN) len = ETHER_MIN_LEN; ! 416: outb(nec+ds0_tbcr0,len&0xff); ! 417: outb(nec+ds0_tbcr1,(len>>8)&0xff); ! 418: outb(nec+ds0_tpsr, TBUF/DS_PGSIZE); ! 419: outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START); ! 420: } ! 421: ! 422: /* buffer successor/predecessor in ring? */ ! 423: #define succ(n) (((n)+1 >= RBUFEND/DS_PGSIZE) ? RBUF/DS_PGSIZE : (n)+1) ! 424: #define pred(n) (((n)-1 < RBUF/DS_PGSIZE) ? RBUFEND/DS_PGSIZE-1 : (n)-1) ! 425: ! 426: /* ! 427: * Controller interrupt. ! 428: */ ! 429: neintr(unit) ! 430: { ! 431: register struct ne_softc *ns = &ne_softc[unit]; ! 432: u_char cmd,isr; ! 433: ! 434: /* Save cmd, clear interrupt */ ! 435: cmd = inb (nec+ds_cmd); ! 436: loop: ! 437: isr = inb (nec+ds0_isr); ! 438: outb(nec+ds_cmd,DSCM_NODMA|DSCM_START); ! 439: outb(nec+ds0_isr, isr); ! 440: ! 441: /* Receiver error */ ! 442: if (isr & DSIS_RXE) { ! 443: /* need to read these registers to clear status */ ! 444: (void) inb(nec+ ds0_rsr); ! 445: (void) inb(nec+ 0xD); ! 446: (void) inb(nec + 0xE); ! 447: (void) inb(nec + 0xF); ! 448: ns->ns_if.if_ierrors++; ! 449: } ! 450: ! 451: /* We received something; rummage thru tiny ring buffer */ ! 452: if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) { ! 453: u_char pend,lastfree; ! 454: ! 455: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1); ! 456: pend = inb(nec+ds1_curr); ! 457: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0); ! 458: lastfree = inb(nec+ds0_bnry); ! 459: ! 460: /* Have we wrapped? */ ! 461: if (lastfree >= RBUFEND/DS_PGSIZE) ! 462: lastfree = RBUF/DS_PGSIZE; ! 463: if (pend < lastfree && ns->ns_cur < pend) ! 464: lastfree = ns->ns_cur; ! 465: else if (ns->ns_cur > lastfree) ! 466: lastfree = ns->ns_cur; ! 467: ! 468: /* Something in the buffer? */ ! 469: while (pend != lastfree) { ! 470: u_char nxt; ! 471: ! 472: /* Extract header from microcephalic board */ ! 473: nefetch(&ns->ns_ph,lastfree*DS_PGSIZE, ! 474: sizeof(ns->ns_ph)); ! 475: ns->ns_ba = lastfree*DS_PGSIZE+sizeof(ns->ns_ph); ! 476: ! 477: /* Incipient paranoia */ ! 478: if (ns->ns_ph.pr_status == DSRS_RPC || ! 479: /* for dequna's */ ! 480: ns->ns_ph.pr_status == 0x21) ! 481: nerecv (ns); ! 482: #ifdef NEDEBUG ! 483: else { ! 484: printf("cur %x pnd %x lfr %x ", ! 485: ns->ns_cur, pend, lastfree); ! 486: printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg, ! 487: (ns->ns_ph.pr_sz1<<8)+ ns->ns_ph.pr_sz0); ! 488: printf("Bogus Sts %x\n", ns->ns_ph.pr_status); ! 489: } ! 490: #endif ! 491: ! 492: nxt = ns->ns_ph.pr_nxtpg ; ! 493: ! 494: /* Sanity check */ ! 495: if ( nxt >= RBUF/DS_PGSIZE && nxt <= RBUFEND/DS_PGSIZE ! 496: && nxt <= pend) ! 497: ns->ns_cur = nxt; ! 498: else ns->ns_cur = nxt = pend; ! 499: ! 500: /* Set the boundaries */ ! 501: lastfree = nxt; ! 502: outb(nec+ds0_bnry, pred(nxt)); ! 503: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1); ! 504: pend = inb(nec+ds1_curr); ! 505: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0); ! 506: } ! 507: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA); ! 508: } ! 509: ! 510: /* Transmit error */ ! 511: if (isr & DSIS_TXE) { ! 512: ns->ns_flags &= ~DSF_LOCK; ! 513: /* Need to read these registers to clear status */ ! 514: ns->ns_if.if_collisions += inb(nec+ds0_tbcr0); ! 515: ns->ns_if.if_oerrors++; ! 516: } ! 517: ! 518: /* Packet Transmitted */ ! 519: if (isr & DSIS_TX) { ! 520: ns->ns_flags &= ~DSF_LOCK; ! 521: ++ns->ns_if.if_opackets; ! 522: ns->ns_if.if_collisions += inb(nec+ds0_tbcr0); ! 523: } ! 524: ! 525: /* Receiver ovverun? */ ! 526: if (isr & DSIS_ROVRN) { ! 527: log(LOG_ERR, "ne%d: error: isr %x\n", ns-ne_softc, isr ! 528: /*, DSIS_BITS*/); ! 529: outb(nec+ds0_rbcr0, 0); ! 530: outb(nec+ds0_rbcr1, 0); ! 531: outb(nec+ds0_tcr, DSTC_LB0); ! 532: outb(nec+ds0_rcr, DSRC_MON); ! 533: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA); ! 534: outb(nec+ds0_rcr, DSRC_AB); ! 535: outb(nec+ds0_tcr, 0); ! 536: } ! 537: ! 538: /* Any more to send? */ ! 539: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); ! 540: nestart(&ns->ns_if); ! 541: outb (nec+ds_cmd, cmd); ! 542: outb (nec+ds0_imr, 0xff); ! 543: ! 544: /* Still more to do? */ ! 545: isr = inb (nec+ds0_isr); ! 546: if(isr) goto loop; ! 547: } ! 548: ! 549: /* ! 550: * Ethernet interface receiver interface. ! 551: * If input error just drop packet. ! 552: * Otherwise examine packet to determine type. If can't determine length ! 553: * from type, then have to drop packet. Othewise decapsulate ! 554: * packet based on type and pass to type specific higher-level ! 555: * input routine. ! 556: */ ! 557: nerecv(ns) ! 558: register struct ne_softc *ns; ! 559: { ! 560: int len,i; ! 561: ! 562: ns->ns_if.if_ipackets++; ! 563: len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8); ! 564: if(len < ETHER_MIN_LEN || len > ETHER_MAX_LEN) ! 565: return; ! 566: ! 567: /* this need not be so torturous - one/two bcopys at most into mbufs */ ! 568: nefetch(ns->ns_pb, ns->ns_ba, min(len,DS_PGSIZE-sizeof(ns->ns_ph))); ! 569: if (len > DS_PGSIZE-sizeof(ns->ns_ph)) { ! 570: int l = len - (DS_PGSIZE-sizeof(ns->ns_ph)), b ; ! 571: u_char *p = ns->ns_pb + (DS_PGSIZE-sizeof(ns->ns_ph)); ! 572: ! 573: if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46; ! 574: b = ns->ns_cur*DS_PGSIZE; ! 575: ! 576: while (l >= DS_PGSIZE) { ! 577: nefetch(p, b, DS_PGSIZE); ! 578: p += DS_PGSIZE; l -= DS_PGSIZE; ! 579: if(++ns->ns_cur > 0x7f) ns->ns_cur = 0x46; ! 580: b = ns->ns_cur*DS_PGSIZE; ! 581: } ! 582: if (l > 0) ! 583: nefetch(p, b, l); ! 584: } ! 585: /* don't forget checksum! */ ! 586: len -= sizeof(struct ether_header) + sizeof(long); ! 587: ! 588: neread(ns,(caddr_t)(ns->ns_pb), len); ! 589: } ! 590: ! 591: /* ! 592: * Pass a packet to the higher levels. ! 593: * We deal with the trailer protocol here. ! 594: */ ! 595: neread(ns, buf, len) ! 596: register struct ne_softc *ns; ! 597: char *buf; ! 598: int len; ! 599: { ! 600: register struct ether_header *eh; ! 601: struct mbuf *m; ! 602: int off, resid; ! 603: register struct ifqueue *inq; ! 604: ! 605: /* ! 606: * Deal with trailer protocol: if type is trailer type ! 607: * get true type from first 16-bit word past data. ! 608: * Remember that type was trailer by setting off. ! 609: */ ! 610: eh = (struct ether_header *)buf; ! 611: eh->ether_type = ntohs((u_short)eh->ether_type); ! 612: #define nedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) ! 613: if (eh->ether_type >= ETHERTYPE_TRAIL && ! 614: eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { ! 615: off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; ! 616: if (off >= ETHERMTU) return; /* sanity */ ! 617: eh->ether_type = ntohs(*nedataaddr(eh, off, u_short *)); ! 618: resid = ntohs(*(nedataaddr(eh, off+2, u_short *))); ! 619: if (off + resid > len) return; /* sanity */ ! 620: len = off + resid; ! 621: } else off = 0; ! 622: ! 623: if (len == 0) return; ! 624: ! 625: /* ! 626: * Pull packet off interface. Off is nonzero if packet ! 627: * has trailing header; neget will then force this header ! 628: * information to be at the front, but we still have to drop ! 629: * the type and length which are at the front of any trailer data. ! 630: */ ! 631: m = neget(buf, len, off, &ns->ns_if); ! 632: if (m == 0) return; ! 633: ! 634: ether_input(&ns->ns_if, eh, m); ! 635: } ! 636: ! 637: /* ! 638: * Supporting routines ! 639: */ ! 640: ! 641: /* ! 642: * Pull read data off a interface. ! 643: * Len is length of data, with local net header stripped. ! 644: * Off is non-zero if a trailer protocol was used, and ! 645: * gives the offset of the trailer information. ! 646: * We copy the trailer information and then all the normal ! 647: * data into mbufs. When full cluster sized units are present ! 648: * we copy into clusters. ! 649: */ ! 650: struct mbuf * ! 651: neget(buf, totlen, off0, ifp) ! 652: caddr_t buf; ! 653: int totlen, off0; ! 654: struct ifnet *ifp; ! 655: { ! 656: struct mbuf *top, **mp, *m, *p; ! 657: int off = off0, len; ! 658: register caddr_t cp = buf; ! 659: char *epkt; ! 660: ! 661: buf += sizeof(struct ether_header); ! 662: cp = buf; ! 663: epkt = cp + totlen; ! 664: ! 665: ! 666: if (off) { ! 667: cp += off + 2 * sizeof(u_short); ! 668: totlen -= 2 * sizeof(u_short); ! 669: } ! 670: ! 671: MGETHDR(m, M_DONTWAIT, MT_DATA); ! 672: if (m == 0) ! 673: return (0); ! 674: m->m_pkthdr.rcvif = ifp; ! 675: m->m_pkthdr.len = totlen; ! 676: m->m_len = MHLEN; ! 677: ! 678: top = 0; ! 679: mp = ⊤ ! 680: while (totlen > 0) { ! 681: if (top) { ! 682: MGET(m, M_DONTWAIT, MT_DATA); ! 683: if (m == 0) { ! 684: m_freem(top); ! 685: return (0); ! 686: } ! 687: m->m_len = MLEN; ! 688: } ! 689: len = min(totlen, epkt - cp); ! 690: if (len >= MINCLSIZE) { ! 691: MCLGET(m, M_DONTWAIT); ! 692: if (m->m_flags & M_EXT) ! 693: m->m_len = len = min(len, MCLBYTES); ! 694: else ! 695: len = m->m_len; ! 696: } else { ! 697: /* ! 698: * Place initial small packet/header at end of mbuf. ! 699: */ ! 700: if (len < m->m_len) { ! 701: if (top == 0 && len + max_linkhdr <= m->m_len) ! 702: m->m_data += max_linkhdr; ! 703: m->m_len = len; ! 704: } else ! 705: len = m->m_len; ! 706: } ! 707: bcopy(cp, mtod(m, caddr_t), (unsigned)len); ! 708: cp += len; ! 709: *mp = m; ! 710: mp = &m->m_next; ! 711: totlen -= len; ! 712: if (cp == epkt) ! 713: cp = buf; ! 714: } ! 715: return (top); ! 716: } ! 717: ! 718: /* ! 719: * Process an ioctl request. ! 720: */ ! 721: neioctl(ifp, cmd, data) ! 722: register struct ifnet *ifp; ! 723: int cmd; ! 724: caddr_t data; ! 725: { ! 726: register struct ifaddr *ifa = (struct ifaddr *)data; ! 727: struct ne_softc *ns = &ne_softc[ifp->if_unit]; ! 728: struct ifreq *ifr = (struct ifreq *)data; ! 729: int s = splimp(), error = 0; ! 730: ! 731: ! 732: switch (cmd) { ! 733: ! 734: case SIOCSIFADDR: ! 735: ifp->if_flags |= IFF_UP; ! 736: ! 737: switch (ifa->ifa_addr->sa_family) { ! 738: #ifdef INET ! 739: case AF_INET: ! 740: neinit(ifp->if_unit); /* before arpwhohas */ ! 741: ((struct arpcom *)ifp)->ac_ipaddr = ! 742: IA_SIN(ifa)->sin_addr; ! 743: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); ! 744: break; ! 745: #endif ! 746: #ifdef NS ! 747: case AF_NS: ! 748: { ! 749: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); ! 750: ! 751: if (ns_nullhost(*ina)) ! 752: ina->x_host = *(union ns_host *)(ns->ns_addr); ! 753: else { ! 754: /* ! 755: * The manual says we can't change the address ! 756: * while the receiver is armed, ! 757: * so reset everything ! 758: */ ! 759: ifp->if_flags &= ~IFF_RUNNING; ! 760: bcopy((caddr_t)ina->x_host.c_host, ! 761: (caddr_t)ns->ns_addr, sizeof(ns->ns_addr)); ! 762: } ! 763: neinit(ifp->if_unit); /* does ne_setaddr() */ ! 764: break; ! 765: } ! 766: #endif ! 767: default: ! 768: neinit(ifp->if_unit); ! 769: break; ! 770: } ! 771: break; ! 772: ! 773: case SIOCSIFFLAGS: ! 774: if ((ifp->if_flags & IFF_UP) == 0 && ! 775: ifp->if_flags & IFF_RUNNING) { ! 776: ifp->if_flags &= ~IFF_RUNNING; ! 777: outb(nec+ds_cmd,DSCM_STOP|DSCM_NODMA); ! 778: } else if (ifp->if_flags & IFF_UP && ! 779: (ifp->if_flags & IFF_RUNNING) == 0) ! 780: neinit(ifp->if_unit); ! 781: break; ! 782: ! 783: #ifdef notdef ! 784: case SIOCGHWADDR: ! 785: bcopy((caddr_t)ns->ns_addr, (caddr_t) &ifr->ifr_data, ! 786: sizeof(ns->ns_addr)); ! 787: break; ! 788: #endif ! 789: ! 790: default: ! 791: error = EINVAL; ! 792: } ! 793: splx(s); ! 794: return (error); ! 795: } ! 796: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.