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