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