1: /* 2: * Copyright (c) 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_ix.c 7.1 (Berkeley) 6/5/86 7: */ 8: 9: #include "np.h" 10: #if NNP > 0 11: 12: /* 13: * Interlan NP100 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 "../vaxif/if_uba.h" 47: #include "../vaxuba/ubareg.h" 48: #include "../vaxuba/ubavar.h" 49: #include "../vaxuba/npreg.h" 50: #include "../vaxif/if_ix.h" 51: 52: int ixattach(), ixrint(), ixcint(); 53: #define ILUNIT(x) minor(x) 54: int ixinit(), ixoutput(), ixioctl(), ixreset(), ixwatch(); 55: int (*IxAttach)() = ixattach; 56: int (*IxReset)() = ixreset; 57: 58: /* 59: * Ethernet software status per interface. 60: * 61: * Each interface is referenced by a network interface structure, 62: * ix_if, which the routing code uses to locate the interface. 63: * This structure contains the output queue for the interface, its address, ... 64: * We also have, for each interface, a UBA interface structure, which 65: * contains information about the UNIBUS resources held by the interface: 66: * map registers, buffered data paths, etc. Information is cached in this 67: * structure for use by the if_uba.c routines in running the interface 68: * efficiently. 69: */ 70: struct ix_softc { 71: struct arpcom ix_ac; /* Ethernet common part */ 72: #define ix_if ix_ac.ac_if /* network-visible interface */ 73: #define ix_addr ix_ac.ac_enaddr /* hardware Ethernet address */ 74: int ix_flags; 75: #define IXF_OACTIVE 0x1 /* output is active */ 76: #define IXF_RCVPENDING 0x2 /* start rcv in ilcint */ 77: #define IXF_GOTUBA 0x4 /* unibus resources mapped */ 78: #define IXF_RUNNING 0x8 /* board is running */ 79: #define IXF_SETADDR 0x10 /* physical address is changed */ 80: #define IXF_STATPENDING 0x20 /* stat cmd pending */ 81: #define IXF_GOTCQE 0x40 /* np resources available */ 82: struct ifuba ix_ifuba; /* unibus resources */ 83: u_short ix_aid; /* Access Id returned by open DDL */ 84: u_short ix_badcqe; 85: struct npmaster *ix_mp; /* Board physio request header */ 86: struct npreq *ix_rrp; /* Cached npreq for recv */ 87: struct npreq *ix_wrp; /* Cached npreq for xmit */ 88: short ix_scaninterval; /* interval of stat collection */ 89: #define IXWATCHINTERVAL 60 /* once every 60 seconds */ 90: union ix_stats ix_stats; /* holds on-board statistics */ 91: int ix_ubaddr; /* mapping registers of ix_stats */ 92: } ix_softc[NNP]; 93: extern struct uba_device *npdinfo[]; 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. We can't even get the ethernet address 99: * or other interesting data until the board has been downloaded. 100: * running ifconfig will attempt to start unit. 101: */ 102: ixattach(ui) 103: struct uba_device *ui; 104: { 105: register struct ix_softc *ix = &ix_softc[ui->ui_unit]; 106: register struct ifnet *ifp = &ix->ix_if; 107: extern struct npmaster npmasters[]; 108: 109: ifp->if_unit = ui->ui_unit; 110: ifp->if_name = "ix"; 111: ifp->if_mtu = ETHERMTU; 112: ifp->if_flags = IFF_BROADCAST; 113: 114: ifp->if_init = ixinit; 115: ifp->if_output = ixoutput; 116: ifp->if_ioctl = ixioctl; 117: ifp->if_reset = ixreset; 118: 119: ix->ix_mp = npmasters + ui->ui_unit; 120: ix->ix_ifuba.ifu_flags = UBA_CANTWAIT; 121: 122: if_attach(ifp); 123: } 124: 125: struct npreq * 126: ix_GetReq(mp, addr, len) 127: struct npmaster *mp; 128: caddr_t addr; 129: { 130: int unit = mp->unit; 131: register struct npreq *rp; 132: register struct CQE *ep; 133: struct ix_softc *ix = ix_softc + unit; 134: extern struct npreq *NpGetReq(); 135: 136: while ((rp = NpGetReq(mp->reqtab)) == NULL) { 137: mp->reqtab->flags |= WANTREQ; 138: sleep((caddr_t)(mp->reqtab), PZERO - 1); 139: } 140: rp->flags = KERNREQ; /* Clear flags */ 141: 142: ep = rp->element; /* Associated CQE */ 143: ep->cqe_famid = (unsign32)ix; /* Process ID */ 144: ep->cqe_wind = 0; /* Amount of buffer mapped */ 145: ep->cqe_nbuf = 1; /* Must be 1, no buffer chain */ 146: ep->cqe_char = 1; /* Driver owns this CQE */ 147: ep->cqe_prot = NPDLA; /* Data Link Access protocol */ 148: ep->cqe_bcnt = len; /* Byte count */ 149: rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */ 150: ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr); 151: ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr); 152: return (rp); 153: } 154: 155: ix_DoReq(mp, rp, cmd, addr, len, rpb, routine) 156: struct npmaster *mp; 157: register struct npreq *rp; 158: u_short cmd; 159: caddr_t addr; 160: int len; 161: register u_short *rpb; 162: int (*routine)(); 163: { 164: register struct CQE *ep = rp->element; 165: register u_short *p = &ep->rpb1; 166: u_short cnt = *rpb++; 167: extern long NpDebug; 168: int pri; 169: 170: ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR; /* Clear status */ 171: ep->cqe_bcnt = len; /* Byte count */ 172: rp->flags = KERNREQ; /* Clear flags */ 173: rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */ 174: rp->intr = routine; 175: rp->user = (caddr_t) (ep->cqe_func = cmd);/* In case pissed on in CQE */ 176: ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr); 177: ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr); 178: ep->cqe_lenrpb = cnt + cnt; 179: for (; cnt > 0; cnt--) *p++ = *rpb++; 180: 181: if (NpDebug & DEBCQE) 182: printf("Function is %x ep %x reqid %x\n", ep->cqe_func, ep, ep->cqe_reqid); 183: if (NpDebug & DEBCQE) 184: printf("irp len = %x rp = %x\n", ep->cqe_lenrpb, rp); 185: if (routine == 0) { 186: NpAddReq(mp->reqtab, rp); /* Queue onto active list */ 187: while (!(rp->flags & REQDONE)) { 188: pri = spl4(); 189: NpAddCQE(ep, &mp->shmemp->devcq, mp); 190: sleep((caddr_t)rp, PZERO - 1); 191: splx(pri); 192: } 193: if (rp->flags & IOABORT || ep->cqe_sts != NPDONE 194: || ep->cqe_ust0 != NPDONE 195: || ep->cqe_ust1 != NPOK) { 196: struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid; 197: printf("ix%d: Req failed, cmd %x, stat %x, ", 198: ix->ix_if.if_unit, rp->user, ep->cqe_sts); 199: printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1); 200: } 201: NpRemReq(rp); /* Clear request */ 202: } else { 203: pri = spl4(); 204: NpAddCQE(ep, &mp->shmemp->devcq, mp); 205: splx(pri); 206: } 207: } 208: 209: /* 210: * Ethernet output routine. 211: * Encapsulate a packet of type family for the local net. 212: * Use trailer local net encapsulation if enough data in first 213: * packet leaves a multiple of 512 bytes of data in remainder. 214: */ 215: ixoutput(ifp, m0, dst) 216: struct ifnet *ifp; 217: struct mbuf *m0; 218: struct sockaddr *dst; 219: { 220: int type, s, error; 221: u_char edst[6]; 222: struct in_addr idst; 223: register struct ix_softc *ix = &ix_softc[ifp->if_unit]; 224: register struct mbuf *m = m0; 225: register struct ether_header *il; 226: register int off; 227: int usetrailers; 228: 229: if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { 230: error = ENETDOWN; 231: goto bad; 232: } 233: switch (dst->sa_family) { 234: 235: #ifdef INET 236: case AF_INET: 237: idst = ((struct sockaddr_in *)dst)->sin_addr; 238: if (!arpresolve(&ix->ix_ac, m, &idst, edst, &usetrailers)) 239: return (0); /* if not yet resolved */ 240: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; 241: if (usetrailers && off > 0 && (off & 0x1ff) == 0 && 242: m->m_off >= MMINOFF + 2 * sizeof (u_short)) { 243: type = ETHERTYPE_TRAIL + (off>>9); 244: m->m_off -= 2 * sizeof (u_short); 245: m->m_len += 2 * sizeof (u_short); 246: *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); 247: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); 248: goto gottrailertype; 249: } 250: type = ETHERTYPE_IP; 251: off = 0; 252: goto gottype; 253: #endif 254: #ifdef NS 255: case AF_NS: 256: type = ETHERTYPE_NS; 257: bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), 258: (caddr_t)edst, sizeof (edst)); 259: off = 0; 260: goto gottype; 261: #endif 262: 263: case AF_UNSPEC: 264: il = (struct ether_header *)dst->sa_data; 265: bcopy((caddr_t)il->ether_dhost, (caddr_t)edst, sizeof (edst)); 266: type = il->ether_type; 267: goto gottype; 268: 269: default: 270: printf("ix%d: can't handle af%d\n", ifp->if_unit, 271: dst->sa_family); 272: error = EAFNOSUPPORT; 273: goto bad; 274: } 275: 276: gottrailertype: 277: /* 278: * Packet to be sent as trailer: move first packet 279: * (control information) to end of chain. 280: */ 281: while (m->m_next) 282: m = m->m_next; 283: m->m_next = m0; 284: m = m0->m_next; 285: m0->m_next = 0; 286: m0 = m; 287: 288: gottype: 289: /* 290: * Add local net header. If no space in first mbuf, 291: * allocate another. 292: */ 293: if (m->m_off > MMAXOFF || 294: MMINOFF + sizeof (struct ether_header) > m->m_off) { 295: m = m_get(M_DONTWAIT, MT_HEADER); 296: if (m == 0) { 297: error = ENOBUFS; 298: goto bad; 299: } 300: m->m_next = m0; 301: m->m_off = MMINOFF; 302: m->m_len = sizeof (struct ether_header); 303: } else { 304: m->m_off -= sizeof (struct ether_header); 305: m->m_len += sizeof (struct ether_header); 306: } 307: il = mtod(m, struct ether_header *); 308: il->ether_type = htons((u_short)type); 309: bcopy((caddr_t)edst, (caddr_t)il->ether_dhost, sizeof (edst)); 310: bcopy((caddr_t)ix->ix_addr, (caddr_t)il->ether_shost, 311: sizeof(il->ether_shost)); 312: 313: /* 314: * Queue message on interface, and start output if interface 315: * not yet active. 316: */ 317: s = splimp(); 318: if (IF_QFULL(&ifp->if_snd)) { 319: IF_DROP(&ifp->if_snd); 320: splx(s); 321: m_freem(m); 322: return (ENOBUFS); 323: } 324: IF_ENQUEUE(&ifp->if_snd, m); 325: if ((ix->ix_flags & IXF_OACTIVE) == 0) 326: ixstart(ifp->if_unit); 327: splx(s); 328: return (0); 329: 330: bad: 331: m_freem(m0); 332: return (error); 333: } 334: /* 335: * Reset of interface after UNIBUS reset. 336: * If interface is on specified uba, reset its state. 337: */ 338: ixreset(unit, uban, softp) 339: int unit, uban; 340: caddr_t softp; 341: { 342: register struct uba_device *ui; 343: int mask = IXF_SETADDR; /* Only remember new physaddr */ 344: 345: if (unit >= NNP || (ui = npdinfo[unit]) == 0 || ui->ui_alive == 0 || 346: ui->ui_ubanum != uban) 347: return; 348: printf(" ix%d reset", unit); 349: if (softp) 350: mask |= IXF_GOTUBA; /* UBA mapping regs still valid; */ 351: ix_softc[unit].ix_if.if_flags &= ~IFF_RUNNING; 352: ix_softc[unit].ix_flags &= mask; 353: } 354: 355: 356: /* 357: * Initialization of interface; clear recorded pending 358: * operations, and reinitialize UNIBUS usage. 359: */ 360: ixinit(unit) 361: int unit; 362: { 363: register struct ix_softc *ix = &ix_softc[unit]; 364: struct uba_device *ui = npdinfo[unit]; 365: register struct ifnet *ifp = &ix->ix_if; 366: register struct CQE *ep; 367: struct npreq *rp; 368: struct npmaster *mp = ix->ix_mp; 369: register u_short *dpmp = & mp->shmemp->statblock.sb_dpm; 370: u_short rpb[7]; 371: int s; 372: 373: /* not yet, if address still unknown */ 374: if (ifp->if_addrlist == (struct ifaddr *)0) 375: return; 376: if (ix->ix_flags & IXF_RUNNING) 377: return; 378: if ((mp->flags & AVAILABLE) == 0 || (*dpmp & PROTOMASK(NPDLA)) == 0) { 379: ifp->if_flags &= ~IFF_UP; 380: return; 381: } 382: if ((ix->ix_flags & IXF_GOTUBA) == 0) { 383: ix->ix_ifuba.ifu_flags = UBA_CANTWAIT; 384: if (if_ubainit(&ix->ix_ifuba, ui->ui_ubanum, 385: sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) { 386: printf("ix%d: can't initialize\n", unit); 387: ix->ix_if.if_flags &= ~IFF_UP; 388: return; 389: } 390: ix->ix_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&ix->ix_stats, 391: sizeof (union ix_stats), 0); 392: ix->ix_flags |= IXF_GOTUBA; 393: } 394: if ((ix->ix_flags & IXF_GOTCQE) == 0) { 395: ix->ix_rrp = ix_GetReq(mp, ix->ix_ifuba.ifu_r.ifrw_info, 396: ETHERMTU); 397: ix->ix_wrp = ix_GetReq(mp, 0, 0); 398: ix->ix_flags |= IXF_GOTCQE; 399: } 400: 401: rp = ix->ix_wrp; 402: ep = rp->element; 403: 404: /* Changing the ethernet address resets the dla module, 405: so must do it before opening the channel */ 406: if (ix->ix_flags & IXF_SETADDR) { 407: register char *cp = (char *) &ix->ix_stats; 408: int spincount; 409: int x; 410: *cp++ = 1; 411: bcopy(ix->ix_addr, (caddr_t)cp, 6); 412: rpb[0] = 1; /* RPB length */ 413: ix_DoReq(mp, rp, IXC_LDPA, ix->ix_ubaddr, 7, rpb, 0); 414: #ifndef TheyFinallyFixedTheBoard 415: /* Board requires some time to reinitialize its protocols */ 416: x = spl1(); 417: spincount = 2000000; 418: while (((*dpmp & PROTOMASK(NPDLA))==0) && spincount > 0) 419: spincount--; 420: if (spincount==0) { 421: printf("ix%d: failed to reinitialize DLA module\n", 422: unit); 423: splx(x); 424: } 425: splx(x); 426: #endif 427: } 428: rpb[0] = 6; /* RPB length */ 429: rpb[2] = 0x10; /* Share with any smart users */ 430: rpb[3] = 0; /* Take (a copy of) all frames */ 431: rpb[5] = 8; /* On board rcv queue length */ 432: rpb[6] = 0; /* XMT packets as is */ 433: ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0); 434: 435: ix->ix_aid = ep->rpb1; 436: 437: /* Here we request our ethernet address, if we didn't reset it*/ 438: if ((ix->ix_flags & IXF_SETADDR)==0) { 439: rpb[0] = 2; 440: rpb[1] = ix->ix_aid; 441: rpb[2] = 0; /* get all stats */ 442: ix_DoReq(mp, rp, IXC_GSTAT, /* Get Stats */ 443: (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8, 444: rpb, 0); 445: bcopy((caddr_t) &ix->ix_stats, (caddr_t) ix->ix_addr, 6); 446: } 447: ix->ix_if.if_flags |= IFF_RUNNING; 448: ix->ix_flags |= IXF_RUNNING; 449: ifp->if_watchdog = ixwatch; 450: ifp->if_timer = ix->ix_scaninterval = IXWATCHINTERVAL; 451: ixrint(mp, 0); 452: } 453: 454: /* 455: * Start output on interface. 456: * Get another datagram to send off of the interface queue, 457: * and map it to the interface before starting the output. 458: */ 459: ixstart(dev) 460: dev_t dev; 461: { 462: int len = 0; 463: int unit = minor(dev); 464: register struct ix_softc *ix = &ix_softc[unit]; 465: register struct mbuf *n; 466: struct mbuf *m; 467: int s, error = 0; 468: struct npmaster *mp = ix->ix_mp; 469: struct npreq *rp = ix->ix_wrp; 470: struct CQE *ep; 471: u_short rpb[8]; 472: 473: IF_DEQUEUE(&ix->ix_if.if_snd, m); 474: if (m == 0) { 475: if (ix->ix_flags & IXF_STATPENDING) { 476: ix->ix_flags |= IXF_OACTIVE; 477: rpb[0] = 2; 478: rpb[1] = ix->ix_aid; 479: rpb[2] = 0; /* get all stats */ 480: ix_DoReq(mp, rp, IXC_GSTAT, /* general Stats */ 481: (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8, 482: rpb, ixcint); 483: } 484: return; 485: } 486: /* 487: * Ensure minimum packet length. 488: * This makes the safe assumtion that there are no virtual holes 489: * after the data. 490: * For security, it might be wise to zero out the added bytes, 491: * but we're mainly interested in speed at the moment. 492: */ 493: len = if_wubaput(&ix->ix_ifuba, m); 494: if (len - sizeof(struct ether_header) < ETHERMIN) 495: len = ETHERMIN + sizeof(struct ether_header); 496: 497: ix->ix_flags |= IXF_OACTIVE; 498: 499: /* Now setup to call np driver */ 500: rpb[0] = 8; 501: rpb[1] = ix->ix_aid; 502: ix_DoReq(mp, rp, IXC_XMIT, /* send frame */ 503: ix->ix_ifuba.ifu_w.ifrw_info, len, rpb, ixcint); 504: } 505: 506: /* 507: * Command done interrupt. (almost) 508: */ 509: ixcint(mp, rp) 510: struct npmaster *mp; 511: struct npreq *rp; 512: { 513: struct CQE *ep; 514: register struct ix_softc *ix; 515: int s = splimp(); 516: 517: ep = rp->element; 518: ix = (struct ix_softc *)ep->cqe_famid; 519: if ((ix->ix_flags & IXF_OACTIVE) == 0) { 520: printf("ix%d: stray xmit interrupt, npreq=%x\n", 521: ix->ix_if.if_unit, rp); 522: } 523: ix->ix_flags &= ~IXF_OACTIVE; 524: 525: switch (ep->cqe_func) { 526: 527: case IXC_XMIT: 528: if (ep->cqe_sts == 1) 529: ix->ix_if.if_opackets++; 530: else 531: ix->ix_if.if_oerrors++; 532: break; 533: 534: case IXC_GSTAT: 535: if (ep->cqe_sts == 1) 536: ix->ix_if.if_collisions = ix->ix_stats.ixg.macg_xrty; 537: break; 538: } 539: if (ix->ix_ifuba.ifu_xtofree) { 540: m_freem(ix->ix_ifuba.ifu_xtofree); 541: ix->ix_ifuba.ifu_xtofree = 0; 542: } 543: done: 544: ixstart(ix->ix_if.if_unit); 545: splx(s); 546: } 547: 548: /* 549: * Ethernet interface receiver interrupt. 550: * If input error just drop packet. 551: * Otherwise purge input buffered data path and examine 552: * packet to determine type. If can't determine length 553: * from type, then have to drop packet. Othewise decapsulate 554: * packet based on type and pass to type specific higher-level 555: * input routine. 556: */ 557: ixrint(mp, rp) 558: struct npmaster *mp; 559: struct npreq *rp; 560: { 561: struct CQE *ep; 562: register struct ix_softc *ix = ix_softc + mp->unit; 563: register struct ether_header *il; 564: struct mbuf *m; 565: int len, off, resid, s; 566: register struct ifqueue *inq; 567: 568: if ((ix->ix_flags & IXF_RUNNING) == 0) 569: return; 570: if (rp == 0) 571: goto setup; 572: ix->ix_flags &= ~IXF_RCVPENDING; 573: ep = rp->element; 574: ix->ix_if.if_ipackets++; 575: if (ix->ix_ifuba.ifu_flags & UBA_NEEDBDP) 576: UBAPURGE(ix->ix_ifuba.ifu_uba, ix->ix_ifuba.ifu_r.ifrw_bdp); 577: il = (struct ether_header *)(ix->ix_ifuba.ifu_r.ifrw_addr); 578: len = ep->cqe_bcnt - sizeof (struct ether_header); 579: if (ep->cqe_sts != NPDONE 580: || ep->cqe_ust0 != NPDONE 581: || ep->cqe_ust1 != NPOK) { 582: printf("ixrint: cqe error %x, %x, %x\n", 583: ep->cqe_sts, ep->cqe_ust0, ep->cqe_ust1); 584: if (++ix->ix_badcqe > 100) { 585: ix->ix_badcqe = 0; 586: printf("ixrint: shutting down unix dla\n"); 587: ix->ix_if.if_flags &= ~IFF_UP; 588: return; 589: } 590: goto setup; 591: } 592: 593: if ( len < 46 || len > ETHERMTU) { 594: ix->ix_if.if_ierrors++; 595: #ifdef notdef 596: if (ix->ix_if.if_ierrors % 100 == 0) 597: printf("ix%d: += 100 input errors\n", unit); 598: #endif 599: goto setup; 600: } 601: 602: /* 603: * Deal with trailer protocol: if type is trailer type 604: * get true type from first 16-bit word past data. 605: * Remember that type was trailer by setting off. 606: */ 607: il->ether_type = ntohs((u_short)il->ether_type); 608: #define ildataaddr(il, off, type) ((type)(((caddr_t)((il)+1)+(off)))) 609: if (il->ether_type >= ETHERTYPE_TRAIL && 610: il->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 611: off = (il->ether_type - ETHERTYPE_TRAIL) * 512; 612: if (off >= ETHERMTU) 613: goto setup; /* sanity */ 614: il->ether_type = ntohs(*ildataaddr(il, off, u_short *)); 615: resid = ntohs(*(ildataaddr(il, off+2, u_short *))); 616: if (off + resid > len) 617: goto setup; /* sanity */ 618: len = off + resid; 619: } else 620: off = 0; 621: if (len == 0) 622: goto setup; 623: 624: /* 625: * Pull packet off interface. Off is nonzero if packet 626: * has trailing header; ilget will then force this header 627: * information to be at the front, but we still have to drop 628: * the type and length which are at the front of any trailer data. 629: */ 630: m = if_rubaget(&ix->ix_ifuba, len, off, &ix->ix_if); 631: if (m == 0) 632: goto setup; 633: if (off) { 634: struct ifnet *ifp; 635: 636: ifp = *(mtod(m, struct ifnet **)); 637: m->m_off += 2 * sizeof (u_short); 638: m->m_len -= 2 * sizeof (u_short); 639: *(mtod(m, struct ifnet **)) = ifp; 640: } 641: switch (il->ether_type) { 642: 643: #ifdef INET 644: case ETHERTYPE_IP: 645: schednetisr(NETISR_IP); 646: inq = &ipintrq; 647: break; 648: 649: case ETHERTYPE_ARP: 650: arpinput(&ix->ix_ac, m); 651: goto setup; 652: #endif 653: #ifdef NS 654: case ETHERTYPE_NS: 655: schednetisr(NETISR_NS); 656: inq = &nsintrq; 657: break; 658: 659: #endif 660: default: 661: m_freem(m); 662: goto setup; 663: } 664: 665: s = splimp(); 666: if (IF_QFULL(inq)) { 667: IF_DROP(inq); 668: m_freem(m); 669: } else 670: IF_ENQUEUE(inq, m); 671: splx(s); 672: 673: setup: 674: /* 675: * Reset for next packet if possible. 676: * If waiting for transmit command completion, set flag 677: * and wait until command completes. 678: */ 679: if (rp == 0) { 680: rp = ix->ix_rrp; 681: rp->intr = ixrint; 682: ep = rp->element; 683: } 684: len = ETHERMTU + sizeof(struct ether_header); 685: 686: /* Now setup to call np driver */ 687: /* Initializations of request structure */ 688: 689: ep->cqe_func = IXC_RECV; /* get frame */ 690: ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR; /* Clear status */ 691: ep->cqe_bcnt = len; /* Byte count */ 692: ep->cqe_lenrpb = 10; /* RPB length */ 693: ep->rpb1 = ix->ix_aid; /* which channel */ 694: ep->rpb2 = 65535; /* Timeout */ 695: 696: ix->ix_flags |= IXF_RCVPENDING; 697: 698: s = spl4(); 699: NpAddCQE(ep, &mp->shmemp->devcq, mp); /* Add CQE to device's queue */ 700: splx(s); 701: } 702: 703: 704: /* 705: * Watchdog routine, request statistics from board. 706: */ 707: ixwatch(unit) 708: int unit; 709: { 710: register struct ix_softc *ix = &ix_softc[unit]; 711: register struct ifnet *ifp = &ix->ix_if; 712: int s; 713: 714: if (ix->ix_flags & IXF_STATPENDING) { 715: ifp->if_timer = ix->ix_scaninterval; 716: return; 717: } 718: s = splimp(); 719: ix->ix_flags |= IXF_STATPENDING; 720: if ((ix->ix_flags & IXF_OACTIVE) == 0) 721: ixstart(ifp->if_unit); 722: splx(s); 723: ifp->if_timer = ix->ix_scaninterval; 724: } 725: /* 726: * Process an ioctl request. 727: */ 728: ixioctl(ifp, cmd, data) 729: register struct ifnet *ifp; 730: int cmd; 731: caddr_t data; 732: { 733: register struct ifaddr *ifa = (struct ifaddr *)data; 734: register struct ix_softc *ix = &ix_softc[ifp->if_unit]; 735: int s = splimp(), error = 0; 736: 737: switch (cmd) { 738: 739: case SIOCSIFADDR: 740: ifp->if_flags |= IFF_UP; 741: ixinit(ifp->if_unit); 742: if ((ifp->if_flags & IFF_UP) == 0) 743: return (EBUSY); 744: 745: switch (ifa->ifa_addr.sa_family) { 746: #ifdef INET 747: case AF_INET: 748: ((struct arpcom *)ifp)->ac_ipaddr = 749: IA_SIN(ifa)->sin_addr; 750: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 751: break; 752: #endif 753: #ifdef NS 754: case AF_NS: 755: { 756: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 757: 758: if (ns_nullhost(*ina)) { 759: ina->x_host = * (union ns_host *) 760: (ix_softc[ifp->if_unit].ix_addr); 761: } else { 762: return 763: ix_setaddr(ina->x_host.c_host, ifp->if_unit); 764: } 765: break; 766: } 767: #endif 768: } 769: break; 770: 771: case SIOCSIFFLAGS: 772: if ((ifp->if_flags & IFF_UP) == 0 && 773: ix->ix_flags & IXF_RUNNING) { 774: ix->ix_flags &= ~IXF_RUNNING; 775: NpReset(ix->ix_mp, 0); 776: } else if (ifp->if_flags & IFF_UP && 777: (ix->ix_flags & IXF_RUNNING) == 0) 778: ixinit(ifp->if_unit); 779: break; 780: 781: default: 782: error = EINVAL; 783: } 784: splx(s); 785: return (error); 786: } 787: 788: /* 789: * set ethernet address for unit 790: */ 791: ix_setaddr(physaddr, unit) 792: u_char *physaddr; 793: int unit; 794: { 795: register struct ix_softc *ix = &ix_softc[unit]; 796: 797: if (! (ix->ix_flags & IXF_RUNNING)) 798: return (EBUSY); 799: 800: /* The following is a big cop out due to the fact that 801: Changing the ethernet address resets the dla module, 802: so must re-open the channel, anyway. */ 803: 804: 805: bcopy((caddr_t)physaddr, (caddr_t)ix->ix_addr, sizeof ix->ix_addr); 806: ix->ix_flags &= ~IXF_RUNNING; 807: ix->ix_flags |= IXF_SETADDR; 808: ixinit(unit); 809: NpKill(ix->ix_mp, ix->ix_rrp); 810: } 811: #endif