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