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