|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.