1 /* 2 * Copyright (c) 1982 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)if_il.c 6.10 (Berkeley) 10/24/85 7 */ 8 9 #include "il.h" 10 #if NIL > 0 11 12 /* 13 * Interlan Ethernet Communications Controller interface 14 */ 15 #include "../machine/pte.h" 16 17 #include "param.h" 18 #include "systm.h" 19 #include "mbuf.h" 20 #include "buf.h" 21 #include "protosw.h" 22 #include "socket.h" 23 #include "vmmac.h" 24 #include "ioctl.h" 25 #include "errno.h" 26 27 #include "../net/if.h" 28 #include "../net/netisr.h" 29 #include "../net/route.h" 30 31 #ifdef BBNNET 32 #define INET 33 #endif 34 #ifdef INET 35 #include "../netinet/in.h" 36 #include "../netinet/in_systm.h" 37 #include "../netinet/in_var.h" 38 #include "../netinet/ip.h" 39 #include "../netinet/if_ether.h" 40 #endif 41 42 #ifdef PUP 43 #include "../netpup/pup.h" 44 #endif 45 46 #ifdef NS 47 #include "../netns/ns.h" 48 #include "../netns/ns_if.h" 49 #endif 50 51 #include "../vax/cpu.h" 52 #include "../vax/mtpr.h" 53 #include "if_il.h" 54 #include "if_ilreg.h" 55 #include "if_uba.h" 56 #include "../vaxuba/ubareg.h" 57 #include "../vaxuba/ubavar.h" 58 59 int ilprobe(), ilattach(), ilrint(), ilcint(); 60 struct uba_device *ilinfo[NIL]; 61 u_short ilstd[] = { 0 }; 62 struct uba_driver ildriver = 63 { ilprobe, 0, ilattach, 0, ilstd, "il", ilinfo }; 64 #define ILUNIT(x) minor(x) 65 int ilinit(),iloutput(),ilioctl(),ilreset(),ilwatch(); 66 67 /* 68 * Ethernet software status per interface. 69 * 70 * Each interface is referenced by a network interface structure, 71 * is_if, which the routing code uses to locate the interface. 72 * This structure contains the output queue for the interface, its address, ... 73 * We also have, for each interface, a UBA interface structure, which 74 * contains information about the UNIBUS resources held by the interface: 75 * map registers, buffered data paths, etc. Information is cached in this 76 * structure for use by the if_uba.c routines in running the interface 77 * efficiently. 78 */ 79 struct il_softc { 80 struct arpcom is_ac; /* Ethernet common part */ 81 #define is_if is_ac.ac_if /* network-visible interface */ 82 #define is_addr is_ac.ac_enaddr /* hardware Ethernet address */ 83 struct ifuba is_ifuba; /* UNIBUS resources */ 84 int is_flags; 85 #define ILF_OACTIVE 0x1 /* output is active */ 86 #define ILF_RCVPENDING 0x2 /* start rcv in ilcint */ 87 #define ILF_STATPENDING 0x4 /* stat cmd pending */ 88 short is_lastcmd; /* can't read csr, so must save it */ 89 short is_scaninterval; /* interval of stat collection */ 90 #define ILWATCHINTERVAL 60 /* once every 60 seconds */ 91 struct il_stats is_stats; /* holds on-board statistics */ 92 struct il_stats is_sum; /* summation over time */ 93 int is_ubaddr; /* mapping registers of is_stats */ 94 } il_softc[NIL]; 95 96 ilprobe(reg) 97 caddr_t reg; 98 { 99 register int br, cvec; /* r11, r10 value-result */ 100 register struct ildevice *addr = (struct ildevice *)reg; 101 register i; 102 103 #ifdef lint 104 br = 0; cvec = br; br = cvec; 105 i = 0; ilrint(i); ilcint(i); ilwatch(i); 106 #endif 107 108 addr->il_csr = ILC_OFFLINE|IL_CIE; 109 DELAY(100000); 110 i = addr->il_csr; /* clear CDONE */ 111 if (cvec > 0 && cvec != 0x200) 112 cvec -= 4; 113 return (1); 114 } 115 116 /* 117 * Interface exists: make available by filling in network interface 118 * record. System will initialize the interface when it is ready 119 * to accept packets. A STATUS command is done to get the ethernet 120 * address and other interesting data. 121 */ 122 ilattach(ui) 123 struct uba_device *ui; 124 { 125 register struct il_softc *is = &il_softc[ui->ui_unit]; 126 register struct ifnet *ifp = &is->is_if; 127 register struct ildevice *addr = (struct ildevice *)ui->ui_addr; 128 129 ifp->if_unit = ui->ui_unit; 130 ifp->if_name = "il"; 131 ifp->if_mtu = ETHERMTU; 132 ifp->if_flags = IFF_BROADCAST; 133 134 /* 135 * Reset the board and map the statistics 136 * buffer onto the Unibus. 137 */ 138 addr->il_csr = ILC_RESET; 139 while ((addr->il_csr&IL_CDONE) == 0) 140 ; 141 if (addr->il_csr&IL_STATUS) 142 printf("il%d: reset failed, csr=%b\n", ui->ui_unit, 143 addr->il_csr, IL_BITS); 144 145 is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats, 146 sizeof (struct il_stats), 0); 147 addr->il_bar = is->is_ubaddr & 0xffff; 148 addr->il_bcr = sizeof (struct il_stats); 149 addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT; 150 while ((addr->il_csr&IL_CDONE) == 0) 151 ; 152 if (addr->il_csr&IL_STATUS) 153 printf("il%d: status failed, csr=%b\n", ui->ui_unit, 154 addr->il_csr, IL_BITS); 155 ubarelse(ui->ui_ubanum, &is->is_ubaddr); 156 #ifdef notdef 157 printf("il%d: addr=%x:%x:%x:%x:%x:%x module=%s firmware=%s\n", 158 ui->ui_unit, 159 is->is_stats.ils_addr[0]&0xff, is->is_stats.ils_addr[1]&0xff, 160 is->is_stats.ils_addr[2]&0xff, is->is_stats.ils_addr[3]&0xff, 161 is->is_stats.ils_addr[4]&0xff, is->is_stats.ils_addr[5]&0xff, 162 is->is_stats.ils_module, is->is_stats.ils_firmware); 163 #endif 164 bcopy((caddr_t)is->is_stats.ils_addr, (caddr_t)is->is_addr, 165 sizeof (is->is_addr)); 166 ifp->if_init = ilinit; 167 ifp->if_output = iloutput; 168 ifp->if_ioctl = ilioctl; 169 ifp->if_reset = ilreset; 170 is->is_ifuba.ifu_flags = UBA_CANTWAIT; 171 #ifdef notdef 172 is->is_ifuba.ifu_flags |= UBA_NEEDBDP; 173 #endif 174 if_attach(ifp); 175 } 176 177 /* 178 * Reset of interface after UNIBUS reset. 179 * If interface is on specified uba, reset its state. 180 */ 181 ilreset(unit, uban) 182 int unit, uban; 183 { 184 register struct uba_device *ui; 185 186 if (unit >= NIL || (ui = ilinfo[unit]) == 0 || ui->ui_alive == 0 || 187 ui->ui_ubanum != uban) 188 return; 189 printf(" il%d", unit); 190 ilinit(unit); 191 } 192 193 /* 194 * Initialization of interface; clear recorded pending 195 * operations, and reinitialize UNIBUS usage. 196 */ 197 ilinit(unit) 198 int unit; 199 { 200 register struct il_softc *is = &il_softc[unit]; 201 register struct uba_device *ui = ilinfo[unit]; 202 register struct ildevice *addr; 203 register struct ifnet *ifp = &is->is_if; 204 int s; 205 206 /* not yet, if address still unknown */ 207 if (ifp->if_addrlist == (struct ifaddr *)0) 208 return; 209 210 if (ifp->if_flags & IFF_RUNNING) 211 return; 212 if (if_ubainit(&is->is_ifuba, ui->ui_ubanum, 213 sizeof (struct il_rheader), (int)btoc(ETHERMTU)) == 0) { 214 printf("il%d: can't initialize\n", unit); 215 is->is_if.if_flags &= ~IFF_UP; 216 return; 217 } 218 is->is_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&is->is_stats, 219 sizeof (struct il_stats), 0); 220 ifp->if_watchdog = ilwatch; 221 is->is_scaninterval = ILWATCHINTERVAL; 222 ifp->if_timer = is->is_scaninterval; 223 addr = (struct ildevice *)ui->ui_addr; 224 225 /* 226 * Turn off source address insertion (it's faster this way), 227 * and set board online. Former doesn't work if board is 228 * already online (happens on ubareset), so we put it offline 229 * first. 230 */ 231 s = splimp(); 232 addr->il_csr = ILC_OFFLINE; 233 while ((addr->il_csr & IL_CDONE) == 0) 234 ; 235 addr->il_csr = ILC_CISA; 236 while ((addr->il_csr & IL_CDONE) == 0) 237 ; 238 /* 239 * Set board online. 240 * Hang receive buffer and start any pending 241 * writes by faking a transmit complete. 242 * Receive bcr is not a muliple of 4 so buffer 243 * chaining can't happen. 244 */ 245 addr->il_csr = ILC_ONLINE; 246 while ((addr->il_csr & IL_CDONE) == 0) 247 ; 248 addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; 249 addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; 250 addr->il_csr = 251 ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; 252 while ((addr->il_csr & IL_CDONE) == 0) 253 ; 254 is->is_flags = ILF_OACTIVE; 255 is->is_if.if_flags |= IFF_RUNNING; 256 is->is_lastcmd = 0; 257 ilcint(unit); 258 splx(s); 259 } 260 261 /* 262 * Start output on interface. 263 * Get another datagram to send off of the interface queue, 264 * and map it to the interface before starting the output. 265 */ 266 ilstart(dev) 267 dev_t dev; 268 { 269 int unit = ILUNIT(dev), len; 270 struct uba_device *ui = ilinfo[unit]; 271 register struct il_softc *is = &il_softc[unit]; 272 register struct ildevice *addr; 273 struct mbuf *m; 274 short csr; 275 276 IF_DEQUEUE(&is->is_if.if_snd, m); 277 addr = (struct ildevice *)ui->ui_addr; 278 if (m == 0) { 279 if ((is->is_flags & ILF_STATPENDING) == 0) 280 return; 281 addr->il_bar = is->is_ubaddr & 0xffff; 282 addr->il_bcr = sizeof (struct il_stats); 283 csr = ((is->is_ubaddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE; 284 is->is_flags &= ~ILF_STATPENDING; 285 goto startcmd; 286 } 287 len = if_wubaput(&is->is_ifuba, m); 288 /* 289 * Ensure minimum packet length. 290 * This makes the safe assumtion that there are no virtual holes 291 * after the data. 292 * For security, it might be wise to zero out the added bytes, 293 * but we're mainly interested in speed at the moment. 294 */ 295 if (len - sizeof(struct ether_header) < ETHERMIN) 296 len = ETHERMIN + sizeof(struct ether_header); 297 if (is->is_ifuba.ifu_flags & UBA_NEEDBDP) 298 UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp); 299 addr->il_bar = is->is_ifuba.ifu_w.ifrw_info & 0xffff; 300 addr->il_bcr = len; 301 csr = 302 ((is->is_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE; 303 304 startcmd: 305 is->is_lastcmd = csr & IL_CMD; 306 addr->il_csr = csr; 307 is->is_flags |= ILF_OACTIVE; 308 } 309 310 /* 311 * Command done interrupt. 312 */ 313 ilcint(unit) 314 int unit; 315 { 316 register struct il_softc *is = &il_softc[unit]; 317 struct uba_device *ui = ilinfo[unit]; 318 register struct ildevice *addr = (struct ildevice *)ui->ui_addr; 319 short csr; 320 321 if ((is->is_flags & ILF_OACTIVE) == 0) { 322 printf("il%d: stray xmit interrupt, csr=%b\n", unit, 323 addr->il_csr, IL_BITS); 324 return; 325 } 326 327 csr = addr->il_csr; 328 /* 329 * Hang receive buffer if it couldn't 330 * be done earlier (in ilrint). 331 */ 332 if (is->is_flags & ILF_RCVPENDING) { 333 addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; 334 addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; 335 addr->il_csr = 336 ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; 337 while ((addr->il_csr & IL_CDONE) == 0) 338 ; 339 is->is_flags &= ~ILF_RCVPENDING; 340 } 341 is->is_flags &= ~ILF_OACTIVE; 342 csr &= IL_STATUS; 343 switch (is->is_lastcmd) { 344 345 case ILC_XMIT: 346 is->is_if.if_opackets++; 347 if (csr > ILERR_RETRIES) 348 is->is_if.if_oerrors++; 349 break; 350 351 case ILC_STAT: 352 if (csr == ILERR_SUCCESS) 353 iltotal(is); 354 break; 355 } 356 if (is->is_ifuba.ifu_xtofree) { 357 m_freem(is->is_ifuba.ifu_xtofree); 358 is->is_ifuba.ifu_xtofree = 0; 359 } 360 ilstart(unit); 361 } 362 363 /* 364 * Ethernet interface receiver interrupt. 365 * If input error just drop packet. 366 * Otherwise purge input buffered data path and examine 367 * packet to determine type. If can't determine length 368 * from type, then have to drop packet. Othewise decapsulate 369 * packet based on type and pass to type specific higher-level 370 * input routine. 371 */ 372 ilrint(unit) 373 int unit; 374 { 375 register struct il_softc *is = &il_softc[unit]; 376 struct ildevice *addr = (struct ildevice *)ilinfo[unit]->ui_addr; 377 register struct il_rheader *il; 378 struct mbuf *m; 379 int len, off, resid, s; 380 register struct ifqueue *inq; 381 382 is->is_if.if_ipackets++; 383 if (is->is_ifuba.ifu_flags & UBA_NEEDBDP) 384 UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp); 385 il = (struct il_rheader *)(is->is_ifuba.ifu_r.ifrw_addr); 386 len = il->ilr_length - sizeof(struct il_rheader); 387 if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 || 388 len > ETHERMTU) { 389 is->is_if.if_ierrors++; 390 #ifdef notdef 391 if (is->is_if.if_ierrors % 100 == 0) 392 printf("il%d: += 100 input errors\n", unit); 393 #endif 394 goto setup; 395 } 396 397 /* 398 * Deal with trailer protocol: if type is trailer type 399 * get true type from first 16-bit word past data. 400 * Remember that type was trailer by setting off. 401 */ 402 il->ilr_type = ntohs((u_short)il->ilr_type); 403 #define ildataaddr(il, off, type) ((type)(((caddr_t)((il)+1)+(off)))) 404 if (il->ilr_type >= ETHERTYPE_TRAIL && 405 il->ilr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 406 off = (il->ilr_type - ETHERTYPE_TRAIL) * 512; 407 if (off >= ETHERMTU) 408 goto setup; /* sanity */ 409 il->ilr_type = ntohs(*ildataaddr(il, off, u_short *)); 410 resid = ntohs(*(ildataaddr(il, off+2, u_short *))); 411 if (off + resid > len) 412 goto setup; /* sanity */ 413 len = off + resid; 414 } else 415 off = 0; 416 if (len == 0) 417 goto setup; 418 419 /* 420 * Pull packet off interface. Off is nonzero if packet 421 * has trailing header; ilget will then force this header 422 * information to be at the front, but we still have to drop 423 * the type and length which are at the front of any trailer data. 424 */ 425 m = if_rubaget(&is->is_ifuba, len, off, &is->is_if); 426 if (m == 0) 427 goto setup; 428 if (off) { 429 struct ifnet *ifp; 430 431 ifp = *(mtod(m, struct ifnet **)); 432 m->m_off += 2 * sizeof (u_short); 433 m->m_len -= 2 * sizeof (u_short); 434 *(mtod(m, struct ifnet **)) = ifp; 435 } 436 switch (il->ilr_type) { 437 438 #ifdef INET 439 case ETHERTYPE_IP: 440 schednetisr(NETISR_IP); 441 inq = &ipintrq; 442 break; 443 444 case ETHERTYPE_ARP: 445 arpinput(&is->is_ac, m); 446 goto setup; 447 #endif 448 #ifdef NS 449 case ETHERTYPE_NS: 450 schednetisr(NETISR_NS); 451 inq = &nsintrq; 452 break; 453 454 #endif 455 default: 456 m_freem(m); 457 goto setup; 458 } 459 460 s = splimp(); 461 if (IF_QFULL(inq)) { 462 IF_DROP(inq); 463 m_freem(m); 464 } else 465 IF_ENQUEUE(inq, m); 466 splx(s); 467 468 setup: 469 /* 470 * Reset for next packet if possible. 471 * If waiting for transmit command completion, set flag 472 * and wait until command completes. 473 */ 474 if (is->is_flags & ILF_OACTIVE) { 475 is->is_flags |= ILF_RCVPENDING; 476 return; 477 } 478 addr->il_bar = is->is_ifuba.ifu_r.ifrw_info & 0xffff; 479 addr->il_bcr = sizeof(struct il_rheader) + ETHERMTU + 6; 480 addr->il_csr = 481 ((is->is_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE; 482 while ((addr->il_csr & IL_CDONE) == 0) 483 ; 484 } 485 486 /* 487 * Ethernet output routine. 488 * Encapsulate a packet of type family for the local net. 489 * Use trailer local net encapsulation if enough data in first 490 * packet leaves a multiple of 512 bytes of data in remainder. 491 */ 492 iloutput(ifp, m0, dst) 493 struct ifnet *ifp; 494 struct mbuf *m0; 495 struct sockaddr *dst; 496 { 497 int type, s, error; 498 u_char edst[6]; 499 struct in_addr idst; 500 register struct il_softc *is = &il_softc[ifp->if_unit]; 501 register struct mbuf *m = m0; 502 register struct ether_header *il; 503 register int off; 504 505 switch (dst->sa_family) { 506 507 #ifdef INET 508 case AF_INET: 509 idst = ((struct sockaddr_in *)dst)->sin_addr; 510 if (!arpresolve(&is->is_ac, m, &idst, edst)) 511 return (0); /* if not yet resolved */ 512 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 513 /* need per host negotiation */ 514 if ((ifp->if_flags & IFF_NOTRAILERS) == 0) 515 if (off > 0 && (off & 0x1ff) == 0 && 516 m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 517 type = ETHERTYPE_TRAIL + (off>>9); 518 m->m_off -= 2 * sizeof (u_short); 519 m->m_len += 2 * sizeof (u_short); 520 *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); 521 *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 522 goto gottrailertype; 523 } 524 type = ETHERTYPE_IP; 525 off = 0; 526 goto gottype; 527 #endif 528 #ifdef NS 529 case AF_NS: 530 type = ETHERTYPE_NS; 531 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 532 (caddr_t)edst, sizeof (edst)); 533 off = 0; 534 goto gottype; 535 #endif 536 537 case AF_UNSPEC: 538 il = (struct ether_header *)dst->sa_data; 539 bcopy((caddr_t)il->ether_dhost, (caddr_t)edst, sizeof (edst)); 540 type = il->ether_type; 541 goto gottype; 542 543 default: 544 printf("il%d: can't handle af%d\n", ifp->if_unit, 545 dst->sa_family); 546 error = EAFNOSUPPORT; 547 goto bad; 548 } 549 550 gottrailertype: 551 /* 552 * Packet to be sent as trailer: move first packet 553 * (control information) to end of chain. 554 */ 555 while (m->m_next) 556 m = m->m_next; 557 m->m_next = m0; 558 m = m0->m_next; 559 m0->m_next = 0; 560 m0 = m; 561 562 gottype: 563 /* 564 * Add local net header. If no space in first mbuf, 565 * allocate another. 566 */ 567 if (m->m_off > MMAXOFF || 568 MMINOFF + sizeof (struct ether_header) > m->m_off) { 569 m = m_get(M_DONTWAIT, MT_HEADER); 570 if (m == 0) { 571 error = ENOBUFS; 572 goto bad; 573 } 574 m->m_next = m0; 575 m->m_off = MMINOFF; 576 m->m_len = sizeof (struct ether_header); 577 } else { 578 m->m_off -= sizeof (struct ether_header); 579 m->m_len += sizeof (struct ether_header); 580 } 581 il = mtod(m, struct ether_header *); 582 il->ether_type = htons((u_short)type); 583 bcopy((caddr_t)edst, (caddr_t)il->ether_dhost, sizeof (edst)); 584 bcopy((caddr_t)is->is_addr, (caddr_t)il->ether_shost, 585 sizeof(il->ether_shost)); 586 587 /* 588 * Queue message on interface, and start output if interface 589 * not yet active. 590 */ 591 s = splimp(); 592 if (IF_QFULL(&ifp->if_snd)) { 593 IF_DROP(&ifp->if_snd); 594 splx(s); 595 m_freem(m); 596 return (ENOBUFS); 597 } 598 IF_ENQUEUE(&ifp->if_snd, m); 599 if ((is->is_flags & ILF_OACTIVE) == 0) 600 ilstart(ifp->if_unit); 601 splx(s); 602 return (0); 603 604 bad: 605 m_freem(m0); 606 return (error); 607 } 608 609 /* 610 * Watchdog routine, request statistics from board. 611 */ 612 ilwatch(unit) 613 int unit; 614 { 615 register struct il_softc *is = &il_softc[unit]; 616 register struct ifnet *ifp = &is->is_if; 617 int s; 618 619 if (is->is_flags & ILF_STATPENDING) { 620 ifp->if_timer = is->is_scaninterval; 621 return; 622 } 623 s = splimp(); 624 is->is_flags |= ILF_STATPENDING; 625 if ((is->is_flags & ILF_OACTIVE) == 0) 626 ilstart(ifp->if_unit); 627 splx(s); 628 ifp->if_timer = is->is_scaninterval; 629 } 630 631 /* 632 * Total up the on-board statistics. 633 */ 634 iltotal(is) 635 register struct il_softc *is; 636 { 637 register u_short *interval, *sum, *end; 638 639 interval = &is->is_stats.ils_frames; 640 sum = &is->is_sum.ils_frames; 641 end = is->is_sum.ils_fill2; 642 while (sum < end) 643 *sum++ += *interval++; 644 is->is_if.if_collisions = is->is_sum.ils_collis; 645 } 646 647 /* 648 * Process an ioctl request. 649 */ 650 ilioctl(ifp, cmd, data) 651 register struct ifnet *ifp; 652 int cmd; 653 caddr_t data; 654 { 655 register struct ifaddr *ifa = (struct ifaddr *)data; 656 int s = splimp(), error = 0; 657 658 switch (cmd) { 659 660 case SIOCSIFADDR: 661 ifp->if_flags |= IFF_UP; 662 ilinit(ifp->if_unit); 663 664 switch (ifa->ifa_addr.sa_family) { 665 #ifdef INET 666 case AF_INET: 667 ((struct arpcom *)ifp)->ac_ipaddr = 668 IA_SIN(ifa)->sin_addr; 669 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 670 break; 671 #endif 672 #ifdef NS 673 case AF_NS: 674 IA_SNS(ifa)->sns_addr.x_host = 675 * (union ns_host *) 676 (il_softc[ifp->if_unit].is_addr); 677 break; 678 #endif 679 } 680 break; 681 682 default: 683 error = EINVAL; 684 } 685 splx(s); 686 return (error); 687 } 688 #endif 689