|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)if_ec.c 7.8 (Berkeley) 12/16/90 ! 34: */ ! 35: ! 36: #include "ec.h" ! 37: #if NEC > 0 ! 38: ! 39: /* ! 40: * 3Com Ethernet Controller interface ! 41: */ ! 42: #include "../include/pte.h" ! 43: ! 44: #include "sys/param.h" ! 45: #include "sys/systm.h" ! 46: #include "sys/mbuf.h" ! 47: #include "sys/buf.h" ! 48: #include "sys/protosw.h" ! 49: #include "sys/socket.h" ! 50: #include "sys/syslog.h" ! 51: #include "sys/vmmac.h" ! 52: #include "sys/ioctl.h" ! 53: #include "sys/errno.h" ! 54: ! 55: #include "net/if.h" ! 56: #include "net/netisr.h" ! 57: #include "net/route.h" ! 58: ! 59: #ifdef INET ! 60: #include "netinet/in.h" ! 61: #include "netinet/in_systm.h" ! 62: #include "netinet/in_var.h" ! 63: #include "netinet/ip.h" ! 64: #include "netinet/if_ether.h" ! 65: #endif ! 66: ! 67: #ifdef NS ! 68: #include "netns/ns.h" ! 69: #include "netns/ns_if.h" ! 70: #endif ! 71: ! 72: #include "../include/cpu.h" ! 73: #include "../include/mtpr.h" ! 74: #include "if_ecreg.h" ! 75: #include "if_uba.h" ! 76: #include "../uba/ubareg.h" ! 77: #include "../uba/ubavar.h" ! 78: ! 79: #if CLSIZE == 2 ! 80: #define ECBUFSIZE 32 /* on-board memory, clusters */ ! 81: #endif ! 82: ! 83: int ecubamem(), ecprobe(), ecattach(), ecrint(), ecxint(), eccollide(); ! 84: struct uba_device *ecinfo[NEC]; ! 85: u_short ecstd[] = { 0 }; ! 86: struct uba_driver ecdriver = ! 87: { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo, 0, 0, 0, 0, ecubamem }; ! 88: ! 89: int ecinit(),ecioctl(),ecstart(),ecreset(),ether_output(); ! 90: struct mbuf *ecget(); ! 91: ! 92: extern struct ifnet loif; ! 93: ! 94: /* ! 95: * Ethernet software status per interface. ! 96: * ! 97: * Each interface is referenced by a network interface structure, ! 98: * es_if, which the routing code uses to locate the interface. ! 99: * This structure contains the output queue for the interface, its address, ... ! 100: * We also have, for each interface, a UBA interface structure, which ! 101: * contains information about the UNIBUS resources held by the interface: ! 102: * map registers, buffered data paths, etc. Information is cached in this ! 103: * structure for use by the if_uba.c routines in running the interface ! 104: * efficiently. ! 105: */ ! 106: struct ec_softc { ! 107: struct arpcom es_ac; /* common Ethernet structures */ ! 108: #define es_if es_ac.ac_if /* network-visible interface */ ! 109: #define es_addr es_ac.ac_enaddr /* hardware Ethernet address */ ! 110: struct ifuba es_ifuba; /* UNIBUS resources */ ! 111: short es_mask; /* mask for current output delay */ ! 112: u_char *es_buf[16]; /* virtual addresses of buffers */ ! 113: } ec_softc[NEC]; ! 114: ! 115: /* ! 116: * Configure on-board memory for an interface. ! 117: * Called from autoconfig and after a uba reset. ! 118: * The address of the memory on the uba is supplied in the device flags. ! 119: */ ! 120: ecubamem(ui, uban) ! 121: register struct uba_device *ui; ! 122: { ! 123: register caddr_t ecbuf = (caddr_t) &umem[uban][ui->ui_flags]; ! 124: register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; ! 125: ! 126: /* ! 127: * Make sure csr is there (we run before ecprobe). ! 128: */ ! 129: if (badaddr((caddr_t)addr, 2)) ! 130: return (-1); ! 131: #if VAX780 ! 132: if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) { ! 133: uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr; ! 134: return (-1); ! 135: } ! 136: #endif ! 137: /* ! 138: * Make sure memory is turned on ! 139: */ ! 140: addr->ec_rcr = EC_AROM; ! 141: /* ! 142: * Tell the system that the board has memory here, so it won't ! 143: * attempt to allocate the addresses later. ! 144: */ ! 145: if (ubamem(uban, ui->ui_flags, ECBUFSIZE*CLSIZE, 1) == 0) { ! 146: printf("ec%d: cannot reserve uba addresses\n", ui->ui_unit); ! 147: addr->ec_rcr = EC_MDISAB; /* disable memory */ ! 148: return (-1); ! 149: } ! 150: /* ! 151: * Check for existence of buffers on Unibus. ! 152: */ ! 153: if (badaddr((caddr_t)ecbuf, 2)) { ! 154: bad: ! 155: printf("ec%d: buffer mem not found\n", ui->ui_unit); ! 156: (void) ubamem(uban, ui->ui_flags, ECBUFSIZE*2, 0); ! 157: addr->ec_rcr = EC_MDISAB; /* disable memory */ ! 158: return (-1); ! 159: } ! 160: #if VAX780 ! 161: if (cpu == VAX_780 && uba_hd[uban].uh_uba->uba_sr) { ! 162: uba_hd[uban].uh_uba->uba_sr = uba_hd[uban].uh_uba->uba_sr; ! 163: goto bad; ! 164: } ! 165: #endif ! 166: if (ui->ui_alive == 0) /* Only printf from autoconfig */ ! 167: printf("ec%d: mem %x-%x\n", ui->ui_unit, ! 168: ui->ui_flags, ui->ui_flags + ECBUFSIZE*CLBYTES - 1); ! 169: ui->ui_type = 1; /* Memory on, allocated */ ! 170: return (0); ! 171: } ! 172: ! 173: /* ! 174: * Do output DMA to determine interface presence and ! 175: * interrupt vector. DMA is too short to disturb other hosts. ! 176: */ ! 177: ecprobe(reg, ui) ! 178: caddr_t reg; ! 179: struct uba_device *ui; ! 180: { ! 181: register int br, cvec; /* r11, r10 value-result */ ! 182: register struct ecdevice *addr = (struct ecdevice *)reg; ! 183: register caddr_t ecbuf = (caddr_t) &umem[ui->ui_ubanum][ui->ui_flags]; ! 184: ! 185: #ifdef lint ! 186: br = 0; cvec = br; br = cvec; ! 187: ecrint(0); ecxint(0); eccollide(0); ! 188: #endif ! 189: ! 190: /* ! 191: * Check that buffer memory was found and enabled. ! 192: */ ! 193: if (ui->ui_type == 0) ! 194: return(0); ! 195: /* ! 196: * Make a one byte packet in what should be buffer #0. ! 197: * Submit it for sending. This should cause an xmit interrupt. ! 198: * The xmit interrupt vector is 8 bytes after the receive vector, ! 199: * so adjust for this before returning. ! 200: */ ! 201: *(u_short *)ecbuf = (u_short) 03777; ! 202: ecbuf[03777] = '\0'; ! 203: addr->ec_xcr = EC_XINTEN|EC_XWBN; ! 204: DELAY(100000); ! 205: addr->ec_xcr = EC_XCLR; ! 206: if (cvec > 0 && cvec != 0x200) { ! 207: if (cvec & 04) { /* collision interrupt */ ! 208: cvec -= 04; ! 209: br += 1; /* rcv is collision + 1 */ ! 210: } else { /* xmit interrupt */ ! 211: cvec -= 010; ! 212: br += 2; /* rcv is xmit + 2 */ ! 213: } ! 214: } ! 215: return (1); ! 216: } ! 217: ! 218: /* ! 219: * Interface exists: make available by filling in network interface ! 220: * record. System will initialize the interface when it is ready ! 221: * to accept packets. ! 222: */ ! 223: ecattach(ui) ! 224: struct uba_device *ui; ! 225: { ! 226: struct ec_softc *es = &ec_softc[ui->ui_unit]; ! 227: register struct ifnet *ifp = &es->es_if; ! 228: register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; ! 229: int i, j; ! 230: u_char *cp; ! 231: ! 232: ifp->if_unit = ui->ui_unit; ! 233: ifp->if_name = "ec"; ! 234: ifp->if_mtu = ETHERMTU; ! 235: ! 236: /* ! 237: * Read the ethernet address off the board, one nibble at a time. ! 238: */ ! 239: addr->ec_xcr = EC_UECLR; /* zero address pointer */ ! 240: addr->ec_rcr = EC_AROM; ! 241: cp = es->es_addr; ! 242: #define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM ! 243: for (i=0; i < sizeof (es->es_addr); i++) { ! 244: *cp = 0; ! 245: for (j=0; j<=4; j+=4) { ! 246: *cp |= ((addr->ec_rcr >> 8) & 0xf) << j; ! 247: NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT; ! 248: } ! 249: cp++; ! 250: } ! 251: printf("ec%d: hardware address %s\n", ui->ui_unit, ! 252: ether_sprintf(es->es_addr)); ! 253: ifp->if_init = ecinit; ! 254: ifp->if_ioctl = ecioctl; ! 255: ifp->if_output = ether_output; ! 256: ifp->if_start = ecstart; ! 257: ifp->if_reset = ecreset; ! 258: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; ! 259: for (i=0; i<16; i++) ! 260: es->es_buf[i] ! 261: = (u_char *)&umem[ui->ui_ubanum][ui->ui_flags + 2048*i]; ! 262: if_attach(ifp); ! 263: } ! 264: ! 265: /* ! 266: * Reset of interface after UNIBUS reset. ! 267: * If interface is on specified uba, reset its state. ! 268: */ ! 269: ecreset(unit, uban) ! 270: int unit, uban; ! 271: { ! 272: register struct uba_device *ui; ! 273: ! 274: if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 || ! 275: ui->ui_ubanum != uban) ! 276: return; ! 277: printf(" ec%d", unit); ! 278: ec_softc[unit].es_if.if_flags &= ~IFF_RUNNING; ! 279: ecinit(unit); ! 280: } ! 281: ! 282: /* ! 283: * Initialization of interface; clear recorded pending ! 284: * operations, and reinitialize UNIBUS usage. ! 285: */ ! 286: ecinit(unit) ! 287: int unit; ! 288: { ! 289: struct ec_softc *es = &ec_softc[unit]; ! 290: struct ecdevice *addr; ! 291: register struct ifnet *ifp = &es->es_if; ! 292: int i, s; ! 293: ! 294: /* not yet, if address still unknown */ ! 295: if (ifp->if_addrlist == (struct ifaddr *)0) ! 296: return; ! 297: ! 298: /* ! 299: * Hang receive buffers and start any pending writes. ! 300: * Writing into the rcr also makes sure the memory ! 301: * is turned on. ! 302: */ ! 303: if ((ifp->if_flags & IFF_RUNNING) == 0) { ! 304: u_short start_read; ! 305: addr = (struct ecdevice *)ecinfo[unit]->ui_addr; ! 306: s = splimp(); ! 307: /* ! 308: * write our ethernet address into the address recognition ROM ! 309: * so we can always use the same EC_READ bits (referencing ROM), ! 310: * in case we change the address sometime. ! 311: * Note that this is safe here as the receiver is NOT armed. ! 312: */ ! 313: ec_setaddr(es->es_addr, unit); ! 314: /* ! 315: * Arm the receiver ! 316: #ifdef MULTI ! 317: if (es->es_if.if_flags & IFF_PROMISC) ! 318: start_read = EC_PROMISC; ! 319: else if (es->es_if.if_flags & IFF_MULTI) ! 320: start_read = EC_MULTI; ! 321: else ! 322: #endif MULTI ! 323: start_read = EC_READ; ! 324: */ ! 325: for (i = ECRHBF; i >= ECRLBF; i--) ! 326: addr->ec_rcr = EC_READ | i; ! 327: es->es_if.if_flags &= ~IFF_OACTIVE; ! 328: es->es_mask = ~0; ! 329: es->es_if.if_flags |= IFF_RUNNING; ! 330: if (es->es_if.if_snd.ifq_head) ! 331: (void) ecstart(&es->es_if); ! 332: splx(s); ! 333: } ! 334: } ! 335: ! 336: /* ! 337: * Start output on interface. Get another datagram to send ! 338: * off of the interface queue, and copy it to the interface ! 339: * before starting the output. ! 340: */ ! 341: ecstart(ifp) ! 342: struct ifnet *ifp; ! 343: { ! 344: int unit = ifp->if_unit; ! 345: register struct ec_softc *es = &ec_softc[unit]; ! 346: struct ecdevice *addr; ! 347: struct mbuf *m; ! 348: ! 349: if ((es->es_if.if_flags & IFF_RUNNING) == 0) ! 350: return (0); ! 351: IF_DEQUEUE(&es->es_if.if_snd, m); ! 352: if (m == 0) ! 353: return (0); ! 354: ecput(es->es_buf[ECTBF], m); ! 355: addr = (struct ecdevice *)ecinfo[unit]->ui_addr; ! 356: addr->ec_xcr = EC_WRITE|ECTBF; ! 357: es->es_if.if_flags |= IFF_OACTIVE; ! 358: return (0); ! 359: } ! 360: ! 361: /* ! 362: * Ethernet interface transmitter interrupt. ! 363: * Start another output if more data to send. ! 364: */ ! 365: ecxint(unit) ! 366: int unit; ! 367: { ! 368: register struct ec_softc *es = &ec_softc[unit]; ! 369: register struct ecdevice *addr = ! 370: (struct ecdevice *)ecinfo[unit]->ui_addr; ! 371: ! 372: if ((es->es_if.if_flags & IFF_OACTIVE) == 0) ! 373: return; ! 374: if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) { ! 375: printf("ec%d: stray xmit interrupt, xcr=%b\n", unit, ! 376: addr->ec_xcr, EC_XBITS); ! 377: es->es_if.if_flags &= ~IFF_OACTIVE; ! 378: addr->ec_xcr = EC_XCLR; ! 379: return; ! 380: } ! 381: es->es_if.if_opackets++; ! 382: es->es_if.if_flags &= ~IFF_OACTIVE; ! 383: es->es_mask = ~0; ! 384: addr->ec_xcr = EC_XCLR; ! 385: if (es->es_if.if_snd.ifq_head) ! 386: (void) ecstart(&es->es_if); ! 387: } ! 388: ! 389: /* ! 390: * Collision on ethernet interface. Do exponential ! 391: * backoff, and retransmit. If have backed off all ! 392: * the way print warning diagnostic, and drop packet. ! 393: */ ! 394: eccollide(unit) ! 395: int unit; ! 396: { ! 397: register struct ec_softc *es = &ec_softc[unit]; ! 398: register struct ecdevice *addr = ! 399: (struct ecdevice *)ecinfo[unit]->ui_addr; ! 400: register i; ! 401: int delay; ! 402: ! 403: es->es_if.if_collisions++; ! 404: if ((es->es_if.if_flags & IFF_OACTIVE) == 0) ! 405: return; ! 406: ! 407: /* ! 408: * Es_mask is a 16 bit number with n low zero bits, with ! 409: * n the number of backoffs. When es_mask is 0 we have ! 410: * backed off 16 times, and give up. ! 411: */ ! 412: if (es->es_mask == 0) { ! 413: u_short start_read; ! 414: es->es_if.if_oerrors++; ! 415: log(LOG_ERR, "ec%d: send error\n", unit); ! 416: /* ! 417: * Reset interface, then requeue rcv buffers. ! 418: * Some incoming packets may be lost, but that ! 419: * can't be helped. ! 420: */ ! 421: addr->ec_xcr = EC_UECLR; ! 422: #ifdef MULTI ! 423: if (es->es_if.if_flags & IFF_PROMISC) ! 424: start_read = EC_PROMISC; ! 425: else if (es->es_if.if_flags & IFF_MULTI) ! 426: start_read = EC_MULTI; ! 427: else ! 428: #endif MULTI ! 429: start_read = EC_READ; ! 430: for (i=ECRHBF; i>=ECRLBF; i--) ! 431: addr->ec_rcr = start_read|i; ! 432: /* ! 433: * Reset and transmit next packet (if any). ! 434: */ ! 435: es->es_if.if_flags &= ~IFF_OACTIVE; ! 436: es->es_mask = ~0; ! 437: if (es->es_if.if_snd.ifq_head) ! 438: (void) ecstart(&es->es_if); ! 439: return; ! 440: } ! 441: /* ! 442: * Do exponential backoff. Compute delay based on low bits ! 443: * of the interval timer (1 bit for each transmission attempt, ! 444: * but at most 5 bits). Then delay for that number of ! 445: * slot times. A slot time is 51.2 microseconds (rounded to 51). ! 446: * This does not take into account the time already used to ! 447: * process the interrupt. ! 448: */ ! 449: es->es_mask <<= 1; ! 450: delay = mfpr(ICR) & 0x1f &~ es->es_mask; ! 451: DELAY(delay * 51); ! 452: /* ! 453: * Clear the controller's collision flag, thus enabling retransmit. ! 454: */ ! 455: addr->ec_xcr = EC_CLEAR; ! 456: } ! 457: ! 458: /* ! 459: * Ethernet interface receiver interrupt. ! 460: * If input error just drop packet. ! 461: * Otherwise examine ! 462: * packet to determine type. If can't determine length ! 463: * from type, then have to drop packet. Othewise decapsulate ! 464: * packet based on type and pass to type specific higher-level ! 465: * input routine. ! 466: */ ! 467: ecrint(unit) ! 468: int unit; ! 469: { ! 470: struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; ! 471: ! 472: while (addr->ec_rcr & EC_RDONE) ! 473: ecread(unit); ! 474: } ! 475: ! 476: ecread(unit) ! 477: int unit; ! 478: { ! 479: register struct ec_softc *es = &ec_softc[unit]; ! 480: struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; ! 481: register struct ether_header *ec; ! 482: struct mbuf *m; ! 483: int len, off, resid, ecoff, rbuf; ! 484: register struct ifqueue *inq; ! 485: u_short start_read; ! 486: u_char *ecbuf; ! 487: ! 488: es->es_if.if_ipackets++; ! 489: rbuf = addr->ec_rcr & EC_RBN; ! 490: if (rbuf < ECRLBF || rbuf > ECRHBF) ! 491: panic("ecrint"); ! 492: ecbuf = es->es_buf[rbuf]; ! 493: ecoff = *(short *)ecbuf; ! 494: if (ecoff <= ECRDOFF || ecoff > 2046) { ! 495: es->es_if.if_ierrors++; ! 496: #ifdef notdef ! 497: if (es->es_if.if_ierrors % 100 == 0) ! 498: printf("ec%d: += 100 input errors\n", unit); ! 499: #endif ! 500: goto setup; ! 501: } ! 502: ! 503: /* ! 504: * Get input data length. ! 505: * Get pointer to ethernet header (in input buffer). ! 506: * Deal with trailer protocol: if type is trailer type ! 507: * get true type from first 16-bit word past data. ! 508: * Remember that type was trailer by setting off. ! 509: */ ! 510: len = ecoff - ECRDOFF - sizeof (struct ether_header); ! 511: ec = (struct ether_header *)(ecbuf + ECRDOFF); ! 512: ec->ether_type = ntohs((u_short)ec->ether_type); ! 513: #define ecdataaddr(ec, off, type) ((type)(((caddr_t)((ec)+1)+(off)))) ! 514: if (ec->ether_type >= ETHERTYPE_TRAIL && ! 515: ec->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { ! 516: off = (ec->ether_type - ETHERTYPE_TRAIL) * 512; ! 517: if (off >= ETHERMTU) ! 518: goto setup; /* sanity */ ! 519: ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *)); ! 520: resid = ntohs(*(ecdataaddr(ec, off+2, u_short *))); ! 521: if (off + resid > len) ! 522: goto setup; /* sanity */ ! 523: len = off + resid; ! 524: } else ! 525: off = 0; ! 526: if (len == 0) ! 527: goto setup; ! 528: ! 529: /* ! 530: * Pull packet off interface. Off is nonzero if packet ! 531: * has trailing header; ecget will then force this header ! 532: * information to be at the front, but we still have to drop ! 533: * the type and length which are at the front of any trailer data. ! 534: */ ! 535: m = ecget(ecbuf, len, off, &es->es_if); ! 536: if (m) ! 537: ether_input(&es->es_if, ec, m); ! 538: /* ! 539: * Reset for next packet. ! 540: */ ! 541: setup: ! 542: #ifdef MULTI ! 543: if (es->es_if.if_flags & IFF_PROMISC) ! 544: start_read = EC_PROMISC; ! 545: else if (es->es_if.if_flags & IFF_MULTI) ! 546: start_read = EC_MULTI; ! 547: else ! 548: #endif MULTI ! 549: start_read = EC_READ; ! 550: addr->ec_rcr = start_read|EC_RCLR|rbuf; ! 551: } ! 552: ! 553: /* ! 554: * Routine to copy from mbuf chain to transmit ! 555: * buffer in UNIBUS memory. ! 556: * If packet size is less than the minimum legal size, ! 557: * the buffer is expanded. We probably should zero out the extra ! 558: * bytes for security, but that would slow things down. ! 559: */ ! 560: ecput(ecbuf, m) ! 561: u_char *ecbuf; ! 562: struct mbuf *m; ! 563: { ! 564: register struct mbuf *mp; ! 565: register int off; ! 566: u_char *bp; ! 567: ! 568: for (off = 2048, mp = m; mp; mp = mp->m_next) ! 569: off -= mp->m_len; ! 570: if (2048 - off < ETHERMIN + sizeof (struct ether_header)) ! 571: off = 2048 - ETHERMIN - sizeof (struct ether_header); ! 572: *(u_short *)ecbuf = off; ! 573: bp = (u_char *)(ecbuf + off); ! 574: for (mp = m; mp; mp = mp->m_next) { ! 575: register unsigned len = mp->m_len; ! 576: u_char *mcp; ! 577: ! 578: if (len == 0) ! 579: continue; ! 580: mcp = mtod(mp, u_char *); ! 581: if ((unsigned)bp & 01) { ! 582: *bp++ = *mcp++; ! 583: len--; ! 584: } ! 585: if (off = (len >> 1)) { ! 586: register u_short *to, *from; ! 587: ! 588: to = (u_short *)bp; ! 589: from = (u_short *)mcp; ! 590: do ! 591: *to++ = *from++; ! 592: while (--off > 0); ! 593: bp = (u_char *)to, ! 594: mcp = (u_char *)from; ! 595: } ! 596: if (len & 01) ! 597: *bp++ = *mcp++; ! 598: } ! 599: m_freem(m); ! 600: } ! 601: ! 602: /* ! 603: * Routine to copy from UNIBUS memory into mbufs. ! 604: * Similar in spirit to if_rubaget. ! 605: * ! 606: * Warning: This makes the fairly safe assumption that ! 607: * mbufs have even lengths. ! 608: */ ! 609: struct mbuf * ! 610: ecget(ecbuf, totlen, off0, ifp) ! 611: u_char *ecbuf; ! 612: int totlen, off0; ! 613: struct ifnet *ifp; ! 614: { ! 615: register struct mbuf *m; ! 616: struct mbuf *top = 0, **mp = ⊤ ! 617: register int off = off0, len; ! 618: u_char *cp = (ecbuf += ECRDOFF + sizeof (struct ether_header)); ! 619: u_char *packet_end = cp + totlen; ! 620: ! 621: if (off) { ! 622: off += 2 * sizeof(u_short); ! 623: totlen -= 2 *sizeof(u_short); ! 624: cp += off; ! 625: } ! 626: ! 627: MGETHDR(m, M_DONTWAIT, MT_DATA); ! 628: if (m == 0) ! 629: return (0); ! 630: m->m_pkthdr.rcvif = ifp; ! 631: m->m_pkthdr.len = totlen; ! 632: m->m_len = MHLEN; ! 633: ! 634: while (totlen > 0) { ! 635: register int words; ! 636: u_char *mcp; ! 637: ! 638: if (top) { ! 639: MGET(m, M_DONTWAIT, MT_DATA); ! 640: if (m == 0) { ! 641: m_freem(top); ! 642: return (0); ! 643: } ! 644: m->m_len = MLEN; ! 645: } ! 646: len = min(totlen, (packet_end - cp)); ! 647: if (len >= MINCLSIZE) { ! 648: MCLGET(m, M_DONTWAIT); ! 649: if (m->m_flags & M_EXT) ! 650: m->m_len = len = min(len, MCLBYTES); ! 651: else ! 652: len = m->m_len; ! 653: } else { ! 654: /* ! 655: * Place initial small packet/header at end of mbuf. ! 656: */ ! 657: if (len < m->m_len) { ! 658: if (top == 0 && len + max_linkhdr <= m->m_len) ! 659: m->m_data += max_linkhdr; ! 660: m->m_len = len; ! 661: } else ! 662: len = m->m_len; ! 663: } ! 664: mcp = mtod(m, u_char *); ! 665: if (words = (len >> 1)) { ! 666: register u_short *to, *from; ! 667: ! 668: to = (u_short *)mcp; ! 669: from = (u_short *)cp; ! 670: do ! 671: *to++ = *from++; ! 672: while (--words > 0); ! 673: mcp = (u_char *)to; ! 674: cp = (u_char *)from; ! 675: } ! 676: if (len & 01) ! 677: *mcp++ = *cp++; ! 678: *mp = m; ! 679: mp = &m->m_next; ! 680: totlen -= len; ! 681: if (cp == packet_end) ! 682: cp = ecbuf; ! 683: } ! 684: return (top); ! 685: bad: ! 686: m_freem(top); ! 687: return (0); ! 688: } ! 689: ! 690: /* ! 691: * Process an ioctl request. ! 692: */ ! 693: ecioctl(ifp, cmd, data) ! 694: register struct ifnet *ifp; ! 695: int cmd; ! 696: caddr_t data; ! 697: { ! 698: register struct ifaddr *ifa = (struct ifaddr *)data; ! 699: struct ec_softc *es = &ec_softc[ifp->if_unit]; ! 700: struct ecdevice *addr; ! 701: int s = splimp(), error = 0; ! 702: ! 703: addr = (struct ecdevice *)(ecinfo[ifp->if_unit]->ui_addr); ! 704: ! 705: switch (cmd) { ! 706: ! 707: case SIOCSIFADDR: ! 708: ifp->if_flags |= IFF_UP; ! 709: ! 710: switch (ifa->ifa_addr->sa_family) { ! 711: #ifdef INET ! 712: case AF_INET: ! 713: ecinit(ifp->if_unit); /* before arpwhohas */ ! 714: ((struct arpcom *)ifp)->ac_ipaddr = ! 715: IA_SIN(ifa)->sin_addr; ! 716: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); ! 717: break; ! 718: #endif ! 719: #ifdef NS ! 720: case AF_NS: ! 721: { ! 722: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); ! 723: ! 724: if (ns_nullhost(*ina)) ! 725: ina->x_host = *(union ns_host *)(es->es_addr); ! 726: else { ! 727: /* ! 728: * The manual says we can't change the address ! 729: * while the receiver is armed, ! 730: * so reset everything ! 731: */ ! 732: ifp->if_flags &= ~IFF_RUNNING; ! 733: bcopy((caddr_t)ina->x_host.c_host, ! 734: (caddr_t)es->es_addr, sizeof(es->es_addr)); ! 735: } ! 736: ecinit(ifp->if_unit); /* does ec_setaddr() */ ! 737: break; ! 738: } ! 739: #endif ! 740: default: ! 741: ecinit(ifp->if_unit); ! 742: break; ! 743: } ! 744: break; ! 745: ! 746: case SIOCSIFFLAGS: ! 747: if ((ifp->if_flags & IFF_UP) == 0 && ! 748: ifp->if_flags & IFF_RUNNING) { ! 749: addr->ec_xcr = EC_UECLR; ! 750: ifp->if_flags &= ~IFF_RUNNING; ! 751: } else if (ifp->if_flags & IFF_UP && ! 752: (ifp->if_flags & IFF_RUNNING) == 0) ! 753: ecinit(ifp->if_unit); ! 754: break; ! 755: ! 756: default: ! 757: error = EINVAL; ! 758: } ! 759: splx(s); ! 760: return (error); ! 761: } ! 762: ! 763: ec_setaddr(physaddr,unit) ! 764: u_char *physaddr; ! 765: int unit; ! 766: { ! 767: struct ec_softc *es = &ec_softc[unit]; ! 768: struct uba_device *ui = ecinfo[unit]; ! 769: register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; ! 770: register char nibble; ! 771: register int i, j; ! 772: ! 773: /* ! 774: * Use the ethernet address supplied ! 775: * Note that we do a UECLR here, so the receive buffers ! 776: * must be requeued. ! 777: */ ! 778: ! 779: #ifdef DEBUG ! 780: printf("ec_setaddr: setting address for unit %d = %s", ! 781: unit, ether_sprintf(physaddr)); ! 782: #endif ! 783: addr->ec_xcr = EC_UECLR; ! 784: addr->ec_rcr = 0; ! 785: /* load requested address */ ! 786: for (i = 0; i < 6; i++) { /* 6 bytes of address */ ! 787: es->es_addr[i] = physaddr[i]; ! 788: nibble = physaddr[i] & 0xf; /* lower nibble */ ! 789: addr->ec_rcr = (nibble << 8); ! 790: addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */ ! 791: addr->ec_rcr = (nibble << 8); ! 792: for (j=0; j < 4; j++) { ! 793: addr->ec_rcr = 0; ! 794: addr->ec_rcr = EC_ASTEP; /* step counter */ ! 795: addr->ec_rcr = 0; ! 796: } ! 797: nibble = (physaddr[i] >> 4) & 0xf; /* upper nibble */ ! 798: addr->ec_rcr = (nibble << 8); ! 799: addr->ec_rcr = (nibble << 8) + EC_AWCLK; /* latch nibble */ ! 800: addr->ec_rcr = (nibble << 8); ! 801: for (j=0; j < 4; j++) { ! 802: addr->ec_rcr = 0; ! 803: addr->ec_rcr = EC_ASTEP; /* step counter */ ! 804: addr->ec_rcr = 0; ! 805: } ! 806: } ! 807: #ifdef DEBUG ! 808: /* ! 809: * Read the ethernet address off the board, one nibble at a time. ! 810: */ ! 811: addr->ec_xcr = EC_UECLR; ! 812: addr->ec_rcr = 0; /* read RAM */ ! 813: cp = es->es_addr; ! 814: #undef NEXTBIT ! 815: #define NEXTBIT addr->ec_rcr = EC_ASTEP; addr->ec_rcr = 0 ! 816: for (i=0; i < sizeof (es->es_addr); i++) { ! 817: *cp = 0; ! 818: for (j=0; j<=4; j+=4) { ! 819: *cp |= ((addr->ec_rcr >> 8) & 0xf) << j; ! 820: NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT; ! 821: } ! 822: cp++; ! 823: } ! 824: printf("ec_setaddr: RAM address for unit %d = %s", ! 825: unit, ether_sprintf(physaddr)); ! 826: #endif ! 827: } ! 828: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.