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