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

Defined functions

ix_DoReq defined in line 155; used 5 times
ix_GetReq defined in line 125; used 2 times
ix_setaddr defined in line 791; used 1 times
ixattach defined in line 102; used 2 times
ixcint defined in line 509; used 3 times
ixinit defined in line 360; used 5 times
ixioctl defined in line 728; used 2 times
ixoutput defined in line 215; used 2 times
ixreset defined in line 338; used 3 times
ixrint defined in line 557; used 3 times
ixstart defined in line 459; used 3 times
ixwatch defined in line 707; used 2 times

Defined variables

ix_softc defined in line 92; used 12 times

Defined struct's

ix_softc defined in line 70; used 26 times

Defined macros

ILUNIT defined in line 53; never used
IXF_GOTCQE defined in line 81; used 2 times
IXF_GOTUBA defined in line 77; used 3 times
IXF_OACTIVE defined in line 75; used 6 times
IXF_RCVPENDING defined in line 76; used 2 times
IXF_RUNNING defined in line 78; used 8 times
IXF_SETADDR defined in line 79; used 4 times
IXF_STATPENDING defined in line 80; used 3 times
IXWATCHINTERVAL defined in line 89; used 1 times
ildataaddr defined in line 608; used 2 times
ix_addr defined in line 73; used 6 times
ix_if defined in line 72; used 18 times
Last modified: 1986-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1895
Valid CSS Valid XHTML 1.0 Strict