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