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