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