|
|
1.1 ! root 1: /*- ! 2: * Copyright (c) 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Tim L. Tucker. ! 7: * ! 8: * Redistribution and use in source and binary forms, with or without ! 9: * modification, are permitted provided that the following conditions ! 10: * are met: ! 11: * 1. Redistributions of source code must retain the above copyright ! 12: * notice, this list of conditions and the following disclaimer. ! 13: * 2. Redistributions in binary form must reproduce the above copyright ! 14: * notice, this list of conditions and the following disclaimer in the ! 15: * documentation and/or other materials provided with the distribution. ! 16: * 3. All advertising materials mentioning features or use of this software ! 17: * must display the following acknowledgement: ! 18: * This product includes software developed by the University of ! 19: * California, Berkeley and its contributors. ! 20: * 4. Neither the name of the University nor the names of its contributors ! 21: * may be used to endorse or promote products derived from this software ! 22: * without specific prior written permission. ! 23: * ! 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 34: * SUCH DAMAGE. ! 35: * ! 36: * @(#)if_we.c 7.3 (Berkeley) 5/21/91 ! 37: */ ! 38: ! 39: /* ! 40: * Modification history ! 41: * ! 42: * 8/28/89 - Initial version(if_wd.c), Tim L Tucker ! 43: */ ! 44: ! 45: #include "we.h" ! 46: #if NWE > 0 ! 47: /* ! 48: * Western Digital 8003 ethernet/starlan adapter ! 49: * ! 50: * Supports the following interface cards: ! 51: * WD8003E, WD8003EBT, WD8003S, WD8003SBT, WD8013EBT ! 52: * ! 53: * The Western Digital card is one of many AT/MCA ethernet interfaces ! 54: * based on the National DS8390 Network Interface chip set. ! 55: */ ! 56: #include "param.h" ! 57: #include "mbuf.h" ! 58: #include "socket.h" ! 59: #include "ioctl.h" ! 60: #include "errno.h" ! 61: #include "syslog.h" ! 62: ! 63: #include "net/if.h" ! 64: #include "net/netisr.h" ! 65: ! 66: #ifdef INET ! 67: #include "netinet/in.h" ! 68: #include "netinet/in_systm.h" ! 69: #include "netinet/in_var.h" ! 70: #include "netinet/ip.h" ! 71: #include "netinet/if_ether.h" ! 72: #endif ! 73: ! 74: #ifdef NS ! 75: #include "netns/ns.h" ! 76: #include "netns/ns_if.h" ! 77: #endif ! 78: ! 79: #include "i386/isa/if_wereg.h" ! 80: #include "i386/isa/isa_device.h" ! 81: ! 82: /* ! 83: * This constant should really be 60 because the we adds 4 bytes of crc. ! 84: * However when set to 60 our packets are ignored by deuna's , 3coms are ! 85: * okay ?????????????????????????????????????????? ! 86: */ ! 87: #define ETHER_MIN_LEN 64 ! 88: #define ETHER_ADDR_LEN 6 ! 89: #define ETHER_HDR_SIZE 14 ! 90: ! 91: /* ! 92: * Ethernet software status per interface. ! 93: * ! 94: * Each interface is referenced by a network interface structure, ! 95: * qe_if, which the routing code uses to locate the interface. ! 96: * This structure contains the output queue for the interface, its address, ... ! 97: */ ! 98: struct we_softc { ! 99: struct arpcom we_ac; /* Ethernet common part */ ! 100: #define we_if we_ac.ac_if /* network-visible interface */ ! 101: #define we_addr we_ac.ac_enaddr /* hardware Ethernet address */ ! 102: ! 103: u_char we_flags; /* software state */ ! 104: #define WDF_RUNNING 0x01 ! 105: #define WDF_TXBUSY 0x02 ! 106: ! 107: u_char we_type; /* interface type code */ ! 108: u_short we_vector; /* interrupt vector */ ! 109: short we_io_ctl_addr; /* i/o bus address, control */ ! 110: short we_io_nic_addr; /* i/o bus address, DS8390 */ ! 111: ! 112: caddr_t we_vmem_addr; /* card RAM virtual memory base */ ! 113: u_long we_vmem_size; /* card RAM bytes */ ! 114: caddr_t we_vmem_ring; /* receive ring RAM vaddress */ ! 115: caddr_t we_vmem_end; /* receive ring RAM end */ ! 116: } we_softc[NWE]; ! 117: ! 118: int weprobe(), weattach(), weintr(), westart(); ! 119: int weinit(), ether_output(), weioctl(), wereset(), wewatchdog(); ! 120: ! 121: struct isa_driver wedriver = { ! 122: weprobe, weattach, "we", ! 123: }; ! 124: ! 125: /* ! 126: * Probe the WD8003 to see if it's there ! 127: */ ! 128: weprobe(is) ! 129: struct isa_device *is; ! 130: { ! 131: register int i; ! 132: register struct we_softc *sc = &we_softc[is->id_unit]; ! 133: union we_mem_sel wem; ! 134: u_char sum; ! 135: ! 136: /* ! 137: * Here we check the card ROM, if the checksum passes, and the ! 138: * type code and ethernet address check out, then we know we have ! 139: * a wd8003 card. ! 140: * ! 141: * Autoconfiguration: No warning message is printed on error. ! 142: */ ! 143: for (sum = 0, i = 0; i < 8; ++i) ! 144: sum += inb(is->id_iobase + WD_ROM_OFFSET + i); ! 145: if (sum != WD_CHECKSUM) ! 146: return (0); ! 147: sc->we_type = inb(is->id_iobase + WD_ROM_OFFSET + 6); ! 148: if ((sc->we_type != WD_ETHER) && (sc->we_type != WD_STARLAN) ! 149: && (sc->we_type != WD_ETHER2)) ! 150: return (0); ! 151: ! 152: /* ! 153: * Setup card RAM area and i/o addresses ! 154: * Kernel Virtual to segment C0000-DFFFF????? ! 155: */ ! 156: sc->we_io_ctl_addr = is->id_iobase; ! 157: sc->we_io_nic_addr = sc->we_io_ctl_addr + WD_NIC_OFFSET; ! 158: sc->we_vector = is->id_irq; ! 159: sc->we_vmem_addr = (caddr_t)is->id_maddr; ! 160: sc->we_vmem_size = is->id_msize; ! 161: sc->we_vmem_ring = sc->we_vmem_addr + (WD_PAGE_SIZE * WD_TXBUF_SIZE); ! 162: sc->we_vmem_end = sc->we_vmem_addr + is->id_msize; ! 163: ! 164: /* ! 165: * Save board ROM station address ! 166: */ ! 167: for (i = 0; i < ETHER_ADDR_LEN; ++i) ! 168: sc->we_addr[i] = inb(sc->we_io_ctl_addr + WD_ROM_OFFSET + i); ! 169: ! 170: /* ! 171: * Mapin interface memory, setup memory select register ! 172: */ ! 173: /* wem.ms_addr = (u_long)sc->we_vmem_addr >> 13; */ ! 174: wem.ms_addr = (u_long)(0xd0000)>> 13; ! 175: wem.ms_enable = 1; ! 176: wem.ms_reset = 0; ! 177: outb(sc->we_io_ctl_addr, wem.ms_byte); ! 178: ! 179: /* ! 180: * clear interface memory, then sum to make sure its valid ! 181: */ ! 182: for (i = 0; i < sc->we_vmem_size; ++i) ! 183: sc->we_vmem_addr[i] = 0x0; ! 184: for (sum = 0, i = 0; i < sc->we_vmem_size; ++i) ! 185: sum += sc->we_vmem_addr[i]; ! 186: if (sum != 0x0) { ! 187: printf("we%d: wd8003 dual port RAM address error\n", is->id_unit); ! 188: return (0); ! 189: } ! 190: ! 191: return (WD_IO_PORTS); ! 192: } ! 193: ! 194: /* ! 195: * Interface exists: make available by filling in network interface ! 196: * record. System will initialize the interface when it is ready ! 197: * to accept packets. ! 198: */ ! 199: weattach(is) ! 200: struct isa_device *is; ! 201: { ! 202: register struct we_softc *sc = &we_softc[is->id_unit]; ! 203: register struct ifnet *ifp = &sc->we_if; ! 204: union we_command wecmd; ! 205: ! 206: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); ! 207: wecmd.cs_stp = 1; ! 208: wecmd.cs_sta = 0; ! 209: wecmd.cs_ps = 0; ! 210: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 211: /* ! 212: * Initialize ifnet structure ! 213: */ ! 214: ifp->if_unit = is->id_unit; ! 215: ifp->if_name = "we" ; ! 216: ifp->if_mtu = ETHERMTU; ! 217: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS ; ! 218: ifp->if_init = weinit; ! 219: ifp->if_output = ether_output; ! 220: ifp->if_start = westart; ! 221: ifp->if_ioctl = weioctl; ! 222: ifp->if_reset = wereset; ! 223: ifp->if_watchdog = wewatchdog; ! 224: if_attach(ifp); ! 225: ! 226: /* ! 227: * Banner... ! 228: */ ! 229: printf(" %s address %s", ! 230: ((sc->we_type != WD_STARLAN) ? "ethernet" : "starlan"), ! 231: ether_sprintf(sc->we_addr)); ! 232: } ! 233: ! 234: /* ! 235: * Reset of interface. ! 236: */ ! 237: wereset(unit, uban) ! 238: int unit, uban; ! 239: { ! 240: if (unit >= NWE) ! 241: return; ! 242: printf("we%d: reset\n", unit); ! 243: /* we_softc[unit].we_flags &= ~WDF_RUNNING; */ ! 244: weinit(unit); ! 245: } ! 246: ! 247: /* ! 248: * Take interface offline. ! 249: */ ! 250: westop(unit) ! 251: int unit; ! 252: { ! 253: register struct we_softc *sc = &we_softc[unit]; ! 254: union we_command wecmd; ! 255: int s; ! 256: ! 257: /* ! 258: * Shutdown DS8390 ! 259: */ ! 260: s = splimp(); ! 261: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); ! 262: wecmd.cs_stp = 1; ! 263: wecmd.cs_sta = 0; ! 264: wecmd.cs_ps = 0; ! 265: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 266: (void) splx(s); ! 267: } ! 268: ! 269: wewatchdog(unit) { ! 270: ! 271: log(LOG_WARNING,"we%d: soft reset\n", unit); ! 272: westop(unit); ! 273: weinit(unit); ! 274: } ! 275: ! 276: static Bdry; ! 277: /* ! 278: * Initialization of interface (really just DS8390). ! 279: */ ! 280: weinit(unit) ! 281: int unit; ! 282: { ! 283: register struct we_softc *sc = &we_softc[unit]; ! 284: register struct ifnet *ifp = &sc->we_if; ! 285: union we_command wecmd; ! 286: int i, s; ! 287: ! 288: /* address not known */ ! 289: if (ifp->if_addrlist == (struct ifaddr *)0) ! 290: return; ! 291: ! 292: /* already running */ ! 293: /*if (ifp->if_flags & IFF_RUNNING) return; */ ! 294: ! 295: /* ! 296: * Initialize DS8390 in order given in NSC NIC manual. ! 297: * this is stock code...please see the National manual for details. ! 298: */ ! 299: s = splhigh(); ! 300: Bdry = 0; ! 301: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); ! 302: wecmd.cs_stp = 1; ! 303: wecmd.cs_sta = 0; ! 304: wecmd.cs_ps = 0; ! 305: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 306: outb(sc->we_io_nic_addr + WD_P0_DCR, WD_D_CONFIG); ! 307: outb(sc->we_io_nic_addr + WD_P0_RBCR0, 0); ! 308: outb(sc->we_io_nic_addr + WD_P0_RBCR1, 0); ! 309: outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_MON); ! 310: outb(sc->we_io_nic_addr + WD_P0_TCR, WD_T_CONFIG); ! 311: outb(sc->we_io_nic_addr + WD_P0_TPSR, 0); ! 312: outb(sc->we_io_nic_addr + WD_P0_PSTART, WD_TXBUF_SIZE); ! 313: outb(sc->we_io_nic_addr + WD_P0_PSTOP, ! 314: sc->we_vmem_size / WD_PAGE_SIZE); ! 315: outb(sc->we_io_nic_addr + WD_P0_BNRY, WD_TXBUF_SIZE); ! 316: outb(sc->we_io_nic_addr + WD_P0_ISR, 0xff); ! 317: outb(sc->we_io_nic_addr + WD_P0_IMR, WD_I_CONFIG); ! 318: wecmd.cs_ps = 1; ! 319: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 320: for (i = 0; i < ETHER_ADDR_LEN; ++i) ! 321: outb(sc->we_io_nic_addr + WD_P1_PAR0 + i, sc->we_addr[i]); ! 322: for (i = 0; i < ETHER_ADDR_LEN; ++i) /* == broadcast addr */ ! 323: outb(sc->we_io_nic_addr + WD_P1_MAR0 + i, 0xff); ! 324: outb(sc->we_io_nic_addr + WD_P1_CURR, WD_TXBUF_SIZE); ! 325: wecmd.cs_ps = 0; ! 326: wecmd.cs_stp = 0; ! 327: wecmd.cs_sta = 1; ! 328: wecmd.cs_rd = 0x4; ! 329: outb(sc->we_io_nic_addr + WD_P1_COMMAND, wecmd.cs_byte); ! 330: outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_CONFIG); ! 331: ! 332: /* ! 333: * Take the interface out of reset, program the vector, ! 334: * enable interrupts, and tell the world we are up. ! 335: */ ! 336: ifp->if_flags |= IFF_RUNNING; ! 337: sc->we_flags &= ~WDF_TXBUSY; ! 338: (void) splx(s); ! 339: westart(ifp); ! 340: } ! 341: ! 342: /* ! 343: * Start output on interface. ! 344: */ ! 345: westart(ifp) ! 346: struct ifnet *ifp; ! 347: { ! 348: register struct we_softc *sc = &we_softc[ifp->if_unit]; ! 349: struct mbuf *m0, *m; ! 350: register caddr_t buffer; ! 351: int len, s; ! 352: union we_command wecmd; ! 353: ! 354: /* ! 355: * The DS8390 has only one transmit buffer, if it is busy we ! 356: * must wait until the transmit interrupt completes. ! 357: */ ! 358: s = splhigh(); ! 359: if (sc->we_flags & WDF_TXBUSY) { ! 360: (void) splx(s); ! 361: return; ! 362: } ! 363: IF_DEQUEUE(&sc->we_if.if_snd, m); ! 364: if (m == 0) { ! 365: (void) splx(s); ! 366: return; ! 367: } ! 368: sc->we_flags |= WDF_TXBUSY; ! 369: (void) splx(s); ! 370: ! 371: /* ! 372: * Copy the mbuf chain into the transmit buffer ! 373: */ ! 374: buffer = sc->we_vmem_addr; ! 375: len = 0; ! 376: for (m0 = m; m != 0; m = m->m_next) { ! 377: bcopy(mtod(m, caddr_t), buffer, m->m_len); ! 378: buffer += m->m_len; ! 379: len += m->m_len; ! 380: } ! 381: ! 382: m_freem(m0); ! 383: ! 384: /* ! 385: * Init transmit length registers, and set transmit start flag. ! 386: */ ! 387: s = splhigh(); ! 388: len = MAX(len, ETHER_MIN_LEN); ! 389: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); ! 390: wecmd.cs_ps = 0; ! 391: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 392: outb(sc->we_io_nic_addr + WD_P0_TBCR0, len & 0xff); ! 393: outb(sc->we_io_nic_addr + WD_P0_TBCR1, len >> 8); ! 394: wecmd.cs_txp = 1; ! 395: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 396: (void) splx(s); ! 397: } ! 398: ! 399: /* ! 400: * Ethernet interface interrupt processor ! 401: */ ! 402: weintr(unit) ! 403: int unit; ! 404: { ! 405: register struct we_softc *sc = &we_softc[unit]; ! 406: union we_command wecmd; ! 407: union we_interrupt weisr; ! 408: ! 409: unit =0; ! 410: ! 411: /* disable onboard interrupts, then get interrupt status */ ! 412: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); ! 413: wecmd.cs_ps = 0; ! 414: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 415: weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR); ! 416: loop: ! 417: outb(sc->we_io_nic_addr + WD_P0_ISR, weisr.is_byte); ! 418: ! 419: /* transmit error */ ! 420: if (weisr.is_txe) { ! 421: /* need to read these registers to clear status */ ! 422: sc->we_if.if_collisions += ! 423: inb(sc->we_io_nic_addr + WD_P0_TBCR0); ! 424: ++sc->we_if.if_oerrors; ! 425: } ! 426: ! 427: /* receiver error */ ! 428: if (weisr.is_rxe) { ! 429: /* need to read these registers to clear status */ ! 430: (void) inb(sc->we_io_nic_addr + 0xD); ! 431: (void) inb(sc->we_io_nic_addr + 0xE); ! 432: (void) inb(sc->we_io_nic_addr + 0xF); ! 433: ++sc->we_if.if_ierrors; ! 434: } ! 435: ! 436: /* normal transmit complete */ ! 437: if (weisr.is_ptx || weisr.is_txe) ! 438: wetint (unit); ! 439: ! 440: /* normal receive notification */ ! 441: if (weisr.is_prx || weisr.is_rxe) ! 442: werint (unit); ! 443: ! 444: /* try to start transmit */ ! 445: westart(&sc->we_if); ! 446: ! 447: /* re-enable onboard interrupts */ ! 448: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); ! 449: wecmd.cs_ps = 0; ! 450: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 451: outb(sc->we_io_nic_addr + WD_P0_IMR, 0xff/*WD_I_CONFIG*/); ! 452: weisr.is_byte = inb(sc->we_io_nic_addr + WD_P0_ISR); ! 453: if (weisr.is_byte) goto loop; ! 454: } ! 455: ! 456: /* ! 457: * Ethernet interface transmit interrupt. ! 458: */ ! 459: wetint(unit) ! 460: int unit; ! 461: { ! 462: register struct we_softc *sc = &we_softc[unit]; ! 463: ! 464: /* ! 465: * Do some statistics (assume page zero of NIC mapped in) ! 466: */ ! 467: sc->we_flags &= ~WDF_TXBUSY; ! 468: sc->we_if.if_timer = 0; ! 469: ++sc->we_if.if_opackets; ! 470: sc->we_if.if_collisions += inb(sc->we_io_nic_addr + WD_P0_TBCR0); ! 471: } ! 472: ! 473: /* ! 474: * Ethernet interface receiver interrupt. ! 475: */ ! 476: werint(unit) ! 477: int unit; ! 478: { ! 479: register struct we_softc *sc = &we_softc[unit]; ! 480: u_char bnry, curr; ! 481: long len; ! 482: union we_command wecmd; ! 483: struct we_ring *wer; ! 484: ! 485: /* ! 486: * Traverse the receive ring looking for packets to pass back. ! 487: * The search is complete when we find a descriptor not in use. ! 488: */ ! 489: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); ! 490: wecmd.cs_ps = 0; ! 491: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 492: bnry = inb(sc->we_io_nic_addr + WD_P0_BNRY); ! 493: wecmd.cs_ps = 1; ! 494: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 495: curr = inb(sc->we_io_nic_addr + WD_P1_CURR); ! 496: if(Bdry) ! 497: bnry =Bdry; ! 498: ! 499: while (bnry != curr) ! 500: { ! 501: /* get pointer to this buffer header structure */ ! 502: wer = (struct we_ring *)(sc->we_vmem_addr + (bnry << 8)); ! 503: ! 504: /* count includes CRC */ ! 505: len = wer->we_count - 4; ! 506: if (len > 30 && len <= ETHERMTU+100 ! 507: /*&& (*(char *)wer == 1 || *(char *) wer == 0x21)*/) ! 508: weread(sc, (caddr_t)(wer + 1), len); ! 509: else printf("reject %d", len); ! 510: ! 511: outofbufs: ! 512: wecmd.cs_byte = inb(sc->we_io_nic_addr + WD_P0_COMMAND); ! 513: wecmd.cs_ps = 0; ! 514: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 515: ! 516: /* advance on chip Boundry register */ ! 517: if((caddr_t) wer + WD_PAGE_SIZE - 1 > sc->we_vmem_end) { ! 518: bnry = WD_TXBUF_SIZE; ! 519: outb(sc->we_io_nic_addr + WD_P0_BNRY, ! 520: sc->we_vmem_size / WD_PAGE_SIZE-1); ! 521: ! 522: } else { ! 523: if (len > 30 && len <= ETHERMTU+100) ! 524: bnry = wer->we_next_packet; ! 525: else bnry = curr; ! 526: ! 527: /* watch out for NIC overflow, reset Boundry if invalid */ ! 528: if ((bnry - 1) < WD_TXBUF_SIZE) { ! 529: outb(sc->we_io_nic_addr + WD_P0_BNRY, ! 530: (sc->we_vmem_size / WD_PAGE_SIZE) - 1); ! 531: bnry = WD_TXBUF_SIZE; ! 532: } else ! 533: outb(sc->we_io_nic_addr + WD_P0_BNRY, bnry-1); ! 534: } ! 535: ! 536: /* refresh our copy of CURR */ ! 537: wecmd.cs_ps = 1; ! 538: outb(sc->we_io_nic_addr + WD_P0_COMMAND, wecmd.cs_byte); ! 539: curr = inb(sc->we_io_nic_addr + WD_P1_CURR); ! 540: } ! 541: Bdry = bnry; ! 542: } ! 543: ! 544: #ifdef shit ! 545: /* ! 546: * Process an ioctl request. ! 547: */ ! 548: weioctl(ifp, cmd, data) ! 549: register struct ifnet *ifp; ! 550: int cmd; ! 551: caddr_t data; ! 552: { ! 553: struct we_softc *sc = &we_softc[ifp->if_unit]; ! 554: struct ifaddr *ifa = (struct ifaddr *)data; ! 555: int s = splimp(), error = 0; ! 556: ! 557: switch (cmd) { ! 558: ! 559: case SIOCSIFADDR: ! 560: ifp->if_flags |= IFF_UP; ! 561: weinit(ifp->if_unit); ! 562: switch(ifa->ifa_addr->sa_family) { ! 563: #ifdef INET ! 564: case AF_INET: ! 565: ((struct arpcom *)ifp)->ac_ipaddr = ! 566: IA_SIN(ifa)->sin_addr; ! 567: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); ! 568: break; ! 569: #endif ! 570: #ifdef NS ! 571: case AF_NS: ! 572: { ! 573: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); ! 574: ! 575: if (ns_nullhost(*ina)) ! 576: ina->x_host = *(union ns_host *)(sc->we_addr); ! 577: else ! 578: wesetaddr(ina->x_host.c_host, ifp->if_unit); ! 579: break; ! 580: } ! 581: #endif ! 582: } ! 583: break; ! 584: ! 585: case SIOCSIFFLAGS: ! 586: if (((ifp->if_flags & IFF_UP) == 0) && ! 587: (sc->we_flags & WDF_RUNNING)) { ! 588: westop(ifp->if_unit); ! 589: } else if (((ifp->if_flags & IFF_UP) == IFF_UP) && ! 590: ((sc->we_flags & WDF_RUNNING) == 0)) ! 591: weinit(ifp->if_unit); ! 592: break; ! 593: ! 594: default: ! 595: error = EINVAL; ! 596: ! 597: } ! 598: (void) splx(s); ! 599: return (error); ! 600: } ! 601: #endif ! 602: ! 603: /* ! 604: * Process an ioctl request. ! 605: */ ! 606: weioctl(ifp, cmd, data) ! 607: register struct ifnet *ifp; ! 608: int cmd; ! 609: caddr_t data; ! 610: { ! 611: register struct ifaddr *ifa = (struct ifaddr *)data; ! 612: struct we_softc *sc = &we_softc[ifp->if_unit]; ! 613: struct ifreq *ifr = (struct ifreq *)data; ! 614: int s = splimp(), error = 0; ! 615: ! 616: ! 617: switch (cmd) { ! 618: ! 619: case SIOCSIFADDR: ! 620: ifp->if_flags |= IFF_UP; ! 621: ! 622: switch (ifa->ifa_addr->sa_family) { ! 623: #ifdef INET ! 624: case AF_INET: ! 625: weinit(ifp->if_unit); /* before arpwhohas */ ! 626: ((struct arpcom *)ifp)->ac_ipaddr = ! 627: IA_SIN(ifa)->sin_addr; ! 628: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); ! 629: break; ! 630: #endif ! 631: #ifdef NS ! 632: case AF_NS: ! 633: { ! 634: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); ! 635: ! 636: if (ns_nullhost(*ina)) ! 637: ina->x_host = *(union ns_host *)(sc->ns_addr); ! 638: else { ! 639: /* ! 640: * The manual says we can't change the address ! 641: * while the receiver is armed, ! 642: * so reset everything ! 643: */ ! 644: ifp->if_flags &= ~IFF_RUNNING; ! 645: bcopy((caddr_t)ina->x_host.c_host, ! 646: (caddr_t)sc->ns_addr, sizeof(sc->ns_addr)); ! 647: } ! 648: weinit(ifp->if_unit); /* does ne_setaddr() */ ! 649: break; ! 650: } ! 651: #endif ! 652: default: ! 653: weinit(ifp->if_unit); ! 654: break; ! 655: } ! 656: break; ! 657: ! 658: case SIOCSIFFLAGS: ! 659: if ((ifp->if_flags & IFF_UP) == 0 && ! 660: ifp->if_flags & IFF_RUNNING) { ! 661: ifp->if_flags &= ~IFF_RUNNING; ! 662: westop(ifp->if_unit); ! 663: } else if (ifp->if_flags & IFF_UP && ! 664: (ifp->if_flags & IFF_RUNNING) == 0) ! 665: weinit(ifp->if_unit); ! 666: break; ! 667: ! 668: #ifdef notdef ! 669: case SIOCGHWADDR: ! 670: bcopy((caddr_t)sc->sc_addr, (caddr_t) &ifr->ifr_data, ! 671: sizeof(sc->sc_addr)); ! 672: break; ! 673: #endif ! 674: ! 675: default: ! 676: error = EINVAL; ! 677: } ! 678: splx(s); ! 679: return (error); ! 680: } ! 681: /* ! 682: * set ethernet address for unit ! 683: */ ! 684: wesetaddr(physaddr, unit) ! 685: u_char *physaddr; ! 686: int unit; ! 687: { ! 688: register struct we_softc *sc = &we_softc[unit]; ! 689: register int i; ! 690: ! 691: /* ! 692: * Rewrite ethernet address, and then force restart of NIC ! 693: */ ! 694: for (i = 0; i < ETHER_ADDR_LEN; i++) ! 695: sc->we_addr[i] = physaddr[i]; ! 696: sc->we_flags &= ~WDF_RUNNING; ! 697: weinit(unit); ! 698: } ! 699: ! 700: #define wedataaddr(sc, eh, off, type) \ ! 701: ((type) ((caddr_t)((eh)+1)+(off) >= (sc)->we_vmem_end) ? \ ! 702: (((caddr_t)((eh)+1)+(off))) - (sc)->we_vmem_end \ ! 703: + (sc)->we_vmem_ring: \ ! 704: ((caddr_t)((eh)+1)+(off))) ! 705: /* ! 706: * Pass a packet to the higher levels. ! 707: * We deal with the trailer protocol here. ! 708: */ ! 709: weread(sc, buf, len) ! 710: register struct we_softc *sc; ! 711: char *buf; ! 712: int len; ! 713: { ! 714: register struct ether_header *eh; ! 715: struct mbuf *m, *weget(); ! 716: int off, resid; ! 717: ! 718: /* ! 719: * Deal with trailer protocol: if type is trailer type ! 720: * get true type from first 16-bit word past data. ! 721: * Remember that type was trailer by setting off. ! 722: */ ! 723: eh = (struct ether_header *)buf; ! 724: eh->ether_type = ntohs((u_short)eh->ether_type); ! 725: if (eh->ether_type >= ETHERTYPE_TRAIL && ! 726: eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { ! 727: off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; ! 728: if (off >= ETHERMTU) return; /* sanity */ ! 729: eh->ether_type = ntohs(*wedataaddr(sc, eh, off, u_short *)); ! 730: resid = ntohs(*(wedataaddr(sc, eh, off+2, u_short *))); ! 731: if (off + resid > len) return; /* sanity */ ! 732: len = off + resid; ! 733: } else off = 0; ! 734: ! 735: len -= sizeof(struct ether_header); ! 736: if (len <= 0) return; ! 737: ! 738: /* ! 739: * Pull packet off interface. Off is nonzero if packet ! 740: * has trailing header; neget will then force this header ! 741: * information to be at the front, but we still have to drop ! 742: * the type and length which are at the front of any trailer data. ! 743: */ ! 744: m = weget(buf, len, off, &sc->we_if, sc); ! 745: if (m == 0) return; ! 746: ether_input(&sc->we_if, eh, m); ! 747: } ! 748: ! 749: /* ! 750: * Supporting routines ! 751: */ ! 752: ! 753: /* ! 754: * Pull read data off a interface. ! 755: * Len is length of data, with local net header stripped. ! 756: * Off is non-zero if a trailer protocol was used, and ! 757: * gives the offset of the trailer information. ! 758: * We copy the trailer information and then all the normal ! 759: * data into mbufs. When full cluster sized units are present ! 760: * we copy into clusters. ! 761: */ ! 762: struct mbuf * ! 763: weget(buf, totlen, off0, ifp, sc) ! 764: caddr_t buf; ! 765: int totlen, off0; ! 766: struct ifnet *ifp; ! 767: struct we_softc *sc; ! 768: { ! 769: struct mbuf *top, **mp, *m, *p; ! 770: int off = off0, len; ! 771: register caddr_t cp = buf; ! 772: char *epkt; ! 773: int tc =totlen; ! 774: ! 775: buf += sizeof(struct ether_header); ! 776: cp = buf; ! 777: epkt = cp + totlen; ! 778: ! 779: if (off) { ! 780: cp += off + 2 * sizeof(u_short); ! 781: totlen -= 2 * sizeof(u_short); ! 782: } ! 783: ! 784: MGETHDR(m, M_DONTWAIT, MT_DATA); ! 785: if (m == 0) ! 786: return (0); ! 787: m->m_pkthdr.rcvif = ifp; ! 788: m->m_pkthdr.len = totlen; ! 789: m->m_len = MHLEN; ! 790: ! 791: top = 0; ! 792: mp = ⊤ ! 793: while (totlen > 0) { ! 794: if (top) { ! 795: MGET(m, M_DONTWAIT, MT_DATA); ! 796: if (m == 0) { ! 797: m_freem(top); ! 798: return (0); ! 799: } ! 800: m->m_len = MLEN; ! 801: } ! 802: len = min(totlen, epkt - cp); ! 803: if (len >= MINCLSIZE) { ! 804: MCLGET(m, M_DONTWAIT); ! 805: if (m->m_flags & M_EXT) ! 806: m->m_len = len = min(len, MCLBYTES); ! 807: else ! 808: len = m->m_len; ! 809: } else { ! 810: /* ! 811: * Place initial small packet/header at end of mbuf. ! 812: */ ! 813: if (len < m->m_len) { ! 814: if (top == 0 && len + max_linkhdr <= m->m_len) ! 815: m->m_data += max_linkhdr; ! 816: m->m_len = len; ! 817: } else ! 818: len = m->m_len; ! 819: } ! 820: ! 821: totlen -= len; ! 822: /* only do up to end of buffer */ ! 823: if (cp+len > sc->we_vmem_end) { ! 824: unsigned toend = sc->we_vmem_end - cp; ! 825: ! 826: bcopy(cp, mtod(m, caddr_t), toend); ! 827: cp = sc->we_vmem_ring; ! 828: bcopy(cp, mtod(m, caddr_t)+toend, len - toend); ! 829: cp += len - toend; ! 830: epkt = cp + totlen; ! 831: } else { ! 832: bcopy(cp, mtod(m, caddr_t), (unsigned)len); ! 833: cp += len; ! 834: } ! 835: *mp = m; ! 836: mp = &m->m_next; ! 837: if (cp == epkt) { ! 838: cp = buf; ! 839: epkt = cp + tc; ! 840: } ! 841: } ! 842: return (top); ! 843: } ! 844: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.