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