|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1986 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Micom-Interlan Inc. ! 7: * ! 8: * Redistribution and use in source and binary forms, with or without ! 9: * modification, are permitted provided that the following conditions ! 10: * are met: ! 11: * 1. Redistributions of source code must retain the above copyright ! 12: * notice, this list of conditions and the following disclaimer. ! 13: * 2. Redistributions in binary form must reproduce the above copyright ! 14: * notice, this list of conditions and the following disclaimer in the ! 15: * documentation and/or other materials provided with the distribution. ! 16: * 3. All advertising materials mentioning features or use of this software ! 17: * must display the following acknowledgement: ! 18: * This product includes software developed by the University of ! 19: * California, Berkeley and its contributors. ! 20: * 4. Neither the name of the University nor the names of its contributors ! 21: * may be used to endorse or promote products derived from this software ! 22: * without specific prior written permission. ! 23: * ! 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 34: * SUCH DAMAGE. ! 35: * ! 36: * @(#)if_ix.c 7.8 (Berkeley) 12/16/90 ! 37: */ ! 38: ! 39: #include "np.h" ! 40: #if NNP > 0 ! 41: ! 42: /* ! 43: * Interlan NP100 Ethernet Communications Controller interface ! 44: */ ! 45: #include "../include/pte.h" ! 46: ! 47: #include "sys/param.h" ! 48: #include "sys/systm.h" ! 49: #include "sys/mbuf.h" ! 50: #include "sys/buf.h" ! 51: #include "sys/protosw.h" ! 52: #include "sys/socket.h" ! 53: #include "sys/vmmac.h" ! 54: #include "sys/ioctl.h" ! 55: #include "sys/errno.h" ! 56: ! 57: #include "net/if.h" ! 58: #include "net/netisr.h" ! 59: #include "net/route.h" ! 60: ! 61: #ifdef INET ! 62: #include "netinet/in.h" ! 63: #include "netinet/in_systm.h" ! 64: #include "netinet/in_var.h" ! 65: #include "netinet/ip.h" ! 66: #include "netinet/if_ether.h" ! 67: #endif ! 68: ! 69: #ifdef NS ! 70: #include "netns/ns.h" ! 71: #include "netns/ns_if.h" ! 72: #endif ! 73: ! 74: #include "../include/cpu.h" ! 75: #include "../include/mtpr.h" ! 76: #include "../if/if_uba.h" ! 77: #include "../uba/ubareg.h" ! 78: #include "../uba/ubavar.h" ! 79: #include "../uba/npreg.h" ! 80: #include "../if/if_ix.h" ! 81: ! 82: int ixattach(), ixrint(), ixcint(); ! 83: #define ILUNIT(x) minor(x) ! 84: int ixinit(), ixioctl(), ixreset(), ixwatch(), ixstart(); ! 85: int (*IxAttach)() = ixattach; ! 86: int (*IxReset)() = ixreset; ! 87: ! 88: /* ! 89: * Ethernet software status per interface. ! 90: * ! 91: * Each interface is referenced by a network interface structure, ! 92: * ix_if, which the routing code uses to locate the interface. ! 93: * This structure contains the output queue for the interface, its address, ... ! 94: * We also have, for each interface, a UBA interface structure, which ! 95: * contains information about the UNIBUS resources held by the interface: ! 96: * map registers, buffered data paths, etc. Information is cached in this ! 97: * structure for use by the if_uba.c routines in running the interface ! 98: * efficiently. ! 99: */ ! 100: struct ix_softc { ! 101: struct arpcom ix_ac; /* Ethernet common part */ ! 102: #define ix_if ix_ac.ac_if /* network-visible interface */ ! 103: #define ix_addr ix_ac.ac_enaddr /* hardware Ethernet address */ ! 104: int ix_flags; ! 105: #define IXF_OACTIVE 0x1 /* output is active */ ! 106: #define IXF_RCVPENDING 0x2 /* start rcv in ilcint */ ! 107: #define IXF_GOTUBA 0x4 /* unibus resources mapped */ ! 108: #define IXF_RUNNING 0x8 /* board is running */ ! 109: #define IXF_SETADDR 0x10 /* physical address is changed */ ! 110: #define IXF_STATPENDING 0x20 /* stat cmd pending */ ! 111: #define IXF_GOTCQE 0x40 /* np resources available */ ! 112: #define IXF_OWATCH 0x80 /* is output hung? */ ! 113: #define IXF_RWATCH 0x100 /* is input hung? */ ! 114: struct ifuba ix_ifuba; /* unibus resources */ ! 115: u_short ix_aid; /* Access Id returned by open DDL */ ! 116: u_short ix_badcqe; ! 117: struct npmaster *ix_mp; /* Board physio request header */ ! 118: struct npreq *ix_rrp; /* Cached npreq for recv */ ! 119: struct npreq *ix_wrp; /* Cached npreq for xmit */ ! 120: short ix_scaninterval; /* interval of stat collection */ ! 121: #define IXWATCHINTERVAL 60 /* once every 60 seconds */ ! 122: union ix_stats ix_stats; /* holds on-board statistics */ ! 123: int ix_ubaddr; /* mapping registers of ix_stats */ ! 124: } ix_softc[NNP]; ! 125: extern struct uba_device *npdinfo[]; ! 126: ! 127: /* ! 128: * Interface exists: make available by filling in network interface ! 129: * record. System will initialize the interface when it is ready ! 130: * to accept packets. We can't even get the ethernet address ! 131: * or other interesting data until the board has been downloaded. ! 132: * running ifconfig will attempt to start unit. ! 133: */ ! 134: ixattach(ui) ! 135: struct uba_device *ui; ! 136: { ! 137: register struct ix_softc *ix = &ix_softc[ui->ui_unit]; ! 138: register struct ifnet *ifp = &ix->ix_if; ! 139: extern struct npmaster npmasters[]; ! 140: ! 141: ifp->if_unit = ui->ui_unit; ! 142: ifp->if_name = "ix"; ! 143: ifp->if_mtu = ETHERMTU; ! 144: ifp->if_flags = IFF_BROADCAST; ! 145: ! 146: ifp->if_init = ixinit; ! 147: ifp->if_output = ether_output; ! 148: ifp->if_start = ixstart; ! 149: ifp->if_ioctl = ixioctl; ! 150: ifp->if_reset = ixreset; ! 151: ! 152: ix->ix_mp = npmasters + ui->ui_unit; ! 153: ix->ix_ifuba.ifu_flags = UBA_CANTWAIT; ! 154: ! 155: if_attach(ifp); ! 156: } ! 157: ! 158: struct npreq * ! 159: ix_GetReq(mp, addr, len) ! 160: struct npmaster *mp; ! 161: caddr_t addr; ! 162: { ! 163: int unit = mp->unit; ! 164: register struct npreq *rp; ! 165: register struct CQE *ep; ! 166: struct ix_softc *ix = ix_softc + unit; ! 167: extern struct npreq *NpGetReq(); ! 168: ! 169: while ((rp = NpGetReq(mp->reqtab)) == NULL) { ! 170: mp->reqtab->flags |= WANTREQ; ! 171: sleep((caddr_t)(mp->reqtab), PZERO - 1); ! 172: } ! 173: rp->flags = KERNREQ; /* Clear flags */ ! 174: ! 175: ep = rp->element; /* Associated CQE */ ! 176: ep->cqe_famid = (unsign32)ix; /* Process ID */ ! 177: ep->cqe_wind = 0; /* Amount of buffer mapped */ ! 178: ep->cqe_nbuf = 1; /* Must be 1, no buffer chain */ ! 179: ep->cqe_char = 1; /* Driver owns this CQE */ ! 180: ep->cqe_prot = NPDLA; /* Data Link Access protocol */ ! 181: ep->cqe_bcnt = len; /* Byte count */ ! 182: rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */ ! 183: ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr); ! 184: ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr); ! 185: return (rp); ! 186: } ! 187: ! 188: ix_DoReq(mp, rp, cmd, addr, len, rpb, routine) ! 189: struct npmaster *mp; ! 190: register struct npreq *rp; ! 191: u_short cmd; ! 192: caddr_t addr; ! 193: int len; ! 194: register u_short *rpb; ! 195: int (*routine)(); ! 196: { ! 197: register struct CQE *ep = rp->element; ! 198: register u_short *p = &ep->rpb1; ! 199: u_short cnt = *rpb++; ! 200: extern long NpDebug; ! 201: int pri; ! 202: int result = 0; ! 203: ! 204: ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR; /* Clear status */ ! 205: ep->cqe_bcnt = len; /* Byte count */ ! 206: rp->flags = KERNREQ | REQALOC; /* Clear flags */ ! 207: rp->bufaddr = (caddr_t) (UBADDRMASK & (int) addr);/* mapped buffer */ ! 208: rp->intr = routine; ! 209: rp->user = (caddr_t) (ep->cqe_func = cmd);/* In case pissed on in CQE */ ! 210: ep->cqe_dma[0] = (unsign16)LOWORD(rp->bufaddr); ! 211: ep->cqe_dma[1] = (unsign16)HIWORD(rp->bufaddr); ! 212: ep->cqe_lenrpb = cnt + cnt; ! 213: for (; cnt > 0; cnt--) *p++ = *rpb++; ! 214: ! 215: if (NpDebug & DEBCQE) ! 216: printf("Function is %x ep %x reqid %x\n", ep->cqe_func, ep, ep->cqe_reqid); ! 217: if (NpDebug & DEBCQE) ! 218: printf("irp len = %x rp = %x\n", ep->cqe_lenrpb, rp); ! 219: if (routine == 0) { ! 220: NpAddReq(mp->reqtab, rp); /* Queue onto active list */ ! 221: while (!(rp->flags & REQDONE)) { ! 222: pri = spl5(); ! 223: NpAddCQE(ep, &mp->shmemp->devcq, mp); ! 224: sleep((caddr_t)rp, PZERO - 1); ! 225: splx(pri); ! 226: } ! 227: if (rp->flags & IOABORT || ep->cqe_sts != NPDONE ! 228: || ep->cqe_ust0 != NPDONE ! 229: || ep->cqe_ust1 != NPOK) { ! 230: struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid; ! 231: printf("ix%d: Req failed, cmd %x, stat %x, flags %x, ", ! 232: ix->ix_if.if_unit, rp->user, ! 233: ep->cqe_sts, rp->flags); ! 234: printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1); ! 235: result = 1; ! 236: } ! 237: NpRemReq(rp); /* Clear request */ ! 238: } else { ! 239: pri = spl5(); ! 240: NpAddCQE(ep, &mp->shmemp->devcq, mp); ! 241: splx(pri); ! 242: } ! 243: return(result); ! 244: } ! 245: /* ! 246: * Reset of interface after UNIBUS reset. ! 247: * If interface is on specified uba, reset its state. ! 248: */ ! 249: ixreset(unit, uban, softp) ! 250: int unit, uban; ! 251: caddr_t softp; ! 252: { ! 253: register struct uba_device *ui; ! 254: int mask = IXF_SETADDR; /* Only remember new physaddr */ ! 255: ! 256: if (unit >= NNP || (ui = npdinfo[unit]) == 0 || ui->ui_alive == 0 || ! 257: ui->ui_ubanum != uban) ! 258: return; ! 259: printf(" ix%d reset", unit); ! 260: if (softp) ! 261: mask |= IXF_GOTUBA; /* UBA mapping regs still valid; */ ! 262: ix_softc[unit].ix_if.if_flags &= ~IFF_RUNNING; ! 263: ix_softc[unit].ix_flags &= mask; ! 264: } ! 265: ! 266: int ix_MacLoop = 0; ! 267: ! 268: /* ! 269: * Initialization of interface; clear recorded pending ! 270: * operations, and reinitialize UNIBUS usage. ! 271: */ ! 272: ixinit(unit) ! 273: int unit; ! 274: { ! 275: register struct ix_softc *ix = &ix_softc[unit]; ! 276: struct uba_device *ui = npdinfo[unit]; ! 277: register struct ifnet *ifp = &ix->ix_if; ! 278: register struct CQE *ep; ! 279: struct npreq *rp; ! 280: struct npmaster *mp = ix->ix_mp; ! 281: register u_short *dpmp = & mp->shmemp->statblock.sb_dpm; ! 282: u_short rpb[7]; ! 283: int s; ! 284: ! 285: /* not yet, if address still unknown */ ! 286: if ((ifp->if_addrlist == (struct ifaddr *)0) || ! 287: (ix->ix_flags & IXF_RUNNING)) ! 288: return; ! 289: if ((mp->flags & AVAILABLE) == 0 || (*dpmp & PROTOMASK(NPDLA)) == 0) { ! 290: ifp->if_flags &= ~IFF_UP; ! 291: return; ! 292: } ! 293: if ((ix->ix_flags & IXF_GOTUBA) == 0) { ! 294: ix->ix_ifuba.ifu_flags = UBA_CANTWAIT; ! 295: if (if_ubainit(&ix->ix_ifuba, ui->ui_ubanum, ! 296: sizeof (struct ether_header), (int)btoc(ETHERMTU)) == 0) { ! 297: printf("ix%d: can't initialize\n", unit); ! 298: ix->ix_if.if_flags &= ~IFF_UP; ! 299: return; ! 300: } ! 301: ix->ix_ubaddr = uballoc(ui->ui_ubanum, (caddr_t)&ix->ix_stats, ! 302: sizeof (union ix_stats), 0); ! 303: ix->ix_flags |= IXF_GOTUBA; ! 304: } ! 305: if ((ix->ix_flags & IXF_GOTCQE) == 0) { ! 306: ix->ix_rrp = ix_GetReq(mp, ix->ix_ifuba.ifu_r.ifrw_info, ! 307: ETHERMTU); ! 308: ix->ix_wrp = ix_GetReq(mp, 0, 0); ! 309: ix->ix_flags |= IXF_GOTCQE; ! 310: } ! 311: ! 312: rp = ix->ix_wrp; ! 313: ep = rp->element; ! 314: ! 315: /* Changing the ethernet address resets the dla module, ! 316: so must do it before opening the channel */ ! 317: if (ix->ix_flags & IXF_SETADDR) { ! 318: register char *cp = (char *) &ix->ix_stats; ! 319: int spincount; ! 320: int x; ! 321: /* Try Issuing an open channel request before reprogramming ! 322: the physical address */ ! 323: rpb[0] = 6; /* RPB length */ ! 324: rpb[2] = 0x10; /* Share with any smart users */ ! 325: rpb[3] = 0; /* Take (a copy of) all frames */ ! 326: rpb[5] = 8; /* On board rcv queue length */ ! 327: rpb[6] = 0; /* XMT packets as is */ ! 328: if (ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0)) ! 329: return; ! 330: /* Proceed with LDPA */ ! 331: *cp++ = 1; ! 332: bcopy(ix->ix_addr, (caddr_t)cp, 6); ! 333: rpb[0] = 1; /* RPB length */ ! 334: if (ix_DoReq(mp, rp, IXC_LDPA, ix->ix_ubaddr, 7, rpb, 0)) ! 335: return; ! 336: #ifndef TheyFinallyFixedTheBoard ! 337: /* Board requires some time to reinitialize its protocols */ ! 338: x = spl1(); ! 339: spincount = 2000000; ! 340: while (((*dpmp & PROTOMASK(NPDLA))==0) && spincount > 0) ! 341: spincount--; ! 342: if (spincount==0) { ! 343: printf("ix%d: failed to reinitialize DLA module\n", ! 344: unit); ! 345: splx(x); ! 346: } ! 347: splx(x); ! 348: #endif ! 349: } ! 350: rpb[0] = 6; /* RPB length */ ! 351: rpb[2] = 0x10; /* Share with any smart users */ ! 352: if (ix_MacLoop) rpb[2] |= 0x8; ! 353: /* Enable software loopback on board */ ! 354: rpb[3] = 0; /* Take (a copy of) all frames */ ! 355: rpb[5] = 8; /* On board rcv queue length */ ! 356: rpb[6] = 0; /* XMT packets as is */ ! 357: if (ix_DoReq(mp, rp, IXC_OPEN, 0, 0, rpb, 0)) ! 358: return; ! 359: ! 360: ix->ix_aid = ep->rpb1; ! 361: ! 362: /* Here we request our ethernet address, if we didn't reset it*/ ! 363: if ((ix->ix_flags & IXF_SETADDR)==0) { ! 364: rpb[0] = 2; ! 365: rpb[1] = ix->ix_aid; ! 366: rpb[2] = 0; /* get all stats */ ! 367: if (ix_DoReq(mp, rp, IXC_GSTAT, /* Get Stats */ ! 368: (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8, ! 369: rpb, 0)) ! 370: return; ! 371: bcopy((caddr_t) &ix->ix_stats, (caddr_t) ix->ix_addr, 6); ! 372: } ! 373: ix->ix_if.if_flags |= IFF_RUNNING; ! 374: ix->ix_flags |= IXF_RUNNING; ! 375: ifp->if_watchdog = ixwatch; ! 376: ifp->if_timer = ix->ix_scaninterval = IXWATCHINTERVAL; ! 377: ixrint(mp, 0); ! 378: } ! 379: ! 380: /* ! 381: * Start output on interface. ! 382: * Get another datagram to send off of the interface queue, ! 383: * and map it to the interface before starting the output. ! 384: */ ! 385: ixstart(ifp) ! 386: struct ifnet *ifp; ! 387: { ! 388: int len = 0; ! 389: int unit = ifp->if_unit; ! 390: register struct ix_softc *ix = &ix_softc[unit]; ! 391: register struct mbuf *n; ! 392: struct mbuf *m; ! 393: int s, error = 0; ! 394: struct npmaster *mp = ix->ix_mp; ! 395: struct npreq *rp = ix->ix_wrp; ! 396: struct CQE *ep; ! 397: u_short rpb[8]; ! 398: ! 399: IF_DEQUEUE(&ix->ix_if.if_snd, m); ! 400: if (m == 0) { ! 401: if (ix->ix_flags & IXF_STATPENDING) { ! 402: ix->ix_flags &= ~IXF_STATPENDING; ! 403: ix->ix_if.if_flags |= IFF_OACTIVE; ! 404: rpb[0] = 2; ! 405: rpb[1] = ix->ix_aid; ! 406: rpb[2] = 0; /* get all stats */ ! 407: ix_DoReq(mp, rp, IXC_GSTAT, /* general Stats */ ! 408: (caddr_t) ix->ix_ubaddr, sizeof(ix->ix_stats) - 8, ! 409: rpb, ixcint); ! 410: } ! 411: return (0); ! 412: } ! 413: /* ! 414: * Ensure minimum packet length. ! 415: * This makes the safe assumtion that there are no virtual holes ! 416: * after the data. ! 417: * For security, it might be wise to zero out the added bytes, ! 418: * but we're mainly interested in speed at the moment. ! 419: */ ! 420: len = if_wubaput(&ix->ix_ifuba, m); ! 421: if (len - sizeof(struct ether_header) < ETHERMIN) ! 422: len = ETHERMIN + sizeof(struct ether_header); ! 423: ! 424: ix->ix_if.if_flags |= IFF_OACTIVE; ! 425: ! 426: /* Now setup to call np driver */ ! 427: rpb[0] = 8; ! 428: rpb[1] = ix->ix_aid; ! 429: ix_DoReq(mp, rp, IXC_XMIT, /* send frame */ ! 430: ix->ix_ifuba.ifu_w.ifrw_info, len, rpb, ixcint); ! 431: return (0); ! 432: } ! 433: ! 434: /* ! 435: * Command done interrupt. (almost) ! 436: */ ! 437: ixcint(mp, rp) ! 438: struct npmaster *mp; ! 439: struct npreq *rp; ! 440: { ! 441: struct CQE *ep; ! 442: register struct ix_softc *ix; ! 443: int s = splimp(); ! 444: ! 445: ep = rp->element; ! 446: ix = (struct ix_softc *)ep->cqe_famid; ! 447: ix->ix_flags &= ~IXF_OWATCH; ! 448: if ((ix->ix_if.if_flags & IFF_OACTIVE) == 0) { ! 449: printf("ix%d: stray xmit interrupt, npreq=%x\n", ! 450: ix->ix_if.if_unit, rp); ! 451: } ! 452: ix->ix_if.if_flags &= ~IFF_OACTIVE; ! 453: if (rp->flags & IOABORT || ep->cqe_sts != NPDONE ! 454: || ep->cqe_ust0 != NPDONE || ep->cqe_ust1 != NPOK) { ! 455: if (ep->cqe_ust1 == 0x48) ! 456: ix->ix_if.if_oerrors++; ! 457: else { ! 458: struct ix_softc *ix = (struct ix_softc *)ep->cqe_famid; ! 459: printf( ! 460: "ix%d: ixcint failed, cmd %x, stat %x, flags %x, ", ! 461: ix->ix_if.if_unit, rp->user, ! 462: ep->cqe_sts, rp->flags); ! 463: printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1); ! 464: if (++ix->ix_badcqe > 65) { ! 465: ix->ix_badcqe = 0; ! 466: printf("ixcint: shutting down unix dla\n"); ! 467: ix->ix_if.if_flags &= ~IFF_UP; ! 468: } ! 469: } ! 470: } ! 471: else switch (ep->cqe_func) { ! 472: ! 473: case IXC_XMIT: ! 474: ix->ix_if.if_opackets++; ! 475: break; ! 476: ! 477: case IXC_GSTAT: ! 478: ix->ix_if.if_collisions += ix->ix_stats.ixg.macg_xrty; ! 479: } ! 480: done: ! 481: if (ix->ix_ifuba.ifu_xtofree) { ! 482: m_freem(ix->ix_ifuba.ifu_xtofree); ! 483: ix->ix_ifuba.ifu_xtofree = 0; ! 484: } ! 485: if ((ix->ix_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) ! 486: (void) ixstart(&ix->ix_if); ! 487: splx(s); ! 488: } ! 489: ! 490: /* ! 491: * Ethernet interface receiver interrupt. ! 492: * If input error just drop packet. ! 493: * Otherwise purge input buffered data path and examine ! 494: * packet to determine type. If can't determine length ! 495: * from type, then have to drop packet. Othewise decapsulate ! 496: * packet based on type and pass to type specific higher-level ! 497: * input routine. ! 498: */ ! 499: ixrint(mp, rp) ! 500: struct npmaster *mp; ! 501: struct npreq *rp; ! 502: { ! 503: struct CQE *ep; ! 504: register struct ix_softc *ix = ix_softc + mp->unit; ! 505: register struct ether_header *il; ! 506: struct mbuf *m; ! 507: int len, off, resid, s; ! 508: register struct ifqueue *inq; ! 509: ! 510: if ((ix->ix_flags & IXF_RUNNING) == 0) ! 511: return; ! 512: if (rp == 0) ! 513: goto setup; ! 514: ix->ix_flags &= ~(IXF_RCVPENDING|IXF_RWATCH); ! 515: ep = rp->element; ! 516: ix->ix_if.if_ipackets++; ! 517: if (ix->ix_ifuba.ifu_flags & UBA_NEEDBDP) ! 518: UBAPURGE(ix->ix_ifuba.ifu_uba, ix->ix_ifuba.ifu_r.ifrw_bdp); ! 519: il = (struct ether_header *)(ix->ix_ifuba.ifu_r.ifrw_addr); ! 520: len = ep->cqe_bcnt - sizeof (struct ether_header); ! 521: if (ep->cqe_sts != NPDONE || rp->flags & IOABORT ! 522: || ep->cqe_ust0 != NPDONE ! 523: || ep->cqe_ust1 != NPOK) { ! 524: printf("ix%drint: cqe error, cmd %x, stat %x, flags %x, ", ! 525: ix->ix_if.if_unit, rp->user, ep->cqe_sts, rp->flags); ! 526: printf("ust error %x,%x\n", ep->cqe_ust0, ep->cqe_ust1); ! 527: if (++ix->ix_badcqe > 50) { ! 528: ix->ix_badcqe = 0; ! 529: printf("ixrint: shutting down unix dla\n"); ! 530: ix->ix_if.if_flags &= ~IFF_UP; ! 531: return; ! 532: } ! 533: goto setup; ! 534: } ! 535: ! 536: if ( len < 46 || len > ETHERMTU) { ! 537: ix->ix_if.if_ierrors++; ! 538: #ifdef notdef ! 539: if (ix->ix_if.if_ierrors % 100 == 0) ! 540: printf("ix%d: += 100 input errors\n", unit); ! 541: #endif ! 542: goto setup; ! 543: } ! 544: ! 545: /* ! 546: * Deal with trailer protocol: if type is trailer type ! 547: * get true type from first 16-bit word past data. ! 548: * Remember that type was trailer by setting off. ! 549: */ ! 550: il->ether_type = ntohs((u_short)il->ether_type); ! 551: #define ildataaddr(il, off, type) ((type)(((caddr_t)((il)+1)+(off)))) ! 552: if (il->ether_type >= ETHERTYPE_TRAIL && ! 553: il->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { ! 554: off = (il->ether_type - ETHERTYPE_TRAIL) * 512; ! 555: if (off >= ETHERMTU) ! 556: goto setup; /* sanity */ ! 557: il->ether_type = ntohs(*ildataaddr(il, off, u_short *)); ! 558: resid = ntohs(*(ildataaddr(il, off+2, u_short *))); ! 559: if (off + resid > len) ! 560: goto setup; /* sanity */ ! 561: len = off + resid; ! 562: } else ! 563: off = 0; ! 564: if (len == 0) ! 565: goto setup; ! 566: ! 567: /* ! 568: * Pull packet off interface. Off is nonzero if packet ! 569: * has trailing header; ilget will then force this header ! 570: * information to be at the front, but we still have to drop ! 571: * the type and length which are at the front of any trailer data. ! 572: */ ! 573: m = if_rubaget(&ix->ix_ifuba, len, off, &ix->ix_if); ! 574: if (m) ! 575: ether_input(&ix->ix_if, il, m); ! 576: ! 577: setup: ! 578: /* ! 579: * Reset for next packet if possible. ! 580: * If waiting for transmit command completion, set flag ! 581: * and wait until command completes. ! 582: */ ! 583: if (rp == 0) { ! 584: rp = ix->ix_rrp; ! 585: rp->intr = ixrint; ! 586: ep = rp->element; ! 587: } ! 588: len = ETHERMTU + sizeof(struct ether_header); ! 589: ! 590: /* Now setup to call np driver */ ! 591: /* Initializations of request structure */ ! 592: ! 593: ep->cqe_func = IXC_RECV; /* get frame */ ! 594: ep->cqe_ust0 = ep->cqe_ust1 = NPCLEAR; /* Clear status */ ! 595: ep->cqe_bcnt = len; /* Byte count */ ! 596: ep->cqe_lenrpb = 10; /* RPB length */ ! 597: ep->rpb1 = ix->ix_aid; /* which channel */ ! 598: ep->rpb2 = 65535; /* Timeout */ ! 599: ! 600: ix->ix_flags |= IXF_RCVPENDING; ! 601: ! 602: s = spl5(); ! 603: NpAddCQE(ep, &mp->shmemp->devcq, mp); /* Add CQE to device's queue */ ! 604: splx(s); ! 605: } ! 606: ! 607: ! 608: long ixwatchcount; ! 609: /* ! 610: * Watchdog routine, request statistics from board. ! 611: */ ! 612: ixwatch(unit) ! 613: int unit; ! 614: { ! 615: register struct ix_softc *ix = &ix_softc[unit]; ! 616: register struct ifnet *ifp = &ix->ix_if; ! 617: int s; ! 618: ! 619: ixwatchcount++; ! 620: if (ix->ix_badcqe > 1) { ! 621: ix->ix_badcqe--; /* If errors aren't happening too fast, ! 622: give the board a reprieve */ ! 623: } ! 624: s = splimp(); ! 625: if (ix->ix_flags & IXF_STATPENDING) { ! 626: ifp->if_timer = ix->ix_scaninterval; ! 627: ix->ix_flags |= IXF_OWATCH; ! 628: splx(s); ! 629: return; ! 630: } ! 631: ix->ix_flags |= IXF_STATPENDING; ! 632: if ((ix->ix_if.if_flags & IFF_OACTIVE) == 0) ! 633: (void) ixstart(ifp); ! 634: else ! 635: ix->ix_flags |= IXF_OWATCH; ! 636: if (ix->ix_flags & IXF_RCVPENDING) ! 637: ix->ix_flags |= IXF_RWATCH; ! 638: splx(s); ! 639: ifp->if_timer = ix->ix_scaninterval; ! 640: } ! 641: /* ! 642: * Process an ioctl request. ! 643: */ ! 644: ixioctl(ifp, cmd, data) ! 645: register struct ifnet *ifp; ! 646: int cmd; ! 647: caddr_t data; ! 648: { ! 649: register struct ifaddr *ifa = (struct ifaddr *)data; ! 650: register struct ix_softc *ix = &ix_softc[ifp->if_unit]; ! 651: int s = splimp(), error = 0; ! 652: ! 653: switch (cmd) { ! 654: ! 655: case SIOCSIFADDR: ! 656: ifp->if_flags |= IFF_UP; ! 657: ixinit(ifp->if_unit); ! 658: if ((ifp->if_flags & IFF_UP) == 0) ! 659: return (EBUSY); ! 660: ! 661: switch (ifa->ifa_addr->sa_family) { ! 662: #ifdef INET ! 663: case AF_INET: ! 664: ((struct arpcom *)ifp)->ac_ipaddr = ! 665: IA_SIN(ifa)->sin_addr; ! 666: arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); ! 667: break; ! 668: #endif ! 669: #ifdef NS ! 670: case AF_NS: ! 671: { ! 672: register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); ! 673: ! 674: if (ns_nullhost(*ina)) { ! 675: ina->x_host = * (union ns_host *) ! 676: (ix_softc[ifp->if_unit].ix_addr); ! 677: } else { ! 678: return ! 679: ix_setaddr(ina->x_host.c_host, ifp->if_unit); ! 680: } ! 681: break; ! 682: } ! 683: #endif ! 684: } ! 685: break; ! 686: ! 687: case SIOCSIFFLAGS: ! 688: if ((ifp->if_flags & IFF_UP) == 0 && ! 689: ix->ix_flags & IXF_RUNNING) { ! 690: ix->ix_flags &= ~IXF_RUNNING; ! 691: NpReset(ix->ix_mp, 0); ! 692: } else if (ifp->if_flags & IFF_UP && ! 693: (ix->ix_flags & IXF_RUNNING) == 0) ! 694: ixinit(ifp->if_unit); ! 695: break; ! 696: ! 697: default: ! 698: error = EINVAL; ! 699: } ! 700: splx(s); ! 701: return (error); ! 702: } ! 703: ! 704: /* ! 705: * set ethernet address for unit ! 706: */ ! 707: ix_setaddr(physaddr, unit) ! 708: u_char *physaddr; ! 709: int unit; ! 710: { ! 711: register struct ix_softc *ix = &ix_softc[unit]; ! 712: ! 713: if (! (ix->ix_flags & IXF_RUNNING)) ! 714: return (EBUSY); ! 715: ! 716: /* The following is a big cop out due to the fact that ! 717: Changing the ethernet address resets the dla module, ! 718: so must re-open the channel, anyway. */ ! 719: ! 720: ! 721: bcopy((caddr_t)physaddr, (caddr_t)ix->ix_addr, sizeof ix->ix_addr); ! 722: ix->ix_flags &= ~IXF_RUNNING; ! 723: ix->ix_flags |= IXF_SETADDR; ! 724: ixinit(unit); ! 725: NpKill(ix->ix_mp, ix->ix_rrp); ! 726: } ! 727: static showme() { ! 728: return ((int) &(ix_softc->ix_badcqe)); ! 729: } ! 730: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.