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