1: /* 2: * Copyright (c) 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)if_vv.c 2.1 (2.11BSD) 1996/11/27 7: */ 8: 9: #include "vv.h" 10: #if NVV > 0 11: 12: /* 13: * Proteon proNET-10 and proNET-80 token ring driver. 14: * The name of this device driver derives from the old MIT 15: * name of V2LNI for the proNET hardware, would would abbreviate 16: * to "v2", but this won't work right. Thus the name is "vv". 17: * 18: * This driver is compatible with the proNET 10 meagbit and 19: * 80 megabit token ring interfaces (models p1000 and p1080). 20: * A unit may be marked as 80 megabit using "flags 1" in the 21: * config file. 22: * 23: * TRAILERS: This driver has a new implementation of trailers that 24: * is at least a tolerable neighbor on the ring. The offset is not 25: * stored in the protocol type, but instead only in the vh_info 26: * field. Also, the vh_info field, and the two shorts before the 27: * trailing header, are in network byte order, not VAX byte order. 28: * 29: * Of course, nothing but BSD UNIX supports trailers on ProNET. 30: * If you need interoperability with anything else, turn off 31: * trailers using the -trailers option to ifconfig! 32: * 33: * HARDWARE COMPATABILITY: This driver prefers that the HSBU (p1001) 34: * have a serial number >= 040, which is about March, 1982. Older 35: * HSBUs do not carry across 64kbyte boundaries. They can be supported 36: * by adding "| UBA_NEED16" to the vs_ifuba.ifu_flags initialization 37: * in vvattach(). 38: * 39: * The old warning about use without Wire Centers applies only to CTL 40: * (p1002) cards with serial <= 057, which have not received ECO 176-743, 41: * which was implemented in March, 1982. Most such CTLs have received 42: * this ECO. 43: */ 44: 45: #include "param.h" 46: #include "../machine/seg.h" 47: #include "systm.h" 48: #include "mbuf.h" 49: #include "buf.h" 50: #include "domain.h" 51: #include "protosw.h" 52: #include "socket.h" 53: #include "ioctl.h" 54: #include "pdpif/if_vv.h" 55: #include "pdpif/if_uba.h" 56: #include "errno.h" 57: #include "pdpuba/ubavar.h" 58: #include "net/if.h" 59: #include "net/netisr.h" 60: #include "net/route.h" 61: 62: #ifdef INET 63: #include "netinet/in.h" 64: #include "netinet/in_systm.h" 65: #include "netinet/in_var.h" 66: #include "netinet/ip.h" 67: #include "netinet/ip_var.h" 68: #endif 69: 70: /* 71: * maximum transmission unit definition -- 72: * you can set VVMTU at anything from 576 to 2024. 73: * 1536 is a popular "large" value, because it is a multiple 74: * of 512, which the trailer scheme likes. 75: * The absolute maximum size is 2024, which is enforced. 76: */ 77: 78: #define VVMTU (1536) 79: 80: #define VVMRU (VVMTU + 16) 81: #define VVBUFSIZE (VVMRU + sizeof(struct vv_header)) 82: #if VVMTU>2024 83: #undef VVMTU 84: #undef VVMRU 85: #undef VVBUFSIZE 86: #define VVBUFSIZE (2046) 87: #define VVMRU (VVBUFSIZE - sizeof (struct vv_header)) 88: #define VVMTU (VVMRU - 16) 89: #endif 90: 91: /* 92: * debugging and tracing stuff 93: */ 94: int vv_tracehdr = 0; /* 1 => trace headers (slowly!!) */ 95: 96: #define vvtracehdr if (vv_tracehdr) vvprt_hdr 97: #define vvprintf if (vs->vs_if.if_flags & IFF_DEBUG) printf 98: 99: /* 100: * externals, types, etc. 101: */ 102: int vvprobe(), vvattach(), vvreset(), vvinit(); 103: int vvidentify(), vvstart(), vvxint(), vvwatchdog(); 104: int vvrint(), vvoutput(), vvioctl(); 105: struct uba_device *vvinfo[NVV]; 106: u_short vvstd[] = { 0 }; 107: struct uba_driver vvdriver = 108: { vvprobe, 0, vvattach, 0, vvstd, "vv", vvinfo }; 109: #define VVUNIT(x) minor(x) 110: 111: #define LOOPBACK /* use loopback for packets meant for us */ 112: #ifdef LOOPBACK 113: extern struct ifnet loif; 114: #endif 115: 116: /* 117: * Software status of each interface. 118: * 119: * Each interface is referenced by a network interface structure, 120: * vs_if, which the routing code uses to locate the interface. 121: * This structure contains the output queue for the interface, its address, ... 122: * We also have, for each interface, a UBA interface structure, which 123: * contains information about the UNIBUS resources held by the interface: 124: * map registers, buffered data paths, etc. Information is cached in this 125: * structure for use by the if_uba.c routines in running the interface 126: * efficiently. 127: */ 128: struct vv_softc { 129: struct ifnet vs_if; /* network-visible interface */ 130: struct ifuba vs_ifuba; /* UNIBUS resources */ 131: u_short vs_host; /* this interface address */ 132: short vs_oactive; /* is output active */ 133: short vs_is80; /* is 80 megabit version */ 134: short vs_olen; /* length of last output */ 135: u_short vs_lastx; /* address of last packet sent */ 136: u_short vs_lastr; /* address of last packet received */ 137: short vs_tries; /* transmit current retry count */ 138: short vs_init; /* number of ring inits */ 139: short vs_refused; /* number of packets refused */ 140: short vs_timeouts; /* number of transmit timeouts */ 141: short vs_otimeout; /* number of output timeouts */ 142: short vs_ibadf; /* number of input bad formats */ 143: short vs_parity; /* number of parity errors on 10 meg, */ 144: /* link data errors on 80 meg */ 145: } vv_softc[NVV]; 146: 147: #define NOHOST 0xffff /* illegal host number */ 148: 149: vvprobe(reg) 150: caddr_t reg; 151: { 152: #ifdef notdef 153: register int br, cvec; 154: register struct vvreg *addr; 155: 156: #ifdef lint 157: br = 0; cvec = br; br = cvec; 158: #endif 159: addr = (struct vvreg *)reg; 160: /* reset interface, enable, and wait till dust settles */ 161: addr->vvicsr = VV_RST; 162: addr->vvocsr = VV_RST; 163: DELAY(100000L); 164: 165: /* generate interrupt by doing 1 word DMA from 0 in uba space!! */ 166: addr->vvoba = 0; /* low 16 bits */ 167: addr->vvoea = 0; /* extended bits */ 168: addr->vvowc = -1; /* for 1 word */ 169: addr->vvocsr = VV_IEN | VV_DEN; /* start the DMA, with interrupt */ 170: DELAY(100000L); 171: addr->vvocsr = VV_RST; /* clear out the CSR */ 172: if (cvec && cvec != 0x200) 173: cvec -= 4; /* backup so vector => receive */ 174: #endif 175: return(1); 176: } 177: 178: /* 179: * Interface exists: make available by filling in network interface 180: * record. System will initialize the interface when it is ready 181: * to accept packets. 182: */ 183: vvattach(ui) 184: struct uba_device *ui; 185: { 186: register struct vv_softc *vs; 187: 188: vs = &vv_softc[ui->ui_unit]; 189: vs->vs_if.if_unit = ui->ui_unit; 190: vs->vs_if.if_name = "vv"; 191: vs->vs_if.if_mtu = VVMTU; 192: vs->vs_if.if_flags = IFF_BROADCAST; 193: vs->vs_if.if_init = vvinit; 194: vs->vs_if.if_ioctl = vvioctl; 195: vs->vs_if.if_output = vvoutput; 196: vs->vs_if.if_reset = vvreset; 197: vs->vs_if.if_timer = 0; 198: vs->vs_if.if_watchdog = vvwatchdog; 199: vs->vs_ifuba.ifu_flags = UBA_CANTWAIT | UBA_NEEDBDP; 200: 201: /* use flag to determine if this is proNET-80 */ 202: vs->vs_is80 = (short)(ui->ui_flags & 01); 203: 204: #if defined(VAX750) 205: /* don't chew up 750 bdp's */ 206: if (cpu == VAX_750 && ui->ui_unit > 0) 207: vs->vs_ifuba.ifu_flags &= ~UBA_NEEDBDP; 208: #endif 209: if_attach(&vs->vs_if); 210: } 211: 212: /* 213: * Reset of interface after UNIBUS reset. 214: * If interface is on specified uba, reset its state. 215: */ 216: vvreset(unit, uban) 217: int unit, uban; 218: { 219: register struct uba_device *ui; 220: 221: if (unit >= NVV || (ui = vvinfo[unit]) == 0 || ui->ui_alive == 0 || 222: ui->ui_ubanum != uban) 223: return; 224: printf(" vv%d", unit); 225: vvinit(unit); 226: } 227: 228: /* 229: * Initialization of interface; clear recorded pending 230: * operations, and reinitialize UNIBUS usage. 231: */ 232: vvinit(unit) 233: int unit; 234: { 235: register struct vv_softc *vs; 236: register struct uba_device *ui; 237: register struct vvreg *addr; 238: register int s; 239: ubadr_t ubainfo; 240: 241: vs = &vv_softc[unit]; 242: ui = vvinfo[unit]; 243: 244: if (vs->vs_if.if_addrlist == (struct ifaddr *)0) 245: return; 246: 247: addr = (struct vvreg *)ui->ui_addr; 248: if (if_ubainit(&vs->vs_ifuba, ui->ui_ubanum, 249: sizeof (struct vv_header), (int)btoc(VVMTU)) == 0) { 250: printf("vv%d: can't initialize, if_ubainit() failed\n", unit); 251: vs->vs_if.if_flags &= ~IFF_UP; 252: return; 253: } 254: 255: /* 256: * Now that the uba is set up, figure out our address and 257: * update complete our host address. 258: */ 259: if ((vs->vs_host = vvidentify(unit)) == NOHOST) { 260: vs->vs_if.if_flags &= ~IFF_UP; 261: return; 262: } 263: printf("vv%d: host %u\n", unit, vs->vs_host); 264: 265: /* 266: * Reset the interface, and stay in the ring 267: */ 268: addr->vvocsr = VV_RST; /* take over output */ 269: addr->vvocsr = VV_CPB; /* clear packet buffer */ 270: addr->vvicsr = VV_RST | VV_HEN; /* take over input, */ 271: /* keep relay closed */ 272: DELAY(500000L); /* let contacts settle */ 273: 274: vs->vs_init = 0; /* clear counters, etc. */ 275: vs->vs_refused = 0; 276: vs->vs_timeouts = 0; 277: vs->vs_otimeout = 0; 278: vs->vs_ibadf = 0; 279: vs->vs_parity = 0; 280: vs->vs_lastx = 256; /* an invalid address */ 281: vs->vs_lastr = 256; /* an invalid address */ 282: 283: /* 284: * Hang a receive and start any 285: * pending writes by faking a transmit complete. 286: */ 287: s = splimp(); 288: ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; 289: addr->vviba = (u_short)ubainfo; 290: addr->vviea = (u_short)(ubainfo >> 16); 291: addr->vviwc = -(VVBUFSIZE) >> 1; 292: addr->vvicsr = VV_IEN | VV_HEN | VV_DEN | VV_ENB; 293: vs->vs_oactive = 1; 294: vs->vs_if.if_flags |= IFF_RUNNING; 295: vvxint(unit); 296: splx(s); 297: } 298: 299: /* 300: * Return our host address. 301: */ 302: 303: vvidentify(unit) 304: int unit; 305: { 306: register struct vv_softc *vs; 307: register struct uba_device *ui; 308: register struct vvreg *addr; 309: register struct mbuf *m; 310: register struct vv_header *v; 311: register int attempts, waitcount; 312: ubadr_t ubainfo; 313: segm seg5; 314: u_short host; 315: u_char type; 316: 317: /* 318: * Build a multicast message to identify our address 319: */ 320: vs = &vv_softc[unit]; 321: ui = vvinfo[unit]; 322: addr = (struct vvreg *)ui->ui_addr; 323: attempts = 0; /* total attempts, including bad msg type */ 324: m = m_get(M_DONTWAIT, MT_HEADER); 325: if (m == NULL) { 326: printf("vv%d: can't initialize, m_get() failed\n", unit); 327: return (NOHOST); 328: } 329: m->m_next = 0; 330: m->m_off = MMINOFF; 331: m->m_len = sizeof(struct vv_header); 332: v = mtod(m, struct vv_header *); 333: v->vh_dhost = VV_BROADCAST; /* multicast destination address */ 334: v->vh_shost = 0; /* will be overwritten with ours */ 335: v->vh_version = RING_VERSION; 336: v->vh_type = RING_WHOAMI; 337: v->vh_info = 0; 338: /* map xmit message into uba */ 339: vs->vs_olen = if_wubaput(&vs->vs_ifuba, m); 340: /* 341: * Reset interface, establish Digital Loopback Mode, and 342: * send the multicast (to myself) with Input Copy enabled. 343: */ 344: retry: 345: ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; 346: addr->vvicsr = VV_RST; 347: addr->vviba = (u_short) ubainfo; 348: addr->vviea = (u_short) (ubainfo >> 16); 349: addr->vviwc = -(sizeof (struct vv_header) + VVMTU) >> 1; 350: addr->vvicsr = VV_STE | VV_DEN | VV_ENB | VV_LPB; 351: 352: /* let flag timers fire so ring will initialize */ 353: DELAY(2000000L); /* about 2 SECONDS on a 780!! */ 354: 355: addr->vvocsr = VV_RST | VV_CPB; /* clear packet buffer */ 356: ubainfo = vs->vs_ifuba.ifu_w.ifrw_info; 357: addr->vvoba = (u_short) ubainfo; 358: addr->vvoea = (u_short) (ubainfo >> 16); 359: addr->vvowc = -((vs->vs_olen + 1) >> 1); 360: addr->vvocsr = VV_CPB | VV_DEN | VV_INR | VV_ENB; 361: /* 362: * Wait for receive side to finish. 363: * Extract source address (which will be our own), 364: * and post to interface structure. 365: */ 366: DELAY(10000L); 367: for (waitcount = 0; (addr->vvicsr & VV_RDY) == 0; waitcount++) { 368: if (waitcount < 10) { 369: DELAY(1000L); 370: continue; 371: } 372: if (attempts++ < VVIDENTRETRY) 373: goto retry; 374: break; 375: } 376: /* deallocate mbuf used for send packet */ 377: if (vs->vs_ifuba.ifu_xtofree) { 378: m_freem(vs->vs_ifuba.ifu_xtofree); 379: vs->vs_ifuba.ifu_xtofree = 0; 380: } 381: if (attempts >= VVIDENTRETRY) { 382: printf("vv%d: can't initialize after %d tries, icsr = %b\n", 383: unit, VVIDENTRETRY, 0xffff&(addr->vvicsr), VV_IBITS); 384: return (NOHOST); 385: } 386: m = if_rubaget(&vs->vs_ifuba, sizeof(struct vv_header), 0, &vs->vs_if); 387: if (m != NULL) 388: m_freem(m); 389: /* 390: * Check message type before we believe the source host address 391: */ 392: saveseg5(seg5); 393: mapseg5(vs->vs_ifuba.ifu_r.ifrw_click, 077406); 394: v = (struct vv_header *) SEG5; 395: type = v->vh_type; 396: host = (u_short)v->vh_shost; 397: restorseg5(seg5); 398: if (type != (u_char)RING_WHOAMI) 399: goto retry; 400: return(host); 401: } 402: 403: /* 404: * Start or restart output on interface. 405: * If interface is active, this is a retransmit, so just 406: * restuff registers and go. 407: * If interface is not already active, get another datagram 408: * to send off of the interface queue, and map it to the interface 409: * before starting the output. 410: */ 411: vvstart(dev) 412: dev_t dev; 413: { 414: register struct uba_device *ui; 415: register struct vv_softc *vs; 416: register struct vvreg *addr; 417: register struct mbuf *m; 418: register int unit, dest, s; 419: ubadr_t ubainfo; 420: segm save5; 421: 422: unit = VVUNIT(dev); 423: ui = vvinfo[unit]; 424: vs = &vv_softc[unit]; 425: if (vs->vs_oactive) 426: goto restart; 427: /* 428: * Not already active: dequeue another request 429: * and map it to the UNIBUS. If no more requests, 430: * just return. 431: */ 432: s = splimp(); 433: IF_DEQUEUE(&vs->vs_if.if_snd, m); 434: splx(s); 435: if (m == NULL) { 436: vs->vs_oactive = 0; 437: return; 438: } 439: dest = mtod(m, struct vv_header *)->vh_dhost; 440: vs->vs_olen = if_wubaput(&vs->vs_ifuba, m); 441: vs->vs_lastx = dest; 442: restart: 443: /* 444: * Have request mapped to UNIBUS for transmission. 445: * Purge any stale data from this BDP, and start the output. 446: * 447: * Make sure this packet will fit in the interface. 448: */ 449: if (vs->vs_olen > VVBUFSIZE) { 450: printf("vv%d vs_olen: %d > VVBUFSIZE\n", unit, vs->vs_olen); 451: panic("vvdriver vs_olen botch"); 452: } 453: 454: vs->vs_if.if_timer = VVTIMEOUT; 455: vs->vs_oactive = 1; 456: 457: /* ship it */ 458: addr = (struct vvreg *)ui->ui_addr; 459: ubainfo = vs->vs_ifuba.ifu_w.ifrw_info; 460: addr->vvoba = (u_short) ubainfo; 461: addr->vvoea = (u_short) (ubainfo >> 16); 462: addr->vvowc = -((vs->vs_olen + 1) >> 1); 463: addr->vvowc = -((vs->vs_olen + 1) >> 1); /* extra byte is garbage */ 464: if (addr->vvocsr & VV_NOK) 465: vs->vs_init++; /* count ring inits */ 466: addr->vvocsr = VV_IEN | VV_CPB | VV_DEN | VV_INR | VV_ENB; 467: } 468: 469: /* 470: * proNET transmit interrupt 471: * Start another output if more data to send. 472: */ 473: vvxint(unit) 474: int unit; 475: { 476: register struct uba_device *ui; 477: register struct vv_softc *vs; 478: register struct vvreg *addr; 479: register int oc; 480: 481: ui = vvinfo[unit]; 482: vs = &vv_softc[unit]; 483: vs->vs_if.if_timer = 0; 484: addr = (struct vvreg *)ui->ui_addr; 485: oc = 0xffff & (addr->vvocsr); 486: if (vs->vs_oactive == 0) { 487: vvprintf("vv%d: stray interrupt vvocsr = %b\n", unit, 488: oc, VV_OBITS); 489: return; 490: } 491: 492: /* 493: * we retransmit on soft error 494: * TODO: sort retransmits to end of queue if possible! 495: */ 496: if (oc & (VV_OPT | VV_RFS)) { 497: if (vs->vs_tries++ < VVRETRY) { 498: if (oc & VV_OPT) 499: vs->vs_otimeout++; 500: if (oc & VV_RFS) { 501: vs->vs_if.if_collisions++; 502: vs->vs_refused++; 503: } 504: vvstart(unit); /* restart this message */ 505: return; 506: } 507: } 508: vs->vs_if.if_opackets++; 509: vs->vs_oactive = 0; 510: vs->vs_tries = 0; 511: 512: if (oc & VVXERR) { 513: vs->vs_if.if_oerrors++; 514: vvprintf("vv%d: error vvocsr = %b\n", unit, 0xffff & oc, 515: VV_OBITS); 516: } 517: if (vs->vs_ifuba.ifu_xtofree) { 518: m_freem(vs->vs_ifuba.ifu_xtofree); 519: vs->vs_ifuba.ifu_xtofree = 0; 520: } 521: vvstart(unit); 522: } 523: 524: /* 525: * Transmit watchdog timer routine. 526: * This routine gets called when we lose a transmit interrupt. 527: * The best we can do is try to restart output. 528: */ 529: vvwatchdog(unit) 530: int unit; 531: { 532: register struct vv_softc *vs; 533: register int s; 534: 535: vs = &vv_softc[unit]; 536: vvprintf("vv%d: lost a transmit interrupt.\n", unit); 537: vs->vs_timeouts++; 538: s = splimp(); 539: vvstart(unit); 540: splx(s); 541: } 542: 543: /* 544: * proNET interface receiver interrupt. 545: * If input error just drop packet. 546: * Otherwise purge input buffered data path and examine 547: * packet to determine type. If can't determine length 548: * from type, then have to drop packet. Otherwise decapsulate 549: * packet based on type and pass to type specific higher-level 550: * input routine. 551: */ 552: vvrint(unit) 553: int unit; 554: { 555: register struct vv_softc *vs; 556: register struct vvreg *addr; 557: register struct vv_header *vv; 558: register struct ifqueue *inq; 559: register struct mbuf *m; 560: int len, off, s; 561: ubadr_t ubainfo; 562: segm save5; 563: short resid; 564: u_short type, shost; 565: 566: saveseg5(save5); 567: vs = &vv_softc[unit]; 568: vs->vs_if.if_ipackets++; 569: addr = (struct vvreg *)vvinfo[unit]->ui_addr; 570: if (addr->vvicsr & VVRERR) { 571: vvprintf("vv%d: receive error, vvicsr = %b\n", unit, 572: 0xffff&(addr->vvicsr), VV_IBITS); 573: if (addr->vvicsr & VV_BDF) 574: vs->vs_ibadf++; 575: goto dropit; 576: } 577: 578: /* 579: * parity errors? 580: */ 581: if (addr->vvicsr & VV_LDE) { 582: /* we don't have to clear it because the receive command */ 583: /* writes 0 to parity bit */ 584: vs->vs_parity++; 585: 586: /* 587: * only on 10 megabit proNET is VV_LDE an end-to-end parity 588: * bit. On 80 megabit, it returns to the intended use of 589: * node-to-node parity. End-to-end parity errors on 80 megabit 590: * give VV_BDF. 591: */ 592: if (vs->vs_is80 == 0) 593: goto dropit; 594: } 595: 596: /* 597: * Get packet length from residual word count 598: * 599: * Compute header offset if trailer protocol 600: * 601: * Pull packet off interface. Off is nonzero if packet 602: * has trailing header; if_rubaget will then force this header 603: * information to be at the front. The vh_info field 604: * carries the offset to the trailer data in trailer 605: * format packets. 606: */ 607: mapseg5(vs->vs_ifuba.ifu_r.ifrw_click, (btoc(VVMRU) << 8) | RW); 608: vv = (struct vv_header *) SEG5; 609: vvtracehdr("vi", vv); 610: resid = addr->vviwc & 01777; /* only low 10 bits valid */ 611: if (resid) 612: resid |= 0176000; /* high 6 bits are undefined */ 613: len = ((VVBUFSIZE >> 1) + resid) << 1; 614: len -= sizeof(struct vv_header); 615: 616: if ((addr->vvicsr & VV_DPR) || len > VVMRU || len <= 0) { 617: vvprintf("vv%d: len too long or short, \ 618: len = %d, vvicsr = %b\n", 619: unit, len, 0xffff&(addr->vvicsr), VV_IBITS); 620: goto dropit; 621: } 622: 623: /* check the protocol header version */ 624: if (vv->vh_version != RING_VERSION) { 625: vvprintf("vv%d: bad protocol header version %d\n", 626: unit, vv->vh_version & 0xff); 627: goto dropit; 628: } 629: 630: #define vvdataaddr(vv, off, type) ((type)(((caddr_t)((vv)+1)+(off)))) 631: if (vv->vh_type == RING_TRAILER ) { 632: off = ntohs((u_short)vv->vh_info); 633: if (off > VVMTU) { 634: vvprintf("vv%d: off > VVMTU, off = %d, vvicsr = %b\n", 635: unit, off, 0xffff&(addr->vvicsr), VV_IBITS); 636: goto dropit; 637: } 638: vv->vh_type = ntohs(*vvdataaddr(vv, off, u_short *)); 639: resid = ntohs(*(vvdataaddr(vv, off+sizeof(u_short), u_short *))); 640: if (off + resid > len) { 641: vvprintf("vv%d: trailer packet too short\n", unit); 642: vvprintf("vv%d: off = %d, resid = %d, vvicsr = %b\n", 643: unit, off, resid, 644: 0xffff&(addr->vvicsr), VV_IBITS); 645: goto dropit; 646: } 647: len = off + resid; 648: } else 649: off = 0; 650: 651: if (len == 0) { 652: vvprintf("vv%d: len is zero, vvicsr = %b\n", unit, 653: 0xffff&(addr->vvicsr), VV_IBITS); 654: goto dropit; 655: } 656: /* 657: * have to restore the mapping before manipulating mbufs because 658: * there may be mbufs in SEG5. save the 'type' and 'shost' then 659: * restore the mapping. 660: */ 661: type = vv->vh_type; 662: shost = vv->vh_shost; 663: restorseg5(save5); 664: m = if_rubaget(&vs->vs_ifuba, len, off, &vs->vs_if); 665: if (m == NULL) { 666: vvprintf("vv%d: if_rubaget() failed, vvicsr = %b\n", unit, 667: 0xffff&(addr->vvicsr), VV_IBITS); 668: goto dropit; 669: } 670: if (off) { 671: struct ifnet *ifp; 672: 673: ifp = *(mtod(m, struct ifnet **)); 674: m->m_off += 2 * sizeof (u_short); 675: m->m_len -= 2 * sizeof (u_short); 676: *(mtod(m, struct ifnet **)) = ifp; 677: } 678: 679: /* Keep track of source address of this packet */ 680: vs->vs_lastr = shost; 681: 682: /* 683: * Demultiplex on packet type 684: */ 685: switch (type) { 686: 687: #ifdef INET 688: case RING_IP: 689: schednetisr(NETISR_IP); 690: inq = &ipintrq; 691: break; 692: #endif 693: default: 694: vvprintf("vv%d: unknown pkt type 0x%x\n", unit, type); 695: m_freem(m); 696: goto setup; 697: } 698: s = splimp(); 699: if (IF_QFULL(inq)) { 700: IF_DROP(inq); 701: m_freem(m); 702: } else 703: IF_ENQUEUE(inq, m); 704: 705: splx(s); 706: /* 707: * Reset for the next packet. 708: */ 709: setup: 710: restorseg5(save5); 711: ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; 712: addr->vviba = (u_short) ubainfo; 713: addr->vviea = (u_short) (ubainfo >> 16); 714: addr->vviwc = -(VVBUFSIZE) >> 1; 715: addr->vvicsr = VV_HEN | VV_IEN | VV_DEN | VV_ENB; 716: return; 717: 718: /* 719: * Drop packet on floor -- count them!! 720: */ 721: dropit: 722: vs->vs_if.if_ierrors++; 723: goto setup; 724: } 725: 726: /* 727: * proNET output routine. 728: * Encapsulate a packet of type family for the local net. 729: * Use trailer local net encapsulation if enough data in first 730: * packet leaves a multiple of 512 bytes of data in remainder. 731: */ 732: vvoutput(ifp, m0, dst) 733: struct ifnet *ifp; 734: struct mbuf *m0; 735: struct sockaddr *dst; 736: { 737: register struct mbuf *m; 738: register struct vv_header *vv; 739: register int off; 740: register int unit; 741: register struct vvreg *addr; 742: register struct vv_softc *vs; 743: register int s; 744: int type, error; 745: u_long dest; 746: segm save5; 747: 748: saveseg5(save5); 749: m = m0; 750: unit = ifp->if_unit; 751: addr = (struct vvreg *)vvinfo[unit]->ui_addr; 752: vs = &vv_softc[unit]; 753: 754: /* 755: * Check to see if the input side has wedged. 756: * 757: * We are lower than device ipl when we enter this routine, 758: * so if the interface is ready with an input packet then 759: * an input interrupt must have slipped through the cracks. 760: * 761: * Avoid the race with an input interrupt by watching to see 762: * if any packets come in. 763: */ 764: s = vs->vs_if.if_ipackets; 765: if (addr->vvicsr & VV_RDY && s == vs->vs_if.if_ipackets) { 766: vvprintf("vv%d: lost a receive interrupt, icsr = %b\n", 767: unit, 0xffff&(addr->vvicsr), VV_IBITS); 768: s = splimp(); 769: vvrint(unit); 770: splx(s); 771: } 772: 773: switch (dst->sa_family) { 774: 775: #ifdef INET 776: case AF_INET: 777: if (in_broadcast(((struct sockaddr_in *)dst)->sin_addr)) 778: dest = VV_BROADCAST; 779: else 780: dest = in_lnaof(((struct sockaddr_in *)dst)->sin_addr); 781: /* Rene Nieuwboer reneni@psy.vu.nl suggests a 'dest &= 0xff;' at this point */ 782: /* dest is contrained in the 'if' a few lines down, i don't see why the & */ 783: #ifdef LOOPBACK 784: if (dest == vs->vs_host && (loif.if_flags & IFF_UP)) 785: return (looutput(&loif, m0, dst)); 786: #endif LOOPBACK 787: if (dest >= 0x100) { 788: error = EPERM; 789: goto bad; 790: } 791: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 792: /* 793: * Trailerize, if the configuration allows it. 794: * TODO: Need per host negotiation. 795: */ 796: if ((ifp->if_flags & IFF_NOTRAILERS) == 0) 797: if (off > 0 && (off & 0x1ff) == 0 && 798: m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 799: type = RING_TRAILER; 800: m->m_off -= 2 * sizeof (u_short); 801: m->m_len += 2 * sizeof (u_short); 802: *mtod(m, u_short *) = htons((short)RING_IP); 803: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 804: goto gottrailertype; 805: } 806: type = RING_IP; 807: off = 0; 808: goto gottype; 809: #endif 810: default: 811: printf("vv%d: can't handle af%d\n", unit, dst->sa_family); 812: error = EAFNOSUPPORT; 813: goto bad; 814: } 815: 816: gottrailertype: 817: /* 818: * Packet to be sent as trailer: move first packet 819: * (control information) to end of chain. 820: */ 821: while (m->m_next) 822: m = m->m_next; 823: m->m_next = m0; 824: m = m0->m_next; 825: m0->m_next = 0; 826: m0 = m; 827: gottype: 828: /* 829: * Add local net header. If no space in first mbuf, 830: * allocate another. 831: */ 832: if (m->m_off > MMAXOFF || 833: MMINOFF + sizeof (struct vv_header) > m->m_off) { 834: m = m_get(M_DONTWAIT, MT_HEADER); 835: if (m == NULL) { 836: error = ENOBUFS; 837: goto bad; 838: } 839: m->m_next = m0; 840: m->m_off = MMINOFF; 841: m->m_len = sizeof (struct vv_header); 842: } else { 843: m->m_off -= sizeof (struct vv_header); 844: m->m_len += sizeof (struct vv_header); 845: } 846: vv = mtod(m, struct vv_header *); 847: vv->vh_shost = vs->vs_host; 848: vv->vh_dhost = dest; 849: vv->vh_version = RING_VERSION; 850: vv->vh_type = type; 851: vv->vh_info = htons((u_short)off); 852: vvtracehdr("vo", vv); 853: 854: /* 855: * Queue message on interface, and start output if interface 856: * not yet active. 857: */ 858: s = splimp(); 859: if (IF_QFULL(&ifp->if_snd)) { 860: IF_DROP(&ifp->if_snd); 861: error = ENOBUFS; 862: goto qfull; 863: } 864: IF_ENQUEUE(&ifp->if_snd, m); 865: if (vs->vs_oactive == 0) 866: vvstart(unit); 867: splx(s); 868: return (0); 869: qfull: 870: m0 = m; 871: splx(s); 872: bad: 873: m_freem(m0); 874: return(error); 875: } 876: 877: /* 878: * Process an ioctl request. 879: */ 880: vvioctl(ifp, cmd, data) 881: register struct ifnet *ifp; 882: u_int cmd; 883: caddr_t data; 884: { 885: struct ifaddr *ifa = (struct ifaddr *) data; 886: int s = splimp(), error = 0; 887: 888: switch (cmd) { 889: 890: case SIOCSIFADDR: 891: ifp->if_flags |= IFF_UP; 892: if ((ifp->if_flags & IFF_RUNNING) == 0) 893: vvinit(ifp->if_unit); 894: /* 895: * Did self-test succeed? 896: */ 897: if ((ifp->if_flags & IFF_UP) == 0) 898: error = ENETDOWN; 899: /* 900: * Attempt to check agreement of protocol address 901: * and board address. 902: */ 903: switch (ifa->ifa_addr.sa_family) { 904: case AF_INET: 905: /* Rene Nieuwboer reneni@psy.vu.nl suggests a '& 0xff;' below */ 906: if ((u_short)(in_lnaof(IA_SIN(ifa)->sin_addr)) != 907: vv_softc[ifp->if_unit].vs_host) 908: error = EADDRNOTAVAIL; 909: break; 910: } 911: break; 912: 913: default: 914: error = EINVAL; 915: } 916: splx(s); 917: return (error); 918: } 919: 920: /* 921: * vvprt_hdr(s, v) print the local net header in "v" 922: * with title is "s" 923: */ 924: vvprt_hdr(s, v) 925: char *s; 926: register struct vv_header *v; 927: { 928: printf("%s: dsvti: 0x%x 0x%x 0x%x 0x%x 0x%x\n", 929: s, 930: 0xff & (int)(v->vh_dhost), 0xff & (int)(v->vh_shost), 931: 0xff & (int)(v->vh_version), 0xff & (int)(v->vh_type), 932: 0xffff & (int)(v->vh_info)); 933: } 934: #endif NVV