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