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