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