|
|
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.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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.