|
|
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.