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