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