|
|
1.1 ! root 1: /* if_ec.c 6.1 83/07/29 */ ! 2: ! 3: #include "ec.h" ! 4: ! 5: /* ! 6: * 3Com Ethernet Controller interface ! 7: */ ! 8: #include "../machine/pte.h" ! 9: ! 10: #include "../h/param.h" ! 11: #include "../h/systm.h" ! 12: #include "../h/mbuf.h" ! 13: #include "../h/buf.h" ! 14: #include "../h/protosw.h" ! 15: #include "../h/socket.h" ! 16: #include "../h/vmmac.h" ! 17: #include "../h/ioctl.h" ! 18: #include "../h/errno.h" ! 19: ! 20: #include "../net/if.h" ! 21: #include "../net/netisr.h" ! 22: #include "../net/route.h" ! 23: #include "../netinet/in.h" ! 24: #include "../netinet/in_systm.h" ! 25: #include "../netinet/ip.h" ! 26: #include "../netinet/ip_var.h" ! 27: #include "../netinet/if_ether.h" ! 28: #include "../netpup/pup.h" ! 29: ! 30: #include "../vax/cpu.h" ! 31: #include "../vax/mtpr.h" ! 32: #include "../vaxif/if_ecreg.h" ! 33: #include "../vaxif/if_uba.h" ! 34: #include "../vaxuba/ubareg.h" ! 35: #include "../vaxuba/ubavar.h" ! 36: ! 37: #define ECMEM 0000000 ! 38: ! 39: int ecprobe(), ecattach(), ecrint(), ecxint(), eccollide(); ! 40: struct uba_device *ecinfo[NEC]; ! 41: u_short ecstd[] = { 0 }; ! 42: struct uba_driver ecdriver = ! 43: { ecprobe, 0, ecattach, 0, ecstd, "ec", ecinfo }; ! 44: #define ECUNIT(x) minor(x) ! 45: ! 46: int ecinit(),ecioctl(),ecoutput(),ecreset(); ! 47: struct mbuf *ecget(); ! 48: ! 49: extern struct ifnet loif; ! 50: ! 51: /* ! 52: * Ethernet software status per interface. ! 53: * ! 54: * Each interface is referenced by a network interface structure, ! 55: * es_if, which the routing code uses to locate the interface. ! 56: * This structure contains the output queue for the interface, its address, ... ! 57: * We also have, for each interface, a UBA interface structure, which ! 58: * contains information about the UNIBUS resources held by the interface: ! 59: * map registers, buffered data paths, etc. Information is cached in this ! 60: * structure for use by the if_uba.c routines in running the interface ! 61: * efficiently. ! 62: */ ! 63: struct ec_softc { ! 64: struct arpcom es_ac; /* common Ethernet structures */ ! 65: #define es_if es_ac.ac_if /* network-visible interface */ ! 66: #define es_addr es_ac.ac_enaddr /* hardware Ethernet address */ ! 67: struct ifuba es_ifuba; /* UNIBUS resources */ ! 68: short es_mask; /* mask for current output delay */ ! 69: short es_oactive; /* is output active? */ ! 70: u_char *es_buf[16]; /* virtual addresses of buffers */ ! 71: } ec_softc[NEC]; ! 72: ! 73: /* ! 74: * Do output DMA to determine interface presence and ! 75: * interrupt vector. DMA is too short to disturb other hosts. ! 76: */ ! 77: ecprobe(reg) ! 78: caddr_t reg; ! 79: { ! 80: register int br, cvec; /* r11, r10 value-result */ ! 81: register struct ecdevice *addr = (struct ecdevice *)reg; ! 82: register caddr_t ecbuf = (caddr_t) &umem[numuba][ECMEM]; ! 83: ! 84: #ifdef lint ! 85: br = 0; cvec = br; br = cvec; ! 86: ecrint(0); ecxint(0); eccollide(0); ! 87: #endif ! 88: /* ! 89: * Make sure memory is turned on ! 90: */ ! 91: addr->ec_rcr = EC_AROM; ! 92: /* ! 93: * Disable map registers for ec unibus space, ! 94: * but don't allocate yet. ! 95: */ ! 96: (void) ubamem(numuba, ECMEM, 32*2, 0); ! 97: /* ! 98: * Check for existence of buffers on Unibus. ! 99: */ ! 100: if (badaddr((caddr_t)ecbuf, 2)) { ! 101: bad1: ! 102: printf("ec: buffer mem not found\n"); ! 103: bad2: ! 104: (void) ubamem(numuba, 0, 0, 0); /* reenable map (780 only) */ ! 105: addr->ec_rcr = EC_MDISAB; /* disable memory */ ! 106: return (0); ! 107: } ! 108: #if VAX780 ! 109: if (cpu == VAX_780 && uba_hd[numuba].uh_uba->uba_sr) { ! 110: uba_hd[numuba].uh_uba->uba_sr = uba_hd[numuba].uh_uba->uba_sr; ! 111: goto bad1; ! 112: } ! 113: #endif ! 114: ! 115: /* ! 116: * Tell the system that the board has memory here, so it won't ! 117: * attempt to allocate the addresses later. ! 118: */ ! 119: if (ubamem(numuba, ECMEM, 32*2, 1) == 0) { ! 120: printf("ecprobe: cannot reserve uba addresses\n"); ! 121: goto bad2; ! 122: } ! 123: ! 124: /* ! 125: * Make a one byte packet in what should be buffer #0. ! 126: * Submit it for sending. This whould cause an xmit interrupt. ! 127: * The xmit interrupt vector is 8 bytes after the receive vector, ! 128: * so adjust for this before returning. ! 129: */ ! 130: *(u_short *)ecbuf = (u_short) 03777; ! 131: ecbuf[03777] = '\0'; ! 132: addr->ec_xcr = EC_XINTEN|EC_XWBN; ! 133: DELAY(100000); ! 134: addr->ec_xcr = EC_XCLR; ! 135: if (cvec > 0 && cvec != 0x200) { ! 136: if (cvec & 04) { /* collision interrupt */ ! 137: cvec -= 04; ! 138: br += 1; /* rcv is collision + 1 */ ! 139: } else { /* xmit interrupt */ ! 140: cvec -= 010; ! 141: br += 2; /* rcv is xmit + 2 */ ! 142: } ! 143: } ! 144: return (1); ! 145: } ! 146: ! 147: /* ! 148: * Interface exists: make available by filling in network interface ! 149: * record. System will initialize the interface when it is ready ! 150: * to accept packets. ! 151: */ ! 152: ecattach(ui) ! 153: struct uba_device *ui; ! 154: { ! 155: struct ec_softc *es = &ec_softc[ui->ui_unit]; ! 156: register struct ifnet *ifp = &es->es_if; ! 157: register struct ecdevice *addr = (struct ecdevice *)ui->ui_addr; ! 158: struct sockaddr_in *sin; ! 159: int i, j; ! 160: u_char *cp; ! 161: ! 162: ifp->if_unit = ui->ui_unit; ! 163: ifp->if_name = "ec"; ! 164: ifp->if_mtu = ETHERMTU; ! 165: ! 166: /* ! 167: * Read the ethernet address off the board, one nibble at a time. ! 168: */ ! 169: addr->ec_xcr = EC_UECLR; ! 170: addr->ec_rcr = EC_AROM; ! 171: cp = es->es_addr; ! 172: #define NEXTBIT addr->ec_rcr = EC_AROM|EC_ASTEP; addr->ec_rcr = EC_AROM ! 173: for (i=0; i<6; i++) { ! 174: *cp = 0; ! 175: for (j=0; j<=4; j+=4) { ! 176: *cp |= ((addr->ec_rcr >> 8) & 0xf) << j; ! 177: NEXTBIT; NEXTBIT; NEXTBIT; NEXTBIT; ! 178: } ! 179: cp++; ! 180: } ! 181: sin = (struct sockaddr_in *)&es->es_if.if_addr; ! 182: sin->sin_family = AF_INET; ! 183: sin->sin_addr = arpmyaddr((struct arpcom *)0); ! 184: ifp->if_init = ecinit; ! 185: ifp->if_ioctl = ecioctl; ! 186: ifp->if_output = ecoutput; ! 187: ifp->if_reset = ecreset; ! 188: for (i=0; i<16; i++) ! 189: es->es_buf[i] = (u_char *)&umem[ui->ui_ubanum][ECMEM+2048*i]; ! 190: if_attach(ifp); ! 191: } ! 192: ! 193: /* ! 194: * Reset of interface after UNIBUS reset. ! 195: * If interface is on specified uba, reset its state. ! 196: */ ! 197: ecreset(unit, uban) ! 198: int unit, uban; ! 199: { ! 200: register struct uba_device *ui; ! 201: ! 202: if (unit >= NEC || (ui = ecinfo[unit]) == 0 || ui->ui_alive == 0 || ! 203: ui->ui_ubanum != uban) ! 204: return; ! 205: printf(" ec%d", unit); ! 206: (void) ubamem(uban, ECMEM, 32*2, 0); /* mr disable (no alloc) */ ! 207: ecinit(unit); ! 208: } ! 209: ! 210: /* ! 211: * Initialization of interface; clear recorded pending ! 212: * operations, and reinitialize UNIBUS usage. ! 213: */ ! 214: ecinit(unit) ! 215: int unit; ! 216: { ! 217: struct ec_softc *es = &ec_softc[unit]; ! 218: struct ecdevice *addr; ! 219: register struct ifnet *ifp = &es->es_if; ! 220: register struct sockaddr_in *sin; ! 221: int i, s; ! 222: ! 223: sin = (struct sockaddr_in *)&ifp->if_addr; ! 224: if (sin->sin_addr.s_addr == 0) /* address still unknown */ ! 225: return; ! 226: ! 227: /* ! 228: * Hang receive buffers and start any pending writes. ! 229: * Writing into the rcr also makes sure the memory ! 230: * is turned on. ! 231: */ ! 232: if ((es->es_if.if_flags & IFF_RUNNING) == 0) { ! 233: addr = (struct ecdevice *)ecinfo[unit]->ui_addr; ! 234: s = splimp(); ! 235: for (i = ECRHBF; i >= ECRLBF; i--) ! 236: addr->ec_rcr = EC_READ | i; ! 237: es->es_oactive = 0; ! 238: es->es_mask = ~0; ! 239: es->es_if.if_flags |= IFF_UP|IFF_RUNNING; ! 240: if (es->es_if.if_snd.ifq_head) ! 241: ecstart(unit); ! 242: splx(s); ! 243: } ! 244: if_rtinit(&es->es_if, RTF_UP); ! 245: arpattach(&es->es_ac); ! 246: arpwhohas(&es->es_ac, &sin->sin_addr); ! 247: } ! 248: ! 249: /* ! 250: * Start or restart output on interface. ! 251: * If interface is already active, then this is a retransmit ! 252: * after a collision, and just restuff registers. ! 253: * If interface is not already active, get another datagram ! 254: * to send off of the interface queue, and map it to the interface ! 255: * before starting the output. ! 256: */ ! 257: ecstart(dev) ! 258: dev_t dev; ! 259: { ! 260: int unit = ECUNIT(dev); ! 261: struct ec_softc *es = &ec_softc[unit]; ! 262: struct ecdevice *addr; ! 263: struct mbuf *m; ! 264: ! 265: if (es->es_oactive) ! 266: goto restart; ! 267: ! 268: IF_DEQUEUE(&es->es_if.if_snd, m); ! 269: if (m == 0) { ! 270: es->es_oactive = 0; ! 271: return; ! 272: } ! 273: ecput(es->es_buf[ECTBF], m); ! 274: ! 275: restart: ! 276: addr = (struct ecdevice *)ecinfo[unit]->ui_addr; ! 277: addr->ec_xcr = EC_WRITE|ECTBF; ! 278: es->es_oactive = 1; ! 279: } ! 280: ! 281: /* ! 282: * Ethernet interface transmitter interrupt. ! 283: * Start another output if more data to send. ! 284: */ ! 285: ecxint(unit) ! 286: int unit; ! 287: { ! 288: register struct ec_softc *es = &ec_softc[unit]; ! 289: register struct ecdevice *addr = ! 290: (struct ecdevice *)ecinfo[unit]->ui_addr; ! 291: ! 292: if (es->es_oactive == 0) ! 293: return; ! 294: if ((addr->ec_xcr&EC_XDONE) == 0 || (addr->ec_xcr&EC_XBN) != ECTBF) { ! 295: printf("ec%d: stray xmit interrupt, xcr=%b\n", unit, ! 296: addr->ec_xcr, EC_XBITS); ! 297: es->es_oactive = 0; ! 298: addr->ec_xcr = EC_XCLR; ! 299: return; ! 300: } ! 301: es->es_if.if_opackets++; ! 302: es->es_oactive = 0; ! 303: es->es_mask = ~0; ! 304: addr->ec_xcr = EC_XCLR; ! 305: if (es->es_if.if_snd.ifq_head) ! 306: ecstart(unit); ! 307: } ! 308: ! 309: /* ! 310: * Collision on ethernet interface. Do exponential ! 311: * backoff, and retransmit. If have backed off all ! 312: * the way print warning diagnostic, and drop packet. ! 313: */ ! 314: eccollide(unit) ! 315: int unit; ! 316: { ! 317: struct ec_softc *es = &ec_softc[unit]; ! 318: ! 319: es->es_if.if_collisions++; ! 320: if (es->es_oactive) ! 321: ecdocoll(unit); ! 322: } ! 323: ! 324: ecdocoll(unit) ! 325: int unit; ! 326: { ! 327: register struct ec_softc *es = &ec_softc[unit]; ! 328: register struct ecdevice *addr = ! 329: (struct ecdevice *)ecinfo[unit]->ui_addr; ! 330: register i; ! 331: int delay; ! 332: ! 333: /* ! 334: * Es_mask is a 16 bit number with n low zero bits, with ! 335: * n the number of backoffs. When es_mask is 0 we have ! 336: * backed off 16 times, and give up. ! 337: */ ! 338: if (es->es_mask == 0) { ! 339: es->es_if.if_oerrors++; ! 340: printf("ec%d: send error\n", unit); ! 341: /* ! 342: * Reset interface, then requeue rcv buffers. ! 343: * Some incoming packets may be lost, but that ! 344: * can't be helped. ! 345: */ ! 346: addr->ec_xcr = EC_UECLR; ! 347: for (i=ECRHBF; i>=ECRLBF; i--) ! 348: addr->ec_rcr = EC_READ|i; ! 349: /* ! 350: * Reset and transmit next packet (if any). ! 351: */ ! 352: es->es_oactive = 0; ! 353: es->es_mask = ~0; ! 354: if (es->es_if.if_snd.ifq_head) ! 355: ecstart(unit); ! 356: return; ! 357: } ! 358: /* ! 359: * Do exponential backoff. Compute delay based on low bits ! 360: * of the interval timer. Then delay for that number of ! 361: * slot times. A slot time is 51.2 microseconds (rounded to 51). ! 362: * This does not take into account the time already used to ! 363: * process the interrupt. ! 364: */ ! 365: es->es_mask <<= 1; ! 366: delay = mfpr(ICR) &~ es->es_mask; ! 367: DELAY(delay * 51); ! 368: /* ! 369: * Clear the controller's collision flag, thus enabling retransmit. ! 370: */ ! 371: addr->ec_xcr = EC_CLEAR; ! 372: } ! 373: ! 374: /* ! 375: * Ethernet interface receiver interrupt. ! 376: * If input error just drop packet. ! 377: * Otherwise purge input buffered data path and examine ! 378: * packet to determine type. If can't determine length ! 379: * from type, then have to drop packet. Othewise decapsulate ! 380: * packet based on type and pass to type specific higher-level ! 381: * input routine. ! 382: */ ! 383: ecrint(unit) ! 384: int unit; ! 385: { ! 386: struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; ! 387: ! 388: while (addr->ec_rcr & EC_RDONE) ! 389: ecread(unit); ! 390: } ! 391: ! 392: ecread(unit) ! 393: int unit; ! 394: { ! 395: register struct ec_softc *es = &ec_softc[unit]; ! 396: struct ecdevice *addr = (struct ecdevice *)ecinfo[unit]->ui_addr; ! 397: register struct ether_header *ec; ! 398: struct mbuf *m; ! 399: int len, off, resid, ecoff, rbuf; ! 400: register struct ifqueue *inq; ! 401: u_char *ecbuf; ! 402: ! 403: es->es_if.if_ipackets++; ! 404: rbuf = addr->ec_rcr & EC_RBN; ! 405: if (rbuf < ECRLBF || rbuf > ECRHBF) ! 406: panic("ecrint"); ! 407: ecbuf = es->es_buf[rbuf]; ! 408: ecoff = *(short *)ecbuf; ! 409: if (ecoff <= ECRDOFF || ecoff > 2046) { ! 410: es->es_if.if_ierrors++; ! 411: #ifdef notdef ! 412: if (es->es_if.if_ierrors % 100 == 0) ! 413: printf("ec%d: += 100 input errors\n", unit); ! 414: #endif ! 415: goto setup; ! 416: } ! 417: ! 418: /* ! 419: * Get input data length. ! 420: * Get pointer to ethernet header (in input buffer). ! 421: * Deal with trailer protocol: if type is PUP trailer ! 422: * get true type from first 16-bit word past data. ! 423: * Remember that type was trailer by setting off. ! 424: */ ! 425: len = ecoff - ECRDOFF - sizeof (struct ether_header); ! 426: ec = (struct ether_header *)(ecbuf + ECRDOFF); ! 427: ec->ether_type = ntohs((u_short)ec->ether_type); ! 428: #define ecdataaddr(ec, off, type) ((type)(((caddr_t)((ec)+1)+(off)))) ! 429: if (ec->ether_type >= ETHERPUP_TRAIL && ! 430: ec->ether_type < ETHERPUP_TRAIL+ETHERPUP_NTRAILER) { ! 431: off = (ec->ether_type - ETHERPUP_TRAIL) * 512; ! 432: if (off >= ETHERMTU) ! 433: goto setup; /* sanity */ ! 434: ec->ether_type = ntohs(*ecdataaddr(ec, off, u_short *)); ! 435: resid = ntohs(*(ecdataaddr(ec, off+2, u_short *))); ! 436: if (off + resid > len) ! 437: goto setup; /* sanity */ ! 438: len = off + resid; ! 439: } else ! 440: off = 0; ! 441: if (len == 0) ! 442: goto setup; ! 443: ! 444: /* ! 445: * Pull packet off interface. Off is nonzero if packet ! 446: * has trailing header; ecget will then force this header ! 447: * information to be at the front, but we still have to drop ! 448: * the type and length which are at the front of any trailer data. ! 449: */ ! 450: m = ecget(ecbuf, len, off); ! 451: if (m == 0) ! 452: goto setup; ! 453: if (off) { ! 454: m->m_off += 2 * sizeof (u_short); ! 455: m->m_len -= 2 * sizeof (u_short); ! 456: } ! 457: switch (ec->ether_type) { ! 458: ! 459: #ifdef INET ! 460: case ETHERPUP_IPTYPE: ! 461: schednetisr(NETISR_IP); ! 462: inq = &ipintrq; ! 463: break; ! 464: ! 465: case ETHERPUP_ARPTYPE: ! 466: arpinput(&es->es_ac, m); ! 467: goto setup; ! 468: #endif ! 469: default: ! 470: m_freem(m); ! 471: goto setup; ! 472: } ! 473: ! 474: if (IF_QFULL(inq)) { ! 475: IF_DROP(inq); ! 476: m_freem(m); ! 477: goto setup; ! 478: } ! 479: IF_ENQUEUE(inq, m); ! 480: ! 481: setup: ! 482: /* ! 483: * Reset for next packet. ! 484: */ ! 485: addr->ec_rcr = EC_READ|EC_RCLR|rbuf; ! 486: } ! 487: ! 488: /* ! 489: * Ethernet output routine. ! 490: * Encapsulate a packet of type family for the local net. ! 491: * Use trailer local net encapsulation if enough data in first ! 492: * packet leaves a multiple of 512 bytes of data in remainder. ! 493: * If destination is this address or broadcast, send packet to ! 494: * loop device to kludge around the fact that 3com interfaces can't ! 495: * talk to themselves. ! 496: */ ! 497: ecoutput(ifp, m0, dst) ! 498: struct ifnet *ifp; ! 499: struct mbuf *m0; ! 500: struct sockaddr *dst; ! 501: { ! 502: int type, s, error; ! 503: u_char edst[6]; ! 504: struct in_addr idst; ! 505: register struct ec_softc *es = &ec_softc[ifp->if_unit]; ! 506: register struct mbuf *m = m0; ! 507: register struct ether_header *ec; ! 508: register int off; ! 509: struct mbuf *mcopy = (struct mbuf *)0; ! 510: ! 511: switch (dst->sa_family) { ! 512: ! 513: #ifdef INET ! 514: case AF_INET: ! 515: idst = ((struct sockaddr_in *)dst)->sin_addr; ! 516: if (!arpresolve(&es->es_ac, m, &idst, edst)) ! 517: return (0); /* if not yet resolved */ ! 518: if (in_lnaof(idst) == INADDR_ANY) ! 519: mcopy = m_copy(m, 0, (int)M_COPYALL); ! 520: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; ! 521: /* need per host negotiation */ ! 522: if ((ifp->if_flags & IFF_NOTRAILERS) == 0) ! 523: if (off > 0 && (off & 0x1ff) == 0 && ! 524: m->m_off >= MMINOFF + 2 * sizeof (u_short)) { ! 525: type = ETHERPUP_TRAIL + (off>>9); ! 526: m->m_off -= 2 * sizeof (u_short); ! 527: m->m_len += 2 * sizeof (u_short); ! 528: *mtod(m, u_short *) = ntohs((u_short)ETHERPUP_IPTYPE); ! 529: *(mtod(m, u_short *) + 1) = ntohs((u_short)m->m_len); ! 530: goto gottrailertype; ! 531: } ! 532: type = ETHERPUP_IPTYPE; ! 533: off = 0; ! 534: goto gottype; ! 535: #endif ! 536: ! 537: case AF_UNSPEC: ! 538: ec = (struct ether_header *)dst->sa_data; ! 539: bcopy((caddr_t)ec->ether_dhost, (caddr_t)edst, sizeof (edst)); ! 540: type = ec->ether_type; ! 541: goto gottype; ! 542: ! 543: default: ! 544: printf("ec%d: can't handle af%d\n", ifp->if_unit, ! 545: dst->sa_family); ! 546: error = EAFNOSUPPORT; ! 547: goto bad; ! 548: } ! 549: ! 550: gottrailertype: ! 551: /* ! 552: * Packet to be sent as trailer: move first packet ! 553: * (control information) to end of chain. ! 554: */ ! 555: while (m->m_next) ! 556: m = m->m_next; ! 557: m->m_next = m0; ! 558: m = m0->m_next; ! 559: m0->m_next = 0; ! 560: m0 = m; ! 561: ! 562: gottype: ! 563: /* ! 564: * Add local net header. If no space in first mbuf, ! 565: * allocate another. ! 566: */ ! 567: if (m->m_off > MMAXOFF || ! 568: MMINOFF + sizeof (struct ether_header) > m->m_off) { ! 569: m = m_get(M_DONTWAIT, MT_HEADER); ! 570: if (m == 0) { ! 571: error = ENOBUFS; ! 572: goto bad; ! 573: } ! 574: m->m_next = m0; ! 575: m->m_off = MMINOFF; ! 576: m->m_len = sizeof (struct ether_header); ! 577: } else { ! 578: m->m_off -= sizeof (struct ether_header); ! 579: m->m_len += sizeof (struct ether_header); ! 580: } ! 581: ec = mtod(m, struct ether_header *); ! 582: bcopy((caddr_t)edst, (caddr_t)ec->ether_dhost, sizeof (edst)); ! 583: ec->ether_type = htons((u_short)type); ! 584: bcopy((caddr_t)es->es_addr, (caddr_t)ec->ether_shost, 6); ! 585: ! 586: /* ! 587: * Queue message on interface, and start output if interface ! 588: * not yet active. ! 589: */ ! 590: s = splimp(); ! 591: if (IF_QFULL(&ifp->if_snd)) { ! 592: IF_DROP(&ifp->if_snd); ! 593: error = ENOBUFS; ! 594: goto qfull; ! 595: } ! 596: IF_ENQUEUE(&ifp->if_snd, m); ! 597: if (es->es_oactive == 0) ! 598: ecstart(ifp->if_unit); ! 599: splx(s); ! 600: return (mcopy ? looutput(&loif, mcopy, dst) : 0); ! 601: ! 602: qfull: ! 603: m0 = m; ! 604: splx(s); ! 605: bad: ! 606: m_freem(m0); ! 607: return (error); ! 608: } ! 609: ! 610: /* ! 611: * Routine to copy from mbuf chain to transmit ! 612: * buffer in UNIBUS memory. ! 613: * If packet size is less than the minimum legal size, ! 614: * the buffer is expanded. We probably should zero out the extra ! 615: * bytes for security, but that would slow things down. ! 616: */ ! 617: ecput(ecbuf, m) ! 618: u_char *ecbuf; ! 619: struct mbuf *m; ! 620: { ! 621: register struct mbuf *mp; ! 622: register int off; ! 623: u_char *bp; ! 624: ! 625: for (off = 2048, mp = m; mp; mp = mp->m_next) ! 626: off -= mp->m_len; ! 627: if (2048 - off < ETHERMIN + sizeof (struct ether_header)) ! 628: off = 2048 - ETHERMIN - sizeof (struct ether_header); ! 629: *(u_short *)ecbuf = off; ! 630: bp = (u_char *)(ecbuf + off); ! 631: for (mp = m; mp; mp = mp->m_next) { ! 632: register unsigned len = mp->m_len; ! 633: u_char *mcp; ! 634: ! 635: if (len == 0) ! 636: continue; ! 637: mcp = mtod(mp, u_char *); ! 638: if ((unsigned)bp & 01) { ! 639: *bp++ = *mcp++; ! 640: len--; ! 641: } ! 642: if (off = (len >> 1)) { ! 643: register u_short *to, *from; ! 644: ! 645: to = (u_short *)bp; ! 646: from = (u_short *)mcp; ! 647: do ! 648: *to++ = *from++; ! 649: while (--off > 0); ! 650: bp = (u_char *)to, ! 651: mcp = (u_char *)from; ! 652: } ! 653: if (len & 01) ! 654: *bp++ = *mcp++; ! 655: } ! 656: m_freem(m); ! 657: } ! 658: ! 659: /* ! 660: * Routine to copy from UNIBUS memory into mbufs. ! 661: * Similar in spirit to if_rubaget. ! 662: * ! 663: * Warning: This makes the fairly safe assumption that ! 664: * mbufs have even lengths. ! 665: */ ! 666: struct mbuf * ! 667: ecget(ecbuf, totlen, off0) ! 668: u_char *ecbuf; ! 669: int totlen, off0; ! 670: { ! 671: register struct mbuf *m; ! 672: struct mbuf *top = 0, **mp = ⊤ ! 673: register int off = off0, len; ! 674: u_char *cp; ! 675: ! 676: cp = ecbuf + ECRDOFF + sizeof (struct ether_header); ! 677: while (totlen > 0) { ! 678: register int words; ! 679: u_char *mcp; ! 680: ! 681: MGET(m, M_DONTWAIT, MT_DATA); ! 682: if (m == 0) ! 683: goto bad; ! 684: if (off) { ! 685: len = totlen - off; ! 686: cp = ecbuf + ECRDOFF + ! 687: sizeof (struct ether_header) + off; ! 688: } else ! 689: len = totlen; ! 690: if (len >= CLBYTES) { ! 691: struct mbuf *p; ! 692: ! 693: MCLGET(p, 1); ! 694: if (p != 0) { ! 695: m->m_len = len = CLBYTES; ! 696: m->m_off = (int)p - (int)m; ! 697: } else { ! 698: m->m_len = len = MIN(MLEN, len); ! 699: m->m_off = MMINOFF; ! 700: } ! 701: } else { ! 702: m->m_len = len = MIN(MLEN, len); ! 703: m->m_off = MMINOFF; ! 704: } ! 705: mcp = mtod(m, u_char *); ! 706: if (words = (len >> 1)) { ! 707: register u_short *to, *from; ! 708: ! 709: to = (u_short *)mcp; ! 710: from = (u_short *)cp; ! 711: do ! 712: *to++ = *from++; ! 713: while (--words > 0); ! 714: mcp = (u_char *)to; ! 715: cp = (u_char *)from; ! 716: } ! 717: if (len & 01) ! 718: *mcp++ = *cp++; ! 719: *mp = m; ! 720: mp = &m->m_next; ! 721: if (off == 0) { ! 722: totlen -= len; ! 723: continue; ! 724: } ! 725: off += len; ! 726: if (off == totlen) { ! 727: cp = ecbuf + ECRDOFF + sizeof (struct ether_header); ! 728: off = 0; ! 729: totlen = off0; ! 730: } ! 731: } ! 732: return (top); ! 733: bad: ! 734: m_freem(top); ! 735: return (0); ! 736: } ! 737: ! 738: /* ! 739: * Process an ioctl request. ! 740: */ ! 741: ecioctl(ifp, cmd, data) ! 742: register struct ifnet *ifp; ! 743: int cmd; ! 744: caddr_t data; ! 745: { ! 746: register struct ifreq *ifr = (struct ifreq *)data; ! 747: int s = splimp(), error = 0; ! 748: ! 749: switch (cmd) { ! 750: ! 751: case SIOCSIFADDR: ! 752: if (ifp->if_flags & IFF_RUNNING) ! 753: if_rtinit(ifp, -1); /* delete previous route */ ! 754: ecsetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr); ! 755: ecinit(ifp->if_unit); ! 756: break; ! 757: ! 758: default: ! 759: error = EINVAL; ! 760: } ! 761: splx(s); ! 762: return (error); ! 763: } ! 764: ! 765: ecsetaddr(ifp, sin) ! 766: register struct ifnet *ifp; ! 767: register struct sockaddr_in *sin; ! 768: { ! 769: ! 770: ifp->if_addr = *(struct sockaddr *)sin; ! 771: ifp->if_net = in_netof(sin->sin_addr); ! 772: ifp->if_host[0] = in_lnaof(sin->sin_addr); ! 773: sin = (struct sockaddr_in *)&ifp->if_broadaddr; ! 774: sin->sin_family = AF_INET; ! 775: sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); ! 776: ifp->if_flags |= IFF_BROADCAST; ! 777: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.