1 /* if_vv.c 6.3 83/12/22 */ 2 3 #include "vv.h" 4 5 /* 6 * Proteon 10 Meg Ring Driver. 7 * This device is called "vv" because its "real name", 8 * V2LNI won't work if shortened to the obvious "v2". 9 * Hence the subterfuge. 10 * 11 */ 12 #include "../machine/pte.h" 13 14 #include "../h/param.h" 15 #include "../h/systm.h" 16 #include "../h/mbuf.h" 17 #include "../h/buf.h" 18 #include "../h/protosw.h" 19 #include "../h/socket.h" 20 #include "../h/vmmac.h" 21 #include "../h/errno.h" 22 #include "../h/time.h" 23 #include "../h/kernel.h" 24 #include "../h/ioctl.h" 25 26 #include "../net/if.h" 27 #include "../net/netisr.h" 28 #include "../net/route.h" 29 30 #include "../netinet/in.h" 31 #include "../netinet/in_systm.h" 32 #include "../netinet/ip.h" 33 #include "../netinet/ip_var.h" 34 35 #include "../vax/mtpr.h" 36 #include "../vax/cpu.h" 37 38 #include "../vaxuba/ubareg.h" 39 #include "../vaxuba/ubavar.h" 40 41 #include "../vaxif/if_vv.h" 42 #include "../vaxif/if_uba.h" 43 44 /* 45 * N.B. - if WIRECENTER is defined wrong, it can well break 46 * the hardware!! 47 */ 48 #define WIRECENTER 49 50 #ifdef WIRECENTER 51 #define VV_CONF VV_HEN /* drive wire center relay */ 52 #else 53 #define VV_CONF VV_STE /* allow operation without wire center */ 54 #endif 55 56 #define VVMTU (1024+512) 57 #define VVMRU (1024+512+16) /* space for trailer */ 58 59 int vv_tracehdr = 0, /* 1 => trace headers (slowly!!) */ 60 vv_logreaderrors = 1; /* 1 => log all read errors */ 61 62 #define vvtracehdr if (vv_tracehdr) vvprt_hdr 63 64 int vvprobe(), vvattach(), vvrint(), vvxint(); 65 struct uba_device *vvinfo[NVV]; 66 u_short vvstd[] = { 0 }; 67 struct uba_driver vvdriver = 68 { vvprobe, 0, vvattach, 0, vvstd, "vv", vvinfo }; 69 #define VVUNIT(x) minor(x) 70 int vvinit(),vvioctl(),vvoutput(),vvreset(),vvsetaddr(); 71 72 /* 73 * Software status of each interface. 74 * 75 * Each interface is referenced by a network interface structure, 76 * vs_if, which the routing code uses to locate the interface. 77 * This structure contains the output queue for the interface, its address, ... 78 * We also have, for each interface, a UBA interface structure, which 79 * contains information about the UNIBUS resources held by the interface: 80 * map registers, buffered data paths, etc. Information is cached in this 81 * structure for use by the if_uba.c routines in running the interface 82 * efficiently. 83 */ 84 struct vv_softc { 85 struct ifnet vs_if; /* network-visible interface */ 86 struct ifuba vs_ifuba; /* UNIBUS resources */ 87 short vs_oactive; /* is output active */ 88 short vs_olen; /* length of last output */ 89 u_short vs_lastx; /* last destination address */ 90 short vs_tries; /* transmit current retry count */ 91 short vs_init; /* number of ring inits */ 92 short vs_nottaken; /* number of packets refused */ 93 } vv_softc[NVV]; 94 95 vvprobe(reg) 96 caddr_t reg; 97 { 98 register int br, cvec; 99 register struct vvreg *addr = (struct vvreg *)reg; 100 101 #ifdef lint 102 br = 0; cvec = br; br = cvec; 103 #endif 104 /* reset interface, enable, and wait till dust settles */ 105 addr->vvicsr = VV_RST; 106 addr->vvocsr = VV_RST; 107 DELAY(100000); 108 /* generate interrupt by doing 1 word DMA from 0 in uba space!! */ 109 addr->vvocsr = VV_IEN; /* enable interrupt */ 110 addr->vvoba = 0; /* low 16 bits */ 111 addr->vvoea = 0; /* extended bits */ 112 addr->vvowc = -1; /* for 1 word */ 113 addr->vvocsr |= VV_DEN; /* start the DMA */ 114 DELAY(100000); 115 addr->vvocsr = 0; 116 if (cvec && cvec != 0x200) 117 cvec -= 4; /* backup so vector => receive */ 118 return(1); 119 } 120 121 /* 122 * Interface exists: make available by filling in network interface 123 * record. System will initialize the interface when it is ready 124 * to accept packets. 125 */ 126 vvattach(ui) 127 struct uba_device *ui; 128 { 129 register struct vv_softc *vs; 130 131 vs = &vv_softc[ui->ui_unit]; 132 vs->vs_if.if_unit = ui->ui_unit; 133 vs->vs_if.if_name = "vv"; 134 vs->vs_if.if_mtu = VVMTU; 135 vs->vs_if.if_init = vvinit; 136 vs->vs_if.if_ioctl = vvioctl; 137 vs->vs_if.if_output = vvoutput; 138 vs->vs_if.if_reset = vvreset; 139 vs->vs_ifuba.ifu_flags = UBA_CANTWAIT | UBA_NEEDBDP | UBA_NEED16; 140 #if defined(VAX750) 141 /* don't chew up 750 bdp's */ 142 if (cpu == VAX_750 && ui->ui_unit > 0) 143 vs->vs_ifuba.ifu_flags &= ~UBA_NEEDBDP; 144 #endif 145 if_attach(&vs->vs_if); 146 } 147 148 /* 149 * Reset of interface after UNIBUS reset. 150 * If interface is on specified uba, reset its state. 151 */ 152 vvreset(unit, uban) 153 int unit, uban; 154 { 155 register struct uba_device *ui; 156 157 if (unit >= NVV || (ui = vvinfo[unit]) == 0 || ui->ui_alive == 0 || 158 ui->ui_ubanum != uban) 159 return; 160 printf(" vv%d", unit); 161 vvinit(unit); 162 } 163 164 /* 165 * Initialization of interface; clear recorded pending 166 * operations, and reinitialize UNIBUS usage. 167 */ 168 vvinit(unit) 169 int unit; 170 { 171 register struct vv_softc *vs; 172 register struct uba_device *ui; 173 register struct vvreg *addr; 174 struct sockaddr_in *sin; 175 int ubainfo, s; 176 177 vs = &vv_softc[unit]; 178 ui = vvinfo[unit]; 179 sin = (struct sockaddr_in *)&vs->vs_if.if_addr; 180 /* 181 * If the network number is still zero, we've been 182 * called too soon. 183 */ 184 if (in_netof(sin->sin_addr) == 0) 185 return; 186 addr = (struct vvreg *)ui->ui_addr; 187 if (if_ubainit(&vs->vs_ifuba, ui->ui_ubanum, 188 sizeof (struct vv_header), (int)btoc(VVMTU)) == 0) { 189 printf("vv%d: can't initialize\n", unit); 190 vs->vs_if.if_flags &= ~IFF_UP; 191 return; 192 } 193 /* 194 * Now that the uba is set up, figure out our address and 195 * update complete our host address. 196 */ 197 vs->vs_if.if_host[0] = vvidentify(unit); 198 printf("vv%d: host %d\n", unit, vs->vs_if.if_host[0]); 199 sin->sin_addr = if_makeaddr(vs->vs_if.if_net, vs->vs_if.if_host[0]); 200 /* 201 * Reset the interface, and join the ring 202 */ 203 addr->vvocsr = VV_RST | VV_CPB; /* clear packet buffer */ 204 addr->vvicsr = VV_RST | VV_CONF; /* close logical relay */ 205 DELAY(500000); /* let contacts settle */ 206 vs->vs_init = 0; 207 vs->vs_nottaken = 0; 208 /* 209 * Hang a receive and start any 210 * pending writes by faking a transmit complete. 211 */ 212 s = splimp(); 213 ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; 214 addr->vviba = (u_short)ubainfo; 215 addr->vviea = (u_short)(ubainfo >> 16); 216 addr->vviwc = -(sizeof (struct vv_header) + VVMTU) >> 1; 217 addr->vvicsr = VV_IEN | VV_CONF | VV_DEN | VV_ENB; 218 vs->vs_oactive = 1; 219 vs->vs_if.if_flags |= IFF_UP | IFF_RUNNING; 220 vvxint(unit); 221 splx(s); 222 if_rtinit(&vs->vs_if, RTF_UP); 223 } 224 225 /* 226 * Return our host address. 227 */ 228 vvidentify(unit) 229 int unit; 230 { 231 register struct vv_softc *vs; 232 register struct uba_device *ui; 233 register struct vvreg *addr; 234 struct mbuf *m; 235 struct vv_header *v; 236 int ubainfo, attempts, waitcount; 237 238 /* 239 * Build a multicast message to identify our address 240 */ 241 vs = &vv_softc[unit]; 242 ui = vvinfo[unit]; 243 addr = (struct vvreg *)ui->ui_addr; 244 attempts = 0; /* total attempts, including bad msg type */ 245 m = m_get(M_DONTWAIT, MT_HEADER); 246 if (m == NULL) 247 return (0); 248 m->m_next = 0; 249 m->m_off = MMINOFF; 250 m->m_len = sizeof(struct vv_header); 251 v = mtod(m, struct vv_header *); 252 v->vh_dhost = VV_BROADCAST; /* multicast destination address */ 253 v->vh_shost = 0; /* will be overwritten with ours */ 254 v->vh_version = RING_VERSION; 255 v->vh_type = RING_WHOAMI; 256 v->vh_info = 0; 257 /* map xmit message into uba */ 258 vs->vs_olen = if_wubaput(&vs->vs_ifuba, m); 259 if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP) 260 UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_w.ifrw_bdp); 261 /* 262 * Reset interface, establish Digital Loopback Mode, and 263 * send the multicast (to myself) with Input Copy enabled. 264 */ 265 retry: 266 ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; 267 addr->vvicsr = VV_RST; 268 addr->vviba = (u_short) ubainfo; 269 addr->vviea = (u_short) (ubainfo >> 16); 270 addr->vviwc = -(sizeof (struct vv_header) + VVMTU) >> 1; 271 addr->vvicsr = VV_STE | VV_DEN | VV_ENB | VV_LPB; 272 273 /* let flag timers fire so ring will initialize */ 274 DELAY(2000000); /* about 2 SECONDS on a 780!! */ 275 276 addr->vvocsr = VV_RST | VV_CPB; /* clear packet buffer */ 277 ubainfo = vs->vs_ifuba.ifu_w.ifrw_info; 278 addr->vvoba = (u_short) ubainfo; 279 addr->vvoea = (u_short) (ubainfo >> 16); 280 addr->vvowc = -((vs->vs_olen + 1) >> 1); 281 addr->vvocsr = VV_CPB | VV_DEN | VV_INR | VV_ENB; 282 /* 283 * Wait for receive side to finish. 284 * Extract source address (which will our own), 285 * and post to interface structure. 286 */ 287 DELAY(10000); 288 for (waitcount = 0; (addr->vvicsr & VV_RDY) == 0; waitcount++) { 289 if (waitcount < 10) { 290 DELAY(1000); 291 continue; 292 } 293 if (attempts++ >= 10) { 294 printf("vv%d: can't initialize\n", unit); 295 printf("vvinit loopwait: icsr = %b\n", 296 0xffff&(addr->vvicsr), VV_IBITS); 297 vs->vs_if.if_flags &= ~IFF_UP; 298 return (0); 299 } 300 goto retry; 301 } 302 if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP) 303 UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_w.ifrw_bdp); 304 if (vs->vs_ifuba.ifu_xtofree) 305 m_freem(vs->vs_ifuba.ifu_xtofree); 306 if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP) 307 UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_r.ifrw_bdp); 308 m = if_rubaget(&vs->vs_ifuba, sizeof(struct vv_header), 0); 309 if (m != NULL) 310 m_freem(m); 311 /* 312 * Check message type before we believe the source host address 313 */ 314 v = (struct vv_header *)(vs->vs_ifuba.ifu_r.ifrw_addr); 315 if (v->vh_type != RING_WHOAMI) 316 goto retry; 317 return(v->vh_shost); 318 } 319 320 /* 321 * Start or restart output on interface. 322 * If interface is active, this is a retransmit, so just 323 * restuff registers and go. 324 * If interface is not already active, get another datagram 325 * to send off of the interface queue, and map it to the interface 326 * before starting the output. 327 */ 328 vvstart(dev) 329 dev_t dev; 330 { 331 int unit = VVUNIT(dev); 332 struct uba_device *ui; 333 register struct vv_softc *vs; 334 register struct vvreg *addr; 335 struct mbuf *m; 336 int ubainfo; 337 int dest; 338 339 ui = vvinfo[unit]; 340 vs = &vv_softc[unit]; 341 if (vs->vs_oactive) 342 goto restart; 343 /* 344 * Not already active: dequeue another request 345 * and map it to the UNIBUS. If no more requests, 346 * just return. 347 */ 348 IF_DEQUEUE(&vs->vs_if.if_snd, m); 349 if (m == NULL) { 350 vs->vs_oactive = 0; 351 return; 352 } 353 dest = mtod(m, struct vv_header *)->vh_dhost; 354 vs->vs_olen = if_wubaput(&vs->vs_ifuba, m); 355 vs->vs_lastx = dest; 356 restart: 357 /* 358 * Have request mapped to UNIBUS for transmission. 359 * Purge any stale data from this BDP, and start the otput. 360 */ 361 /* 362 * The following test is questionable and isn't done in 363 * the en driver... 364 */ 365 if (vs->vs_olen > VVMTU + sizeof (struct vv_header)) { 366 printf("vv%d vs_olen: %d > VVMTU\n", unit, vs->vs_olen); 367 panic("vvdriver vs_olen botch"); 368 } 369 if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP) 370 UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_w.ifrw_bdp); 371 addr = (struct vvreg *)ui->ui_addr; 372 ubainfo = vs->vs_ifuba.ifu_w.ifrw_info; 373 addr->vvoba = (u_short) ubainfo; 374 addr->vvoea = (u_short) (ubainfo >> 16); 375 addr->vvowc = -((vs->vs_olen + 1) >> 1); 376 addr->vvocsr = VV_IEN | VV_CPB | VV_DEN | VV_INR | VV_ENB; 377 vs->vs_oactive = 1; 378 } 379 380 /* 381 * VVLNI transmit interrupt 382 * Start another output if more data to send. 383 */ 384 vvxint(unit) 385 int unit; 386 { 387 register struct uba_device *ui; 388 register struct vv_softc *vs; 389 register struct vvreg *addr; 390 register int oc; 391 392 ui = vvinfo[unit]; 393 vs = &vv_softc[unit]; 394 addr = (struct vvreg *)ui->ui_addr; 395 oc = 0xffff & (addr->vvocsr); 396 if (vs->vs_oactive == 0) { 397 printf("vv%d: stray interrupt vvocsr = %b\n", unit, 398 oc, VV_OBITS); 399 return; 400 } 401 if (oc & (VV_OPT | VV_RFS)) { 402 vs->vs_if.if_collisions++; 403 if (vs->vs_tries++ < VVRETRY) { 404 if (oc & VV_OPT) 405 vs->vs_init++; 406 if (oc & VV_RFS) 407 vs->vs_nottaken++; 408 vvstart(unit); /* restart this message */ 409 return; 410 } 411 if (oc & VV_OPT) 412 printf("vv%d: output timeout\n", unit); 413 } 414 vs->vs_if.if_opackets++; 415 vs->vs_oactive = 0; 416 vs->vs_tries = 0; 417 if (oc & VVXERR) { 418 vs->vs_if.if_oerrors++; 419 printf("vv%d: error vvocsr = %b\n", unit, 0xffff & oc, 420 VV_OBITS); 421 } 422 if (vs->vs_ifuba.ifu_xtofree) { 423 m_freem(vs->vs_ifuba.ifu_xtofree); 424 vs->vs_ifuba.ifu_xtofree = 0; 425 } 426 if (vs->vs_if.if_snd.ifq_head == 0) { 427 vs->vs_lastx = 256; /* an invalid address */ 428 return; 429 } 430 vvstart(unit); 431 } 432 433 /* 434 * V2lni interface receiver interrupt. 435 * If input error just drop packet. 436 * Otherwise purge input buffered data path and examine 437 * packet to determine type. If can't determine length 438 * from type, then have to drop packet. Otherwise decapsulate 439 * packet based on type and pass to type specific higher-level 440 * input routine. 441 */ 442 vvrint(unit) 443 int unit; 444 { 445 register struct vv_softc *vs; 446 struct vvreg *addr; 447 register struct vv_header *vv; 448 register struct ifqueue *inq; 449 struct mbuf *m; 450 int ubainfo, len, off; 451 short resid; 452 453 vs = &vv_softc[unit]; 454 addr = (struct vvreg *)vvinfo[unit]->ui_addr; 455 vs->vs_if.if_ipackets++; 456 /* 457 * Purge BDP; drop if input error indicated. 458 */ 459 if (vs->vs_ifuba.ifu_flags & UBA_NEEDBDP) 460 UBAPURGE(vs->vs_ifuba.ifu_uba, vs->vs_ifuba.ifu_r.ifrw_bdp); 461 if (addr->vvicsr & VVRERR) { 462 if (vs->vs_if.if_flags & IFF_DEBUG && vv_logreaderrors) 463 printf("vv%d: error vvicsr = %b\n", unit, 464 0xffff&(addr->vvicsr), VV_IBITS); 465 goto dropit; 466 } 467 468 /* 469 * Get packet length from word count residue 470 * 471 * Compute header offset if trailer protocol 472 * 473 * Pull packet off interface. Off is nonzero if packet 474 * has trailing header; if_rubaget will then force this header 475 * information to be at the front. The vh_info field 476 * carries the offset to the trailer data in trailer 477 * format packets. 478 */ 479 vv = (struct vv_header *)(vs->vs_ifuba.ifu_r.ifrw_addr); 480 vvtracehdr("vi", vv); 481 resid = addr->vviwc; 482 if (resid) 483 resid |= 0176000; /* ugly!!!! */ 484 len = (((sizeof (struct vv_header) + VVMRU) >> 1) + resid) << 1; 485 len -= sizeof(struct vv_header); 486 if (len > VVMRU || len <= 0) 487 goto dropit; 488 #define vvdataaddr(vv, off, type) ((type)(((caddr_t)((vv)+1)+(off)))) 489 if (vv->vh_type >= RING_IPTrailer && 490 vv->vh_type < RING_IPTrailer+RING_IPNTrailer) { 491 off = (vv->vh_type - RING_IPTrailer) * 512; 492 if (off > VVMTU) 493 goto dropit; 494 vv->vh_type = *vvdataaddr(vv, off, u_short *); 495 resid = *(vvdataaddr(vv, off+2, u_short *)); 496 if (off + resid > len) 497 goto dropit; 498 len = off + resid; 499 } else 500 off = 0; 501 if (len == 0) 502 goto dropit; 503 m = if_rubaget(&vs->vs_ifuba, len, off); 504 if (m == NULL) 505 goto dropit; 506 if (off) { 507 m->m_off += 2 * sizeof(u_short); 508 m->m_len -= 2 * sizeof(u_short); 509 } 510 511 /* 512 * Demultiplex on packet type 513 */ 514 switch (vv->vh_type) { 515 516 #ifdef INET 517 case RING_IP: 518 schednetisr(NETISR_IP); 519 inq = &ipintrq; 520 break; 521 #endif 522 default: 523 printf("vv%d: unknown pkt type 0x%x\n", unit, vv->vh_type); 524 m_freem(m); 525 goto setup; 526 } 527 if (IF_QFULL(inq)) { 528 IF_DROP(inq); 529 m_freem(m); 530 } else 531 IF_ENQUEUE(inq, m); 532 533 /* 534 * Reset for the next packet. 535 */ 536 setup: 537 ubainfo = vs->vs_ifuba.ifu_r.ifrw_info; 538 addr->vviba = (u_short) ubainfo; 539 addr->vviea = (u_short) (ubainfo >> 16); 540 addr->vviwc = -(sizeof (struct vv_header) + VVMTU) >> 1; 541 addr->vvicsr = VV_RST | VV_CONF; 542 addr->vvicsr |= VV_IEN | VV_DEN | VV_ENB; 543 return; 544 545 /* 546 * Drop packet on floor -- count them!! 547 */ 548 dropit: 549 vs->vs_if.if_ierrors++; 550 if (vs->vs_if.if_flags & IFF_DEBUG && vv_logreaderrors) 551 printf("vv%d: error vvicsr = %b\n", unit, 552 0xffff&(addr->vvicsr), VV_IBITS); 553 goto setup; 554 } 555 556 /* 557 * V2lni output routine. 558 * Encapsulate a packet of type family for the local net. 559 * Use trailer local net encapsulation if enough data in first 560 * packet leaves a multiple of 512 bytes of data in remainder. 561 */ 562 vvoutput(ifp, m0, dst) 563 struct ifnet *ifp; 564 struct mbuf *m0; 565 struct sockaddr *dst; 566 { 567 register struct mbuf *m = m0; 568 register struct vv_header *vv; 569 register int off; 570 int type, dest, s, error; 571 572 switch (dst->sa_family) { 573 574 #ifdef INET 575 case AF_INET: 576 dest = ((struct sockaddr_in *)dst)->sin_addr.s_addr; 577 if ((dest = in_lnaof(*((struct in_addr *)&dest))) >= 0x100) { 578 error = EPERM; 579 goto bad; 580 } 581 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 582 /* Need per host negotiation. */ 583 if ((ifp->if_flags & IFF_NOTRAILERS) == 0) 584 if (off > 0 && (off & 0x1ff) == 0 && 585 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 586 type = RING_IPTrailer + (off>>9); 587 m->m_off -= 2 * sizeof (u_short); 588 m->m_len += 2 * sizeof (u_short); 589 *mtod(m, u_short *) = RING_IP; 590 *(mtod(m, u_short *) + 1) = m->m_len; 591 goto gottrailertype; 592 } 593 type = RING_IP; 594 off = 0; 595 goto gottype; 596 #endif 597 default: 598 printf("vv%d: can't handle af%d\n", ifp->if_unit, 599 dst->sa_family); 600 error = EAFNOSUPPORT; 601 goto bad; 602 } 603 604 gottrailertype: 605 /* 606 * Packet to be sent as trailer: move first packet 607 * (control information) to end of chain. 608 */ 609 while (m->m_next) 610 m = m->m_next; 611 m->m_next = m0; 612 m = m0->m_next; 613 m0->m_next = 0; 614 m0 = m; 615 gottype: 616 /* 617 * Add local net header. If no space in first mbuf, 618 * allocate another. 619 */ 620 if (m->m_off > MMAXOFF || 621 MMINOFF + sizeof (struct vv_header) > m->m_off) { 622 m = m_get(M_DONTWAIT, MT_HEADER); 623 if (m == NULL) { 624 error = ENOBUFS; 625 goto bad; 626 } 627 m->m_next = m0; 628 m->m_off = MMINOFF; 629 m->m_len = sizeof (struct vv_header); 630 } else { 631 m->m_off -= sizeof (struct vv_header); 632 m->m_len += sizeof (struct vv_header); 633 } 634 vv = mtod(m, struct vv_header *); 635 vv->vh_shost = ifp->if_host[0]; 636 /* Map the destination address if it's a broadcast */ 637 if ((vv->vh_dhost = dest) == INADDR_ANY) 638 vv->vh_dhost = VV_BROADCAST; 639 vv->vh_version = RING_VERSION; 640 vv->vh_type = type; 641 vv->vh_info = off; 642 vvtracehdr("vo", vv); 643 644 /* 645 * Queue message on interface, and start output if interface 646 * not yet active. 647 */ 648 s = splimp(); 649 if (IF_QFULL(&ifp->if_snd)) { 650 IF_DROP(&ifp->if_snd); 651 error = ENOBUFS; 652 goto qfull; 653 } 654 IF_ENQUEUE(&ifp->if_snd, m); 655 if (vv_softc[ifp->if_unit].vs_oactive == 0) 656 vvstart(ifp->if_unit); 657 splx(s); 658 return (0); 659 qfull: 660 m0 = m; 661 splx(s); 662 bad: 663 m_freem(m0); 664 return(error); 665 } 666 667 /* 668 * Process an ioctl request. 669 */ 670 vvioctl(ifp, cmd, data) 671 register struct ifnet *ifp; 672 int cmd; 673 caddr_t data; 674 { 675 struct ifreq *ifr; 676 int s, error; 677 678 ifr = (struct ifreq *)data; 679 error = 0; 680 s = splimp(); 681 switch (cmd) { 682 683 case SIOCSIFADDR: 684 /* too difficult to change addr while running */ 685 if ((ifp->if_flags & IFF_RUNNING) == 0) { 686 vvsetaddr(ifp, (struct sockaddr_in *)&ifr->ifr_addr); 687 vvinit(ifp->if_unit); 688 } else 689 error = EINVAL; 690 break; 691 692 default: 693 error = EINVAL; 694 } 695 splx(s); 696 return (error); 697 } 698 699 /* 700 * Set up the address for this interface. We use the network number 701 * from the passed address and an invalid host number because vvinit() 702 * is smart enough to figure out the host number out. 703 */ 704 vvsetaddr(ifp, sin) 705 register struct ifnet *ifp; 706 register struct sockaddr_in *sin; 707 { 708 ifp->if_net = in_netof(sin->sin_addr); 709 ifp->if_host[0] = 256; /* an invalid host number */ 710 sin = (struct sockaddr_in *)&ifp->if_addr; 711 sin->sin_family = AF_INET; 712 sin->sin_addr = if_makeaddr(ifp->if_net, ifp->if_host[0]); 713 sin = (struct sockaddr_in *)&ifp->if_broadaddr; 714 sin->sin_family = AF_INET; 715 sin->sin_addr = if_makeaddr(ifp->if_net, INADDR_ANY); 716 ifp->if_flags |= IFF_BROADCAST; 717 } 718 719 /* 720 * vvprt_hdr(s, v) print the local net header in "v" 721 * with title is "s" 722 */ 723 vvprt_hdr(s, v) 724 char *s; 725 register struct vv_header *v; 726 { 727 printf("%s: dsvti: 0x%x 0x%x 0x%x 0x%x 0x%x\n", 728 s, 729 0xff & (int)(v->vh_dhost), 0xff & (int)(v->vh_shost), 730 0xff & (int)(v->vh_version), 0xff & (int)(v->vh_type), 731 0xffff & (int)(v->vh_info)); 732 } 733 734 #ifdef notdef 735 /* 736 * print "l" hex bytes starting at "s" 737 */ 738 vvprt_hex(s, l) 739 char *s; 740 int l; 741 { 742 register int i; 743 register int z; 744 745 for (i=0 ; i < l; i++) { 746 z = 0xff & (int)(*(s + i)); 747 printf("%c%c ", 748 "0123456789abcdef"[(z >> 4) & 0x0f], 749 "0123456789abcdef"[z & 0x0f] 750 ); 751 } 752 } 753 #endif 754