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