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