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