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