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