|
|
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: ! 46: ! 47: #if NNE > 0 ! 48: #ifdef MACH_KERNEL ! 49: ! 50: #include <kern/time_out.h> ! 51: #include <device/device_types.h> ! 52: #include <device/errno.h> ! 53: #include <device/io_req.h> ! 54: #include <device/if_hdr.h> ! 55: #include <device/if_ether.h> ! 56: #include <device/net_status.h> ! 57: #include <device/net_io.h> ! 58: #include <i386at/ds8390.h> ! 59: #include <i386at/if_nereg.h> ! 60: #include <i386/ipl.h> ! 61: #include <chips/busses.h> ! 62: #ifdef FIPC ! 63: #include <ipc/fipc.h> ! 64: #endif /* FIPC */ ! 65: ! 66: #else MACH_KERNEL ! 67: ! 68: #include <sys/param.h> ! 69: #include <mach/vm_param.h> ! 70: #include <sys/systm.h> ! 71: #include <sys/mbuf.h> ! 72: #include <sys/table.h> ! 73: #include <sys/buf.h> ! 74: #include <sys/protosw.h> ! 75: #include <sys/socket.h> ! 76: #include <sys/vmmac.h> ! 77: #include <sys/ioctl.h> ! 78: #include <sys/errno.h> ! 79: #include <sys/syslog.h> ! 80: #include <vm/vm_kern.h> ! 81: ! 82: #include <net/if.h> ! 83: #include <net/if_types.h> ! 84: #include <net/route.h> ! 85: ! 86: #include <netinet/in.h> ! 87: #include <netinet/in_systm.h> ! 88: #include <netinet/in_var.h> ! 89: #include <netinet/ip.h> ! 90: #include <netinet/if_ether.h> ! 91: ! 92: #include <netns/ns.h> ! 93: #include <netns/ns_if.h> ! 94: ! 95: ! 96: #include <i386/ipl.h> ! 97: #include <i386at/atbus.h> ! 98: #include <i386at/ds8390.h> ! 99: #include <i386at/if_nereg.h> ! 100: #include <i386/handler.h> ! 101: #include <i386/dispatcher.h> ! 102: int ether_output(); ! 103: int neioctl(); ! 104: ! 105: #endif ! 106: ! 107: ! 108: int neprobe(); ! 109: void neattach(); ! 110: int neintr(); ! 111: int nestart(); ! 112: int neinit(); ! 113: ! 114: static vm_offset_t ne_std[NNE] = {0}; ! 115: static struct bus_device *ne_info[NNE]; ! 116: struct bus_driver nedriver = ! 117: { neprobe, 0, neattach, 0, ne_std, "ne", ne_info, 0, 0, 0 }; ! 118: ! 119: #define ETHER_MIN_LEN 64 ! 120: #define ETHER_MAX_LEN 1536 ! 121: #define SPLNET spl6 ! 122: /* ! 123: * Ethernet software status per interface. ! 124: * ! 125: * Each interface is referenced by a network interface structure, ! 126: * ns_if, which the routing code uses to locate the interface. ! 127: * This structure contains the output queue for the interface, its address, ... ! 128: */ ! 129: typedef struct { ! 130: ! 131: #ifdef MACH_KERNEL ! 132: struct ifnet ds_if; ! 133: u_char ds_addr[6]; ! 134: #else MACH_KERNEL ! 135: struct arpcom ns_ac; /* Ethernet common part */ ! 136: #define ds_if ns_ac.ac_if /* network-visible interface */ ! 137: #define ds_addr ns_ac.ac_enaddr /* hardware Ethernet address */ ! 138: #endif MACH_KERNEL ! 139: ! 140: int ns_flags; ! 141: #define DSF_LOCK 1 /* block re-entering enstart */ ! 142: #define DSF_RUNNING 2 ! 143: int ns_oactive ; ! 144: int ns_mask ; ! 145: int ns_ba; /* byte addr in buffer ram of inc pkt */ ! 146: int ns_cur; /* current page being filled */ ! 147: struct prhdr ns_ph; /* hardware header of incoming packet*/ ! 148: struct ether_header ns_eh; /* header of incoming packet */ ! 149: u_char ns_pb[2048 /*ETHERMTU+sizeof(long)*/]; ! 150: short ns_txstart; /* transmitter buffer start */ ! 151: short ns_rxend; /* recevier buffer end */ ! 152: short ns_rxbndry; /* recevier buffer boundary */ ! 153: caddr_t ns_port; /* i/o port base */ ! 154: short ns_mode; /* word/byte mode */ ! 155: int mode; ! 156: short card_present; ! 157: #ifndef MACH_KERNEL ! 158: ihandler_t handler; ! 159: ihandler_id_t *handler_id; ! 160: #endif MACH_KERNEL ! 161: ! 162: } ne_softc_t; ! 163: ne_softc_t ne_softc[NNE]; ! 164: ! 165: #define PAT(n) (0xa55a + 37*(n)) ! 166: ! 167: u_short boarddata[16]; ! 168: ! 169: /* ! 170: * Fetch from onboard ROM/RAM ! 171: */ ! 172: nefetch (ns, up, ad, len) ne_softc_t *ns; caddr_t up; { ! 173: u_char cmd; ! 174: caddr_t nec = ns->ns_port; ! 175: int counter = 10000; ! 176: int t_len; ! 177: unsigned char last_word[2]; ! 178: char odd; ! 179: ! 180: cmd = inb (nec + ds_cmd); ! 181: outb (nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); ! 182: ! 183: /* Setup remote dma */ ! 184: outb (nec + ds0_isr, DSIS_RDC); ! 185: ! 186: t_len = len; ! 187: if ((ns->ns_mode & DSDC_WTS) && len&1) { ! 188: odd=1; ! 189: t_len++; /* roundup to words */ ! 190: } else odd=0; ! 191: ! 192: outb (nec+ds0_rbcr0, t_len); ! 193: outb (nec+ds0_rbcr1, t_len>>8); ! 194: outb (nec+ds0_rsar0, ad); ! 195: outb (nec+ds0_rsar1, ad>>8); ! 196: ! 197: /* Execute & extract from card */ ! 198: outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START); ! 199: ! 200: if (ns->ns_mode & DSDC_WTS) ! 201: if (odd) { ! 202: linw (nec+ne_data, up, len/2); ! 203: *(last_word) = inw(nec+ne_data); /* get last word */ ! 204: *(up+len-1) = last_word[0]; /* last byte */ ! 205: } else { ! 206: linw (nec+ne_data, up, len/2); ! 207: } ! 208: else ! 209: linb (nec+ne_data, up, len); ! 210: ! 211: ! 212: /* Wait till done, then shutdown feature */ ! 213: while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0) ! 214: ; ! 215: ! 216: outb (nec+ds0_isr, DSIS_RDC); ! 217: outb (nec+ds_cmd, cmd); ! 218: } ! 219: ! 220: /* ! 221: * Put to onboard RAM ! 222: */ ! 223: neput (ns, up, ad, len) ne_softc_t *ns; caddr_t up; { ! 224: u_char cmd; ! 225: caddr_t nec = ns->ns_port; ! 226: int counter = 10000; ! 227: int t_len; ! 228: int odd; ! 229: unsigned char last_word[2]; ! 230: ! 231: cmd = inb(nec+ds_cmd); ! 232: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); ! 233: ! 234: /* Setup for remote dma */ ! 235: outb (nec+ds0_isr, DSIS_RDC); ! 236: ! 237: t_len = len; ! 238: if ((ns->ns_mode & DSDC_WTS) && len&1) { ! 239: odd = 1; ! 240: t_len++; /* roundup to words */ ! 241: } else odd = 0; ! 242: ! 243: outb (nec+ds0_rbcr0, t_len); ! 244: outb (nec+ds0_rbcr1, t_len>>8); ! 245: outb (nec+ds0_rsar0, ad); ! 246: outb (nec+ds0_rsar1, ad>>8); ! 247: ! 248: /* Execute & stuff to card */ ! 249: outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START); ! 250: if (ns->ns_mode & DSDC_WTS) { ! 251: if (odd) { ! 252: loutw (nec+ne_data, up, len/2); ! 253: last_word[0] = *(up+len-1); ! 254: outw (nec+ne_data, (unsigned short) *(last_word)); ! 255: } ! 256: else { ! 257: loutw (nec+ne_data, up, len/2); ! 258: } ! 259: } ! 260: else ! 261: loutb (nec+ne_data, up, len); ! 262: ! 263: ! 264: /* Wait till done, then shutdown feature */ ! 265: while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0) ! 266: ; ! 267: ! 268: outb (nec+ds0_isr, DSIS_RDC); ! 269: outb (nec+ds_cmd, cmd); ! 270: } ! 271: ! 272: int ! 273: neprobe(port, dev) ! 274: struct bus_device *dev; ! 275: { ! 276: int val, i, sum, bytemode = 1, pat; ! 277: int unit = dev->unit; ! 278: ne_softc_t *ns = &ne_softc[unit]; ! 279: caddr_t nec; ! 280: ! 281: if ((unsigned) unit >= NNE) ! 282: return(0); ! 283: ! 284: nec = (caddr_t) ns->ns_port = dev->address; ! 285: ! 286: if (ns->card_present) { ! 287: printf("ne%s : card already present in port %x\n", ! 288: unit, nec); ! 289: return(0); ! 290: } ! 291: ! 292: if (bytemode) { ! 293: /* Byte Transfers, Burst Mode Select, Fifo at 8 bytes */ ! 294: ns->ns_mode = DSDC_BMS|DSDC_FT1; ! 295: ns->ns_txstart = TBUF8; ! 296: ns->ns_rxend = RBUFEND8; ! 297: } else { ! 298: word: ! 299: /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */ ! 300: ns->ns_mode = DSDC_WTS|DSDC_BMS|DSDC_FT1; ! 301: ns->ns_txstart = TBUF16; ! 302: ns->ns_rxend = RBUFEND16; ! 303: bytemode = 0; ! 304: } ! 305: ! 306: /* Reset the bastard */ ! 307: val = inb(nec + ne_reset); ! 308: delay(200); ! 309: outb(nec + ne_reset, val); ! 310: delay(200); ! 311: ! 312: outb(nec + ds_cmd, DSCM_STOP|DSCM_NODMA); ! 313: ! 314: i = 10000; ! 315: while ((inb(nec + ds0_isr) & DSIS_RESET) == 0 && i-- > 0); ! 316: if (i < 0) return (0); ! 317: ! 318: outb(nec + ds0_isr, 0xff); ! 319: outb(nec + ds0_dcr, ns->ns_mode); ! 320: outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); ! 321: delay(1000); ! 322: ! 323: /* Check cmd reg and fail if not right */ ! 324: if ((i = inb(nec + ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP)) ! 325: return(0); ! 326: ! 327: outb(nec + ds0_tcr, DSTC_LB0); ! 328: outb(nec + ds0_rcr, DSRC_MON); ! 329: outb(nec + ds0_pstart, ns->ns_txstart+PKTSZ); ! 330: outb(nec + ds0_pstop, ns->ns_rxend); ! 331: outb(nec + ds0_bnry, ns->ns_rxend); ! 332: outb(nec + ds0_imr, 0); ! 333: outb(nec + ds0_isr, 0); ! 334: outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); ! 335: outb(nec + ds1_curr, ns->ns_txstart+PKTSZ); ! 336: outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); ! 337: ! 338: #ifdef NEDEBUG ! 339: #define RCON 37 ! 340: { int i, rom; ! 341: ! 342: rom=1; ! 343: printf("ne ram "); ! 344: ! 345: for (i = 0; i < 0xfff0; i+=4) { ! 346: pat = PAT(i); ! 347: neput(ns, &pat,i,4); ! 348: nefetch(ns, &pat,i,4); ! 349: if (pat == PAT(i)) { ! 350: if (rom) { ! 351: rom=0; ! 352: printf(" %x", i); ! 353: } ! 354: } else { ! 355: if (!rom) { ! 356: rom=1; ! 357: printf("..%x ", i); ! 358: } ! 359: } ! 360: pat=0; ! 361: neput(ns, &pat,i,4); ! 362: } ! 363: printf("\n"); ! 364: } ! 365: #endif ! 366: ! 367: /* ! 368: * <groan> detect difference between units ! 369: * solely by where the RAM is decoded. ! 370: */ ! 371: pat = PAT(0); ! 372: neput (ns, &pat, ns->ns_txstart*DS_PGSIZE, 4); ! 373: nefetch(ns, &pat, ns->ns_txstart*DS_PGSIZE, 4); ! 374: if (pat != PAT(0)) { ! 375: if (bytemode) ! 376: goto word; ! 377: else return (0); ! 378: } ! 379: ! 380: ! 381: /* Extract board address */ ! 382: nefetch (ns, (caddr_t)boarddata, 0, sizeof(boarddata)); ! 383: ! 384: for(i=0; i < 6; i++) ! 385: ns->ds_addr[i] = boarddata[i]; ! 386: ns->card_present = 1; ! 387: return (1); ! 388: } ! 389: ! 390: /* ! 391: * Interface exists: make available by filling in network interface ! 392: * record. System will initialize the interface when it is ready ! 393: * to accept packets. We get the ethernet address here. ! 394: */ ! 395: void ! 396: neattach(dev) ! 397: struct bus_device *dev; ! 398: { ! 399: short unit = dev->unit; ! 400: ne_softc_t *ns = &ne_softc[unit]; ! 401: register struct ifnet *ifp = &(ns->ds_if); ! 402: ! 403: if ((unsigned) unit >= NNE) ! 404: return; ! 405: ! 406: #ifdef MACH_KERNEL ! 407: take_dev_irq(dev); ! 408: #else MACH_KERNEL ! 409: /* setup intr handler */ ! 410: ns->handler.ih_level = dev->dev_pic; ! 411: ns->handler.ih_handler = dev->dev_intr[0]; ! 412: ns->handler.ih_resolver = i386_resolver; ! 413: ns->handler.ih_rdev = dev; ! 414: ns->handler.ih_stats.intr_type = INTR_DEVICE; ! 415: ns->handler.ih_stats.intr_cnt = 0; ! 416: ns->handler.ih_hparam[0].intparam = unit; ! 417: if ((ns->handler_id = handler_add(&ns->handler)) != NULL) ! 418: handler_enable(ns->handler_id); ! 419: else ! 420: panic("Unable to add NEx000 interrupt handler"); ! 421: #endif MACH_KERNEL ! 422: printf (", port = %x, spl = %d, pic = %d, [%s].", ! 423: dev->address, dev->sysdep, dev->sysdep1, ! 424: ether_sprintf(ns->ds_addr)); ! 425: #ifndef MACH_KERNEL ! 426: ns->ns_ac.ac_bcastaddr = (u_char *)etherbroadcastaddr; ! 427: ns->ns_ac.ac_arphrd = ARPHRD_ETHER; ! 428: #endif MACH_KERNEL ! 429: ns->ns_flags = 0; ! 430: ns->mode = 0; ! 431: ifp->if_unit = unit; ! 432: ifp->if_mtu = ETHERMTU; ! 433: ifp->if_flags = IFF_BROADCAST; ! 434: #ifdef MACH_KERNEL ! 435: ifp->if_header_size = sizeof(struct ether_header); ! 436: ifp->if_header_format = HDR_ETHERNET; ! 437: ifp->if_address_size = 6; ! 438: ifp->if_address = (char *)&ns->ds_addr[0]; ! 439: if_init_queues(ifp); ! 440: #else MACH_KERNEL ! 441: ifp->if_name = nedriver.driver_dname; ! 442: ifp->if_init = neinit; ! 443: ifp->if_output = ether_output; ! 444: ifp->if_start = nestart; ! 445: ifp->if_ioctl = neioctl; ! 446: ifp->if_reset = nereset; ! 447: ifp->if_watchdog= 0; ! 448: if_attach(ifp); ! 449: #endif MACH_KERNEL ! 450: } ! 451: ! 452: /* ! 453: * Initialization of interface; set up initialization block ! 454: * and transmit/receive descriptor rings. ! 455: */ ! 456: neinit(unit) ! 457: int unit; ! 458: { ! 459: ne_softc_t *ns = &ne_softc[unit]; ! 460: struct ifnet *ifp = &ns->ds_if; ! 461: int i; char *cp; ! 462: int oldpri; ! 463: caddr_t nec = ns->ns_port; ! 464: ! 465: #ifndef MACH_KERNEL ! 466: if (ifp->if_addrlist == (struct ifaddr *)0) return; ! 467: #endif MACH_KERNEL ! 468: ! 469: oldpri = SPLNET(); ! 470: ! 471: outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); ! 472: ! 473: /* Word Transfer select, Burst Mode Select, Fifo at 8 bytes */ ! 474: outb(nec+ds0_dcr, ns->ns_mode); ! 475: ! 476: /* clear remote byte count resigters */ ! 477: outb (nec+ds0_rbcr0, 0); ! 478: outb (nec+ds0_rbcr1, 0); ! 479: ! 480: /* don't store incoming packets into memory for now */ ! 481: outb (nec+ds0_rcr, DSRC_MON); ! 482: ! 483: /* place NIC in internal loopback mode */ ! 484: outb(nec+ds0_tcr, DSTC_LB0); ! 485: ! 486: /* initialize transmit/recieve (ring-buffer) Page Start */ ! 487: outb (nec+ds0_tpsr, 0); ! 488: outb (nec+ds0_pstart, ns->ns_txstart+PKTSZ); ! 489: ! 490: /* initialize reciever (ring-buffer) Page Stop and Boundary */ ! 491: outb (nec+ds0_pstop, ns->ns_rxend); ! 492: outb (nec+ds0_bnry, ns->ns_txstart+PKTSZ); ! 493: ! 494: /* clear all interrupts */ ! 495: outb (nec+ds0_isr, 0xff); ! 496: ! 497: /* enable the interrupts that we care about */ ! 498: outb (nec+ds0_imr, IMR_ENABLE); ! 499: ! 500: /* set physical address on ethernet */ ! 501: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP); ! 502: for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ds_addr[i]); ! 503: ! 504: ns->ns_cur = ns->ns_txstart+PKTSZ + 1; ! 505: outb (nec+ds1_curr, ns->ns_cur); ! 506: ! 507: /* XXX deal with Reciever Configuration Register */ ! 508: /* clr logical address hash filter for now */ ! 509: for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff); ! 510: ! 511: /* set page 0 registers */ ! 512: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP); ! 513: outb (nec+ds0_rcr, DSRC_AB); ! 514: ! 515: /* take unit out of loopback mode */ ! 516: outb (nec+ds0_tcr, 0); ! 517: ! 518: ns->ds_if.if_flags |= IFF_RUNNING; ! 519: ns->ns_flags &= ~(DSF_LOCK|DSF_RUNNING); ! 520: ns->ns_oactive = 0; ns->ns_mask = ~0; ! 521: splx(oldpri); ! 522: nestart(unit); ! 523: return(1); ! 524: } ! 525: ! 526: /* ! 527: * Setup output on interface. ! 528: * Get another datagram to send off of the interface queue, ! 529: * and map it to the interface before starting the output. ! 530: * called only at splimp or interrupt level. ! 531: */ ! 532: nestart(unit) ! 533: int unit; ! 534: { ! 535: ne_softc_t *ns = &ne_softc[unit]; ! 536: struct ifnet *ifp = &ns->ds_if; ! 537: int buffer; ! 538: int len, i, total,t; ! 539: caddr_t nec = ns->ns_port; ! 540: #ifdef MACH_KERNEL ! 541: io_req_t m; ! 542: ! 543: #else MACH_KERNEL ! 544: struct mbuf *m0, *m; ! 545: #endif MACH_KERNEL ! 546: ! 547: /* ! 548: * The DS8390 has only one transmit buffer, if it is busy we ! 549: * must wait until the transmit interrupt completes. ! 550: */ ! 551: outb(nec+ds_cmd,DSCM_NODMA|DSCM_START); ! 552: ! 553: if (ns->ns_flags & DSF_LOCK) ! 554: goto done; ! 555: ! 556: if (inb(nec+ds_cmd) & DSCM_TRANS) ! 557: goto done; ! 558: ! 559: if ((ns->ds_if.if_flags & IFF_RUNNING) == 0) ! 560: goto done; ! 561: ! 562: IF_DEQUEUE(&ns->ds_if.if_snd, m); ! 563: if (m == 0) ! 564: goto done; ! 565: ! 566: /* ! 567: * Copy the mbuf chain into the transmit buffer ! 568: */ ! 569: ! 570: ns->ns_flags |= DSF_LOCK; /* prevent entering nestart */ ! 571: buffer = ns->ns_txstart*DS_PGSIZE; ! 572: #ifdef MACH_KERNEL ! 573: total = m->io_count; ! 574: neput(ns, m->io_data, buffer, total); ! 575: #else MACH_KERNEL ! 576: t = 0; len = i = 0; ! 577: for (m0 = m; m != 0; m = m->m_next) ! 578: t += m->m_len; ! 579: ! 580: m = m0; ! 581: total = t; ! 582: for (m0 = m; m != 0; ) { ! 583: ! 584: if (m->m_len&1 && t > m->m_len) { ! 585: neput(ns, mtod(m, caddr_t), buffer, m->m_len - 1); ! 586: t -= m->m_len - 1; ! 587: buffer += m->m_len - 1; ! 588: m->m_data += m->m_len - 1; ! 589: m->m_len = 1; ! 590: m = m_pullup(m, 2); ! 591: } else { ! 592: neput(ns, mtod(m, caddr_t), buffer, m->m_len); ! 593: buffer += m->m_len; ! 594: t -= m->m_len; ! 595: MFREE(m, m0); ! 596: m = m0; ! 597: } ! 598: } ! 599: #endif MACH_KERNEL ! 600: /* ! 601: * Init transmit length registers, and set transmit start flag. ! 602: */ ! 603: ! 604: len = total; ! 605: if (len < ETHER_MIN_LEN) len = ETHER_MIN_LEN; ! 606: outb(nec+ds0_tbcr0,len&0xff); ! 607: outb(nec+ds0_tbcr1,(len>>8)&0xff); ! 608: outb(nec+ds0_tpsr, ns->ns_txstart); ! 609: outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START); ! 610: ! 611: #ifdef MACH_KERNEL ! 612: iodone(m); ! 613: m = 0; ! 614: done: ! 615: #endif MACH_KERNEL ! 616: } ! 617: ! 618: /* buffer successor/predecessor in ring? */ ! 619: #define succ(n) (((n)+1 >= ns->ns_rxend) ? (ns->ns_txstart+PKTSZ) : (n)+1) ! 620: #define pred(n) (((n)-1 < (ns->ns_txstart+PKTSZ)) ? ns->ns_rxend-1 : (n)-1) ! 621: ! 622: /* ! 623: * Controller interrupt. ! 624: */ ! 625: neintr(unit) ! 626: { ! 627: ne_softc_t *ns = &ne_softc[unit]; ! 628: u_char cmd,isr; ! 629: caddr_t nec = ns->ns_port; ! 630: ! 631: /* Save cmd, clear interrupt */ ! 632: cmd = inb (nec+ds_cmd); ! 633: isr = inb (nec+ds0_isr); ! 634: loop: ! 635: outb(nec+ds_cmd,DSCM_NODMA|DSCM_START); ! 636: outb(nec+ds0_isr, isr); ! 637: ! 638: /* Receiver error */ ! 639: if (isr & DSIS_RXE) { ! 640: (void) inb(nec+ds0_rsr); ! 641: /* need to read these registers to clear status */ ! 642: ns->ds_if.if_ierrors++; ! 643: } ! 644: ! 645: /* Counters overflowed, reading the registers resets them */ ! 646: if (isr & DSIS_CTRS) { ! 647: (void) inb(nec+ds0_cntr0); ! 648: (void) inb(nec+ds0_cntr1); ! 649: (void) inb(nec+ds0_cntr2); ! 650: } ! 651: ! 652: ! 653: /* We received something; rummage thru tiny ring buffer */ ! 654: if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) { ! 655: u_char pend,lastfree; ! 656: ! 657: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1); ! 658: pend = inb(nec+ds1_curr); ! 659: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0); ! 660: ! 661: /* Something in the buffer? */ ! 662: while (pend != ns->ns_cur) { ! 663: /* Extract header from microcephalic board */ ! 664: nefetch(ns, &ns->ns_ph,ns->ns_cur*DS_PGSIZE, ! 665: sizeof(ns->ns_ph)); ! 666: ns->ns_ba = ns->ns_cur*DS_PGSIZE+sizeof(ns->ns_ph); ! 667: ! 668: /* Incipient paranoia */ ! 669: if (ns->ns_ph.pr_status == DSRS_RPC || ! 670: /* for dequna's */ ! 671: ns->ns_ph.pr_status == 0x21) { ! 672: if (nerecv(ns)) ! 673: ns->ns_cur = ns->ns_ph.pr_nxtpg ; ! 674: else { ! 675: outb(nec+ds0_bnry, pred(ns->ns_cur)); ! 676: goto short_load; ! 677: } ! 678: } ! 679: #ifdef NEDEBUG ! 680: else { ! 681: printf("cur %x pnd %x lfr %x ", ! 682: ns->ns_cur, pend, lastfree); ! 683: printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg, ! 684: (ns->ns_ph.pr_sz1<<8)+ ns->ns_ph.pr_sz0); ! 685: printf("Bogus Sts %x\n", ns->ns_ph.pr_status); ! 686: ns->ns_cur = pend; ! 687: } ! 688: #endif ! 689: outb(nec+ds0_bnry, pred(ns->ns_cur)); ! 690: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1); ! 691: pend = inb(nec+ds1_curr); ! 692: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0); ! 693: } ! 694: short_load: ! 695: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA); ! 696: } ! 697: ! 698: /* Transmit error */ ! 699: if (isr & DSIS_TXE) { ! 700: ns->ns_flags &= ~DSF_LOCK; ! 701: /* Need to read these registers to clear status */ ! 702: ns->ds_if.if_collisions += inb(nec+ds0_tbcr0); ! 703: ns->ds_if.if_oerrors++; ! 704: } ! 705: ! 706: /* Packet Transmitted */ ! 707: if (isr & DSIS_TX) { ! 708: ns->ns_flags &= ~DSF_LOCK; ! 709: ++ns->ds_if.if_opackets; ! 710: ns->ds_if.if_collisions += inb(nec+ds0_tbcr0); ! 711: } ! 712: ! 713: /* Receiver ovverun? */ ! 714: if (isr & DSIS_ROVRN) { ! 715: outb(nec+ds0_rbcr0, 0); ! 716: outb(nec+ds0_rbcr1, 0); ! 717: outb(nec+ds0_tcr, DSTC_LB0); ! 718: outb(nec+ds0_rcr, DSRC_MON); ! 719: outb(nec+ds_cmd, DSCM_START|DSCM_NODMA); ! 720: outb(nec+ds0_rcr, DSRC_AB); ! 721: outb(nec+ds0_tcr, 0); ! 722: } ! 723: ! 724: /* Any more to send? */ ! 725: outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START); ! 726: nestart(unit); ! 727: outb (nec+ds_cmd, cmd); ! 728: outb (nec+ds0_imr, IMR_ENABLE); ! 729: ! 730: /* Still more to do? */ ! 731: isr = inb (nec+ds0_isr); ! 732: if(isr) goto loop; ! 733: ! 734: return 0; ! 735: } ! 736: ! 737: /* ! 738: * Ethernet interface receiver interface. ! 739: * If input error just drop packet. ! 740: * Otherwise examine packet to determine type. If can't determine length ! 741: * from type, then have to drop packet. Othewise decapsulate ! 742: * packet based on type and pass to type specific higher-level ! 743: * input routine. ! 744: */ ! 745: nerecv(ns) ! 746: ne_softc_t *ns; ! 747: { ! 748: #ifdef MACH_KERNEL ! 749: ipc_kmsg_t new_kmsg; ! 750: struct ether_header *ehp; ! 751: struct packet_header *pkt; ! 752: register struct ifnet *ifp = &ns->ds_if; ! 753: #ifdef FIPC ! 754: char *fipc_buf; ! 755: #endif ! 756: #else MACH_KERNEL ! 757: struct mbuf *top, **mp, *m, *p; ! 758: #endif MACH_KERNEL ! 759: int len, l; ! 760: int epkt; ! 761: ! 762: ns->ds_if.if_ipackets++; ! 763: len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8); ! 764: if(len < ETHER_MIN_LEN || len > ETHER_MAX_LEN) ! 765: return 0; ! 766: ! 767: nefetch(ns, &ns->ns_eh, ns->ns_ba, sizeof(struct ether_header)); ! 768: ! 769: #ifndef MACH_KERNEL ! 770: ns->ns_eh.ether_type = ntohs((u_short)ns->ns_eh.ether_type); ! 771: #endif MACH_KERNEL ! 772: ns->ns_ba += sizeof(struct ether_header); ! 773: ! 774: /* don't forget checksum! */ ! 775: len -= (sizeof(struct ether_header) + sizeof(long)); ! 776: #ifdef MACH_KERNEL ! 777: #ifdef FIPC ! 778: if (ns->ns_eh.ether_type == FIPC_MSG_TYPE) /* fipc packet */ ! 779: { ! 780: /* We need to hand the whole packet to the handler. */ ! 781: ! 782: fipc_recvs++; ! 783: ! 784: fipc_buf = get_fipc_buffer (len, TRUE, TRUE); ! 785: ! 786: if (fipc_buf == NULL) ! 787: { ! 788: ns->ds_if.if_rcvdrops++; ! 789: return(0); ! 790: } ! 791: nefetch (ns, fipc_buf, ns->ns_ba, len); ! 792: ! 793: fipc_packet (fipc_buf, ns->ns_eh); ! 794: } ! 795: else /* net_kmsg */ ! 796: { ! 797: #endif /* FIPC */ ! 798: new_kmsg = net_kmsg_get(); ! 799: ! 800: if (new_kmsg == IKM_NULL) { ! 801: ns->ds_if.if_rcvdrops++; ! 802: return(0); ! 803: } ! 804: ! 805: ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]); ! 806: pkt = (struct packet_header *)(&net_kmsg(new_kmsg)->packet[0]); ! 807: *ehp = ns->ns_eh; ! 808: ! 809: nefetch(ns, (char *) (pkt + 1), ns->ns_ba, len); ! 810: ! 811: pkt->type = ehp->ether_type; ! 812: ! 813: pkt->length = len + sizeof(struct packet_header); ! 814: net_packet(ifp, new_kmsg, pkt->length, ethernet_priority(new_kmsg)); ! 815: #ifdef FIPC ! 816: } ! 817: #endif ! 818: ! 819: #else MACH_KERNEL ! 820: /**/ ! 821: epkt = ns->ns_ba + len; ! 822: ! 823: MGETHDR(m, M_DONTWAIT, MT_DATA); ! 824: if (m == 0) ! 825: return (0); ! 826: ! 827: m->m_pkthdr.rcvif = &ns->ds_if; ! 828: m->m_pkthdr.len = len; ! 829: m->m_len = MHLEN; ! 830: ! 831: top = 0; ! 832: mp = ⊤ ! 833: while (len > 0) { ! 834: if (top) { ! 835: MGET(m, M_DONTWAIT, MT_DATA); ! 836: if (m == 0) { ! 837: m_freem(top); ! 838: return (0); ! 839: } ! 840: m->m_len = MLEN; ! 841: } ! 842: l = min(len, epkt - ns->ns_ba); ! 843: if (l >= MINCLSIZE) { ! 844: MCLGET(m, M_DONTWAIT); ! 845: if (m->m_flags & M_EXT) ! 846: m->m_len = l = min(len, MCLBYTES); ! 847: else ! 848: l = m->m_len; ! 849: } else { ! 850: /* ! 851: * Place initial small packet/header at end of mbuf. ! 852: */ ! 853: if (l < m->m_len) { ! 854: if (top == 0 && len + max_linkhdr <= m->m_len) ! 855: m->m_data += max_linkhdr; ! 856: m->m_len = l; ! 857: } else ! 858: l = m->m_len; ! 859: } ! 860: nefetch(ns, mtod(m, caddr_t), ns->ns_ba, l); ! 861: ns->ns_ba += l; ! 862: *mp = m; ! 863: mp = &m->m_next; ! 864: len -= l; ! 865: } ! 866: /**/ ! 867: if (top == 0) return 0; /* NEED MODIFY HERE !!! */ ! 868: ! 869: ether_input(&ns->ds_if, &ns->ns_eh, top); ! 870: #endif MACH_KERNEL ! 871: return 1; ! 872: } ! 873: ! 874: #ifdef MACH_KERNEL ! 875: neopen(dev, flag) ! 876: dev_t dev; ! 877: int flag; ! 878: { ! 879: register int unit = minor(dev); ! 880: ! 881: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE) ! 882: return (ENXIO); ! 883: ! 884: ne_softc[unit].ds_if.if_flags |= IFF_UP; ! 885: neinit(unit); ! 886: return(0); ! 887: } ! 888: ! 889: #ifdef FIPC ! 890: nefoutput(dev, ior) ! 891: dev_t dev; ! 892: io_req_t ior; ! 893: { ! 894: register int unit = minor(dev); ! 895: ! 896: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE) ! 897: return (ENXIO); ! 898: ! 899: return (net_fwrite(&ne_softc[unit].ds_if, nestart, ior)); ! 900: } ! 901: #endif ! 902: ! 903: neoutput(dev, ior) ! 904: dev_t dev; ! 905: io_req_t ior; ! 906: { ! 907: register int unit = minor(dev); ! 908: ! 909: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE) ! 910: return (ENXIO); ! 911: ! 912: return (net_write(&ne_softc[unit].ds_if, nestart, ior)); ! 913: } ! 914: ! 915: nesetinput(dev, receive_port, priority, filter, filter_count) ! 916: dev_t dev; ! 917: mach_port_t receive_port; ! 918: int priority; ! 919: filter_t filter[]; ! 920: unsigned int filter_count; ! 921: { ! 922: register int unit = minor(dev); ! 923: ! 924: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE) ! 925: return (ENXIO); ! 926: ! 927: return (net_set_filter(&ne_softc[unit].ds_if, ! 928: receive_port, priority, ! 929: filter, filter_count)); ! 930: } ! 931: ! 932: negetstat(dev, flavor, status, count) ! 933: dev_t dev; ! 934: int flavor; ! 935: dev_status_t status; ! 936: unsigned int *count; ! 937: { ! 938: register int unit = minor(dev); ! 939: ! 940: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE) ! 941: return (ENXIO); ! 942: ! 943: return (net_getstat(&ne_softc[unit].ds_if, ! 944: flavor, ! 945: status, ! 946: count)); ! 947: } ! 948: ! 949: nesetstat(dev, flavor, status, count) ! 950: dev_t dev; ! 951: int flavor; ! 952: dev_status_t status; ! 953: unsigned int count; ! 954: { ! 955: register int unit = minor(dev); ! 956: register ne_softc_t *ns; ! 957: ! 958: if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE) ! 959: return (ENXIO); ! 960: ! 961: ns = &ne_softc[unit]; ! 962: ! 963: switch(flavor) { ! 964: case NET_STATUS: { ! 965: register struct net_status *s = (struct net_status *)status; ! 966: int mode = 0; ! 967: if (count < NET_STATUS_COUNT) ! 968: return(D_INVALID_SIZE); ! 969: #define MOD_ENAL 1 ! 970: #define MOD_PROM 2 ! 971: if (s->flags & IFF_ALLMULTI) ! 972: mode |= MOD_ENAL; ! 973: if (s->flags & IFF_PROMISC) ! 974: mode |= MOD_PROM; ! 975: ! 976: if (ns->mode != mode) { ! 977: ns->mode = mode; ! 978: if (ns->ns_flags & DSF_RUNNING) { ! 979: ns->ns_flags &= ~(DSF_LOCK | DSF_RUNNING); ! 980: neinit(unit); ! 981: } ! 982: } ! 983: break; ! 984: } ! 985: default : ! 986: return (D_INVALID_OPERATION); ! 987: } ! 988: return (D_SUCCESS); ! 989: } ! 990: ! 991: #else MACH_KERNEL ! 992: ! 993: /* ! 994: * Process an ioctl request. ! 995: */ ! 996: neioctl(ifp, cmd, data) ! 997: register struct ifnet *ifp; ! 998: int cmd; ! 999: caddr_t data; ! 1000: { ! 1001: register struct ifaddr *ifa = (struct ifaddr *)data; ! 1002: ne_softc_t *ns = &ne_softc[ifp->if_unit]; ! 1003: struct ifreq *ifr = (struct ifreq *)data; ! 1004: int s = splimp(), error = 0; ! 1005: ! 1006: ! 1007: switch (cmd) { ! 1008: ! 1009: case SIOCSIFADDR: ! 1010: ifp->if_flags |= IFF_UP; ! 1011: ! 1012: switch (ifa->ifa_addr->sa_family) { ! 1013: case AF_INET: ! 1014: neinit(ifp->if_unit); /* before arpwhohas */ ! 1015: ((struct arpcom *)ifp)->ac_ipaddr = ! 1016: IA_SIN(ifa)->sin_addr; ! 1017: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); ! 1018: break; ! 1019: case AF_NS: ! 1020: { ! 1021: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); ! 1022: ! 1023: if (ns_nullhost(*ina)) ! 1024: ina->x_host = *(union ns_host *)(ns->ds_addr); ! 1025: else { ! 1026: /* ! 1027: * The manual says we can't change the address ! 1028: * while the receiver is armed, ! 1029: * so reset everything ! 1030: */ ! 1031: ifp->if_flags &= ~IFF_RUNNING; ! 1032: bcopy((caddr_t)ina->x_host.c_host, ! 1033: (caddr_t)ns->ds_addr, sizeof(ns->ds_addr)); ! 1034: } ! 1035: neinit(ifp->if_unit); /* does ne_setaddr() */ ! 1036: break; ! 1037: } ! 1038: default: ! 1039: neinit(ifp->if_unit); ! 1040: break; ! 1041: } ! 1042: break; ! 1043: ! 1044: case SIOCSIFFLAGS: ! 1045: if ((ifp->if_flags & IFF_UP) == 0 && ! 1046: ifp->if_flags & IFF_RUNNING) { ! 1047: ifp->if_flags &= ~IFF_RUNNING; ! 1048: outb(ns->ns_port + ds_cmd, DSCM_STOP|DSCM_NODMA); ! 1049: } else if (ifp->if_flags & IFF_UP && ! 1050: (ifp->if_flags & IFF_RUNNING) == 0) ! 1051: neinit(ifp->if_unit); ! 1052: break; ! 1053: ! 1054: #ifdef notdef ! 1055: case SIOCGHWADDR: ! 1056: bcopy((caddr_t)ns->ds_addr, (caddr_t) &ifr->ifr_data, ! 1057: sizeof(ns->ds_addr)); ! 1058: break; ! 1059: #endif ! 1060: ! 1061: default: ! 1062: error = EINVAL; ! 1063: } ! 1064: splx(s); ! 1065: return (error); ! 1066: } ! 1067: ! 1068: /* ! 1069: * Reset of interface. ! 1070: */ ! 1071: nereset(unit, uban) ! 1072: int unit, uban; ! 1073: { ! 1074: if (unit >= NNE) ! 1075: return; ! 1076: printf("ne%d: reset\n", unit); ! 1077: ne_softc[unit].ns_flags &= ~DSF_LOCK; ! 1078: neinit(unit); ! 1079: } ! 1080: #endif MACH_KERNEL ! 1081: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.