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