|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 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_dmc.c 7.2 (Berkeley) 5/27/88
7: */
8:
9: #include "dmc.h"
10: #if NDMC > 0
11:
12: /*
13: * DMC11 device driver, internet version
14: *
15: * Bill Nesheim
16: * Cornell University
17: *
18: * Lou Salkind
19: * New York University
20: */
21:
22: /* #define DEBUG /* for base table dump on fatal error */
23:
24: #include "../machine/pte.h"
25:
26: #include "param.h"
27: #include "systm.h"
28: #include "mbuf.h"
29: #include "buf.h"
30: #include "ioctl.h" /* must precede tty.h */
31: #include "tty.h"
32: #include "protosw.h"
33: #include "socket.h"
34: #include "syslog.h"
35: #include "vmmac.h"
36: #include "errno.h"
37:
38: #include "../net/if.h"
39: #include "../net/netisr.h"
40: #include "../net/route.h"
41:
42: #ifdef INET
43: #include "../netinet/in.h"
44: #include "../netinet/in_systm.h"
45: #include "../netinet/in_var.h"
46: #include "../netinet/ip.h"
47: #endif
48:
49: #include "../vax/cpu.h"
50: #include "../vax/mtpr.h"
51: #include "if_uba.h"
52: #include "if_dmc.h"
53: #include "../vaxuba/ubareg.h"
54: #include "../vaxuba/ubavar.h"
55:
56: #include "../h/time.h"
57: #include "../h/kernel.h"
58:
59: /*
60: * output timeout value, sec.; should depend on line speed.
61: */
62: int dmc_timeout = 20;
63:
64: /*
65: * Driver information for auto-configuration stuff.
66: */
67: int dmcprobe(), dmcattach(), dmcinit(), dmcioctl();
68: int dmcoutput(), dmcreset(), dmctimeout();
69: struct uba_device *dmcinfo[NDMC];
70: u_short dmcstd[] = { 0 };
71: struct uba_driver dmcdriver =
72: { dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo };
73:
74: #define NRCV 7
75: #define NXMT 3
76: #define NCMDS (NRCV+NXMT+4) /* size of command queue */
77:
78: #define printd if(dmcdebug)printf
79: int dmcdebug = 0;
80:
81: /* error reporting intervals */
82: #define DMC_RPNBFS 50
83: #define DMC_RPDSC 1
84: #define DMC_RPTMO 10
85: #define DMC_RPDCK 10
86:
87: struct dmc_command {
88: char qp_cmd; /* command */
89: short qp_ubaddr; /* buffer address */
90: short qp_cc; /* character count || XMEM */
91: struct dmc_command *qp_next; /* next command on queue */
92: };
93:
94: struct dmcbufs {
95: int ubinfo; /* from uballoc */
96: short cc; /* buffer size */
97: short flags; /* access control */
98: };
99: #define DBUF_OURS 0 /* buffer is available */
100: #define DBUF_DMCS 1 /* buffer claimed by somebody */
101: #define DBUF_XMIT 4 /* transmit buffer */
102: #define DBUF_RCV 8 /* receive buffer */
103:
104:
105: /*
106: * DMC software status per interface.
107: *
108: * Each interface is referenced by a network interface structure,
109: * sc_if, which the routing code uses to locate the interface.
110: * This structure contains the output queue for the interface, its address, ...
111: * We also have, for each interface, a set of 7 UBA interface structures
112: * for each, which
113: * contain information about the UNIBUS resources held by the interface:
114: * map registers, buffered data paths, etc. Information is cached in this
115: * structure for use by the if_uba.c routines in running the interface
116: * efficiently.
117: */
118: struct dmc_softc {
119: struct ifnet sc_if; /* network-visible interface */
120: short sc_oused; /* output buffers currently in use */
121: short sc_iused; /* input buffers given to DMC */
122: short sc_flag; /* flags */
123: int sc_ubinfo; /* UBA mapping info for base table */
124: int sc_errors[4]; /* non-fatal error counters */
125: #define sc_datck sc_errors[0]
126: #define sc_timeo sc_errors[1]
127: #define sc_nobuf sc_errors[2]
128: #define sc_disc sc_errors[3]
129: struct dmcbufs sc_rbufs[NRCV]; /* receive buffer info */
130: struct dmcbufs sc_xbufs[NXMT]; /* transmit buffer info */
131: struct ifubinfo sc_ifuba; /* UNIBUS resources */
132: struct ifrw sc_ifr[NRCV]; /* UNIBUS receive buffer maps */
133: struct ifxmt sc_ifw[NXMT]; /* UNIBUS receive buffer maps */
134: /* command queue stuff */
135: struct dmc_command sc_cmdbuf[NCMDS];
136: struct dmc_command *sc_qhead; /* head of command queue */
137: struct dmc_command *sc_qtail; /* tail of command queue */
138: struct dmc_command *sc_qactive; /* command in progress */
139: struct dmc_command *sc_qfreeh; /* head of list of free cmd buffers */
140: struct dmc_command *sc_qfreet; /* tail of list of free cmd buffers */
141: /* end command queue stuff */
142: } dmc_softc[NDMC];
143:
144: /* flags */
145: #define DMC_RUNNING 0x01 /* device initialized */
146: #define DMC_BMAPPED 0x02 /* base table mapped */
147: #define DMC_RESTART 0x04 /* software restart in progress */
148: #define DMC_ONLINE 0x08 /* device running (had a RDYO) */
149:
150: struct dmc_base {
151: short d_base[128]; /* DMC base table */
152: } dmc_base[NDMC];
153:
154: /* queue manipulation macros */
155: #define QUEUE_AT_HEAD(qp, head, tail) \
156: (qp)->qp_next = (head); \
157: (head) = (qp); \
158: if ((tail) == (struct dmc_command *) 0) \
159: (tail) = (head)
160:
161: #define QUEUE_AT_TAIL(qp, head, tail) \
162: if ((tail)) \
163: (tail)->qp_next = (qp); \
164: else \
165: (head) = (qp); \
166: (qp)->qp_next = (struct dmc_command *) 0; \
167: (tail) = (qp)
168:
169: #define DEQUEUE(head, tail) \
170: (head) = (head)->qp_next;\
171: if ((head) == (struct dmc_command *) 0)\
172: (tail) = (head)
173:
174: dmcprobe(reg)
175: caddr_t reg;
176: {
177: register int br, cvec;
178: register struct dmcdevice *addr = (struct dmcdevice *)reg;
179: register int i;
180:
181: #ifdef lint
182: br = 0; cvec = br; br = cvec;
183: dmcrint(0); dmcxint(0);
184: #endif
185: addr->bsel1 = DMC_MCLR;
186: for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
187: ;
188: if ((addr->bsel1 & DMC_RUN) == 0) {
189: printf("dmcprobe: can't start device\n" );
190: return (0);
191: }
192: addr->bsel0 = DMC_RQI|DMC_IEI;
193: /* let's be paranoid */
194: addr->bsel0 |= DMC_RQI|DMC_IEI;
195: DELAY(1000000);
196: addr->bsel1 = DMC_MCLR;
197: for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
198: ;
199: return (1);
200: }
201:
202: /*
203: * Interface exists: make available by filling in network interface
204: * record. System will initialize the interface when it is ready
205: * to accept packets.
206: */
207: dmcattach(ui)
208: register struct uba_device *ui;
209: {
210: register struct dmc_softc *sc = &dmc_softc[ui->ui_unit];
211:
212: sc->sc_if.if_unit = ui->ui_unit;
213: sc->sc_if.if_name = "dmc";
214: sc->sc_if.if_mtu = DMCMTU;
215: sc->sc_if.if_init = dmcinit;
216: sc->sc_if.if_output = dmcoutput;
217: sc->sc_if.if_ioctl = dmcioctl;
218: sc->sc_if.if_reset = dmcreset;
219: sc->sc_if.if_watchdog = dmctimeout;
220: sc->sc_if.if_flags = IFF_POINTOPOINT;
221: sc->sc_ifuba.iff_flags = UBA_CANTWAIT;
222:
223: if_attach(&sc->sc_if);
224: }
225:
226: /*
227: * Reset of interface after UNIBUS reset.
228: * If interface is on specified UBA, reset its state.
229: */
230: dmcreset(unit, uban)
231: int unit, uban;
232: {
233: register struct uba_device *ui;
234: register struct dmc_softc *sc = &dmc_softc[unit];
235:
236: if (unit >= NDMC || (ui = dmcinfo[unit]) == 0 || ui->ui_alive == 0 ||
237: ui->ui_ubanum != uban)
238: return;
239: printf(" dmc%d", unit);
240: sc->sc_flag = 0;
241: sc->sc_if.if_flags &= ~IFF_RUNNING;
242: dmcinit(unit);
243: }
244:
245: /*
246: * Initialization of interface; reinitialize UNIBUS usage.
247: */
248: dmcinit(unit)
249: int unit;
250: {
251: register struct dmc_softc *sc = &dmc_softc[unit];
252: register struct uba_device *ui = dmcinfo[unit];
253: register struct dmcdevice *addr;
254: register struct ifnet *ifp = &sc->sc_if;
255: register struct ifrw *ifrw;
256: register struct ifxmt *ifxp;
257: register struct dmcbufs *rp;
258: register struct dmc_command *qp;
259: struct ifaddr *ifa;
260: int base;
261: int s;
262:
263: addr = (struct dmcdevice *)ui->ui_addr;
264:
265: /*
266: * Check to see that an address has been set
267: * (both local and destination for an address family).
268: */
269: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
270: if (ifa->ifa_addr.sa_family && ifa->ifa_dstaddr.sa_family)
271: break;
272: if (ifa == (struct ifaddr *) 0)
273: return;
274:
275: if ((addr->bsel1&DMC_RUN) == 0) {
276: printf("dmcinit: DMC not running\n");
277: ifp->if_flags &= ~IFF_UP;
278: return;
279: }
280: /* map base table */
281: if ((sc->sc_flag & DMC_BMAPPED) == 0) {
282: sc->sc_ubinfo = uballoc(ui->ui_ubanum,
283: (caddr_t)&dmc_base[unit], sizeof (struct dmc_base), 0);
284: sc->sc_flag |= DMC_BMAPPED;
285: }
286: /* initialize UNIBUS resources */
287: sc->sc_iused = sc->sc_oused = 0;
288: if ((ifp->if_flags & IFF_RUNNING) == 0) {
289: if (if_ubaminit(&sc->sc_ifuba, ui->ui_ubanum,
290: sizeof(struct dmc_header), (int)btoc(DMCMTU),
291: sc->sc_ifr, NRCV, sc->sc_ifw, NXMT) == 0) {
292: printf("dmc%d: can't allocate uba resources\n", unit);
293: ifp->if_flags &= ~IFF_UP;
294: return;
295: }
296: ifp->if_flags |= IFF_RUNNING;
297: }
298: sc->sc_flag &= ~DMC_ONLINE;
299: sc->sc_flag |= DMC_RUNNING;
300: /*
301: * Limit packets enqueued until we see if we're on the air.
302: */
303: ifp->if_snd.ifq_maxlen = 3;
304:
305: /* initialize buffer pool */
306: /* receives */
307: ifrw = &sc->sc_ifr[0];
308: for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
309: rp->ubinfo = ifrw->ifrw_info & 0x3ffff;
310: rp->cc = DMCMTU + sizeof (struct dmc_header);
311: rp->flags = DBUF_OURS|DBUF_RCV;
312: ifrw++;
313: }
314: /* transmits */
315: ifxp = &sc->sc_ifw[0];
316: for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) {
317: rp->ubinfo = ifxp->ifw_info & 0x3ffff;
318: rp->cc = 0;
319: rp->flags = DBUF_OURS|DBUF_XMIT;
320: ifxp++;
321: }
322:
323: /* set up command queues */
324: sc->sc_qfreeh = sc->sc_qfreet
325: = sc->sc_qhead = sc->sc_qtail = sc->sc_qactive =
326: (struct dmc_command *)0;
327: /* set up free command buffer list */
328: for (qp = &sc->sc_cmdbuf[0]; qp < &sc->sc_cmdbuf[NCMDS]; qp++) {
329: QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);
330: }
331:
332: /* base in */
333: base = sc->sc_ubinfo & 0x3ffff;
334: dmcload(sc, DMC_BASEI, base, (base>>2) & DMC_XMEM);
335: /* specify half duplex operation, flags tell if primary */
336: /* or secondary station */
337: if (ui->ui_flags == 0)
338: /* use DDCMP mode in full duplex */
339: dmcload(sc, DMC_CNTLI, 0, 0);
340: else if (ui->ui_flags == 1)
341: /* use MAINTENENCE mode */
342: dmcload(sc, DMC_CNTLI, 0, DMC_MAINT );
343: else if (ui->ui_flags == 2)
344: /* use DDCMP half duplex as primary station */
345: dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX);
346: else if (ui->ui_flags == 3)
347: /* use DDCMP half duplex as secondary station */
348: dmcload(sc, DMC_CNTLI, 0, DMC_HDPLX | DMC_SEC);
349:
350: /* enable operation done interrupts */
351: while ((addr->bsel2 & DMC_IEO) == 0)
352: addr->bsel2 |= DMC_IEO;
353: s = spl5();
354: /* queue first NRCV buffers for DMC to fill */
355: for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
356: rp->flags |= DBUF_DMCS;
357: dmcload(sc, DMC_READ, rp->ubinfo,
358: (((rp->ubinfo>>2)&DMC_XMEM) | rp->cc));
359: sc->sc_iused++;
360: }
361: splx(s);
362: }
363:
364: /*
365: * Start output on interface. Get another datagram
366: * to send from the interface queue and map it to
367: * the interface before starting output.
368: *
369: * Must be called at spl 5
370: */
371: dmcstart(unit)
372: int unit;
373: {
374: register struct dmc_softc *sc = &dmc_softc[unit];
375: struct mbuf *m;
376: register struct dmcbufs *rp;
377: register int n;
378:
379: /*
380: * Dequeue up to NXMT requests and map them to the UNIBUS.
381: * If no more requests, or no dmc buffers available, just return.
382: */
383: n = 0;
384: for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++ ) {
385: /* find an available buffer */
386: if ((rp->flags & DBUF_DMCS) == 0) {
387: IF_DEQUEUE(&sc->sc_if.if_snd, m);
388: if (m == 0)
389: return;
390: /* mark it dmcs */
391: rp->flags |= (DBUF_DMCS);
392: /*
393: * Have request mapped to UNIBUS for transmission
394: * and start the output.
395: */
396: rp->cc = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[n], m);
397: rp->cc &= DMC_CCOUNT;
398: if (++sc->sc_oused == 1)
399: sc->sc_if.if_timer = dmc_timeout;
400: dmcload(sc, DMC_WRITE, rp->ubinfo,
401: rp->cc | ((rp->ubinfo>>2)&DMC_XMEM));
402: }
403: n++;
404: }
405: }
406:
407: /*
408: * Utility routine to load the DMC device registers.
409: */
410: dmcload(sc, type, w0, w1)
411: register struct dmc_softc *sc;
412: int type, w0, w1;
413: {
414: register struct dmcdevice *addr;
415: register int unit, sps;
416: register struct dmc_command *qp;
417:
418: unit = sc - dmc_softc;
419: addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
420: sps = spl5();
421:
422: /* grab a command buffer from the free list */
423: if ((qp = sc->sc_qfreeh) == (struct dmc_command *)0)
424: panic("dmc command queue overflow");
425: DEQUEUE(sc->sc_qfreeh, sc->sc_qfreet);
426:
427: /* fill in requested info */
428: qp->qp_cmd = (type | DMC_RQI);
429: qp->qp_ubaddr = w0;
430: qp->qp_cc = w1;
431:
432: if (sc->sc_qactive) { /* command in progress */
433: if (type == DMC_READ) {
434: QUEUE_AT_HEAD(qp, sc->sc_qhead, sc->sc_qtail);
435: } else {
436: QUEUE_AT_TAIL(qp, sc->sc_qhead, sc->sc_qtail);
437: }
438: } else { /* command port free */
439: sc->sc_qactive = qp;
440: addr->bsel0 = qp->qp_cmd;
441: dmcrint(unit);
442: }
443: splx(sps);
444: }
445:
446: /*
447: * DMC interface receiver interrupt.
448: * Ready to accept another command,
449: * pull one off the command queue.
450: */
451: dmcrint(unit)
452: int unit;
453: {
454: register struct dmc_softc *sc;
455: register struct dmcdevice *addr;
456: register struct dmc_command *qp;
457: register int n;
458:
459: addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
460: sc = &dmc_softc[unit];
461: if ((qp = sc->sc_qactive) == (struct dmc_command *) 0) {
462: printf("dmc%d: dmcrint no command\n", unit);
463: return;
464: }
465: while (addr->bsel0&DMC_RDYI) {
466: addr->sel4 = qp->qp_ubaddr;
467: addr->sel6 = qp->qp_cc;
468: addr->bsel0 &= ~(DMC_IEI|DMC_RQI);
469: /* free command buffer */
470: QUEUE_AT_HEAD(qp, sc->sc_qfreeh, sc->sc_qfreet);
471: while (addr->bsel0 & DMC_RDYI) {
472: /*
473: * Can't check for RDYO here 'cause
474: * this routine isn't reentrant!
475: */
476: DELAY(5);
477: }
478: /* move on to next command */
479: if ((sc->sc_qactive = sc->sc_qhead) == (struct dmc_command *)0)
480: break; /* all done */
481: /* more commands to do, start the next one */
482: qp = sc->sc_qactive;
483: DEQUEUE(sc->sc_qhead, sc->sc_qtail);
484: addr->bsel0 = qp->qp_cmd;
485: n = RDYSCAN;
486: while (n-- > 0)
487: if ((addr->bsel0&DMC_RDYI) || (addr->bsel2&DMC_RDYO))
488: break;
489: }
490: if (sc->sc_qactive) {
491: addr->bsel0 |= DMC_IEI|DMC_RQI;
492: /* VMS does it twice !*$%@# */
493: addr->bsel0 |= DMC_IEI|DMC_RQI;
494: }
495:
496: }
497:
498: /*
499: * DMC interface transmitter interrupt.
500: * A transfer may have completed, check for errors.
501: * If it was a read, notify appropriate protocol.
502: * If it was a write, pull the next one off the queue.
503: */
504: dmcxint(unit)
505: int unit;
506: {
507: register struct dmc_softc *sc;
508: register struct ifnet *ifp;
509: struct uba_device *ui = dmcinfo[unit];
510: struct dmcdevice *addr;
511: struct mbuf *m;
512: struct ifqueue *inq;
513: int arg, pkaddr, cmd, len, s;
514: register struct ifrw *ifrw;
515: register struct dmcbufs *rp;
516: register struct ifxmt *ifxp;
517: struct dmc_header *dh;
518: int off, resid;
519:
520: addr = (struct dmcdevice *)ui->ui_addr;
521: sc = &dmc_softc[unit];
522: ifp = &sc->sc_if;
523:
524: while (addr->bsel2 & DMC_RDYO) {
525:
526: cmd = addr->bsel2 & 0xff;
527: arg = addr->sel6 & 0xffff;
528: /* reconstruct UNIBUS address of buffer returned to us */
529: pkaddr = ((arg&DMC_XMEM)<<2) | (addr->sel4 & 0xffff);
530: /* release port */
531: addr->bsel2 &= ~DMC_RDYO;
532: switch (cmd & 07) {
533:
534: case DMC_OUR:
535: /*
536: * A read has completed.
537: * Pass packet to type specific
538: * higher-level input routine.
539: */
540: ifp->if_ipackets++;
541: /* find location in dmcuba struct */
542: ifrw= &sc->sc_ifr[0];
543: for (rp = &sc->sc_rbufs[0]; rp < &sc->sc_rbufs[NRCV]; rp++) {
544: if(rp->ubinfo == pkaddr)
545: break;
546: ifrw++;
547: }
548: if (rp >= &sc->sc_rbufs[NRCV])
549: panic("dmc rcv");
550: if ((rp->flags & DBUF_DMCS) == 0)
551: printf("dmc%d: done unalloc rbuf\n", unit);
552:
553: len = (arg & DMC_CCOUNT) - sizeof (struct dmc_header);
554: if (len < 0 || len > DMCMTU) {
555: ifp->if_ierrors++;
556: printd("dmc%d: bad rcv pkt addr 0x%x len 0x%x\n",
557: unit, pkaddr, len);
558: goto setup;
559: }
560: /*
561: * Deal with trailer protocol: if type is trailer
562: * get true type from first 16-bit word past data.
563: * Remember that type was trailer by setting off.
564: */
565: dh = (struct dmc_header *)ifrw->ifrw_addr;
566: dh->dmc_type = ntohs((u_short)dh->dmc_type);
567: #define dmcdataaddr(dh, off, type) ((type)(((caddr_t)((dh)+1)+(off))))
568: if (dh->dmc_type >= DMC_TRAILER &&
569: dh->dmc_type < DMC_TRAILER+DMC_NTRAILER) {
570: off = (dh->dmc_type - DMC_TRAILER) * 512;
571: if (off >= DMCMTU)
572: goto setup; /* sanity */
573: dh->dmc_type = ntohs(*dmcdataaddr(dh, off, u_short *));
574: resid = ntohs(*(dmcdataaddr(dh, off+2, u_short *)));
575: if (off + resid > len)
576: goto setup; /* sanity */
577: len = off + resid;
578: } else
579: off = 0;
580: if (len == 0)
581: goto setup;
582:
583: /*
584: * Pull packet off interface. Off is nonzero if
585: * packet has trailing header; dmc_get will then
586: * force this header information to be at the front,
587: * but we still have to drop the type and length
588: * which are at the front of any trailer data.
589: */
590: m = if_ubaget(&sc->sc_ifuba, ifrw, len, off, ifp);
591: if (m == 0)
592: goto setup;
593: if (off) {
594: ifp = *(mtod(m, struct ifnet **));
595: m->m_off += 2 * sizeof (u_short);
596: m->m_len -= 2 * sizeof (u_short);
597: *(mtod(m, struct ifnet **)) = ifp;
598: }
599: switch (dh->dmc_type) {
600:
601: #ifdef INET
602: case DMC_IPTYPE:
603: schednetisr(NETISR_IP);
604: inq = &ipintrq;
605: break;
606: #endif
607: default:
608: m_freem(m);
609: goto setup;
610: }
611:
612: s = splimp();
613: if (IF_QFULL(inq)) {
614: IF_DROP(inq);
615: m_freem(m);
616: } else
617: IF_ENQUEUE(inq, m);
618: splx(s);
619:
620: setup:
621: /* is this needed? */
622: rp->ubinfo = ifrw->ifrw_info & 0x3ffff;
623:
624: dmcload(sc, DMC_READ, rp->ubinfo,
625: ((rp->ubinfo >> 2) & DMC_XMEM) | rp->cc);
626: break;
627:
628: case DMC_OUX:
629: /*
630: * A write has completed, start another
631: * transfer if there is more data to send.
632: */
633: ifp->if_opackets++;
634: /* find associated dmcbuf structure */
635: ifxp = &sc->sc_ifw[0];
636: for (rp = &sc->sc_xbufs[0]; rp < &sc->sc_xbufs[NXMT]; rp++) {
637: if(rp->ubinfo == pkaddr)
638: break;
639: ifxp++;
640: }
641: if (rp >= &sc->sc_xbufs[NXMT]) {
642: printf("dmc%d: bad packet address 0x%x\n",
643: unit, pkaddr);
644: break;
645: }
646: if ((rp->flags & DBUF_DMCS) == 0)
647: printf("dmc%d: unallocated packet 0x%x\n",
648: unit, pkaddr);
649: /* mark buffer free */
650: if (ifxp->ifw_xtofree) {
651: (void)m_freem(ifxp->ifw_xtofree);
652: ifxp->ifw_xtofree = 0;
653: }
654: rp->flags &= ~DBUF_DMCS;
655: if (--sc->sc_oused == 0)
656: sc->sc_if.if_timer = 0;
657: else
658: sc->sc_if.if_timer = dmc_timeout;
659: if ((sc->sc_flag & DMC_ONLINE) == 0) {
660: extern int ifqmaxlen;
661:
662: /*
663: * We're on the air.
664: * Open the queue to the usual value.
665: */
666: sc->sc_flag |= DMC_ONLINE;
667: ifp->if_snd.ifq_maxlen = ifqmaxlen;
668: }
669: break;
670:
671: case DMC_CNTLO:
672: arg &= DMC_CNTMASK;
673: if (arg & DMC_FATAL) {
674: if (arg != DMC_START)
675: log(LOG_ERR,
676: "dmc%d: fatal error, flags=%b\n",
677: unit, arg, CNTLO_BITS);
678: dmcrestart(unit);
679: break;
680: }
681: /* ACCUMULATE STATISTICS */
682: switch(arg) {
683: case DMC_NOBUFS:
684: ifp->if_ierrors++;
685: if ((sc->sc_nobuf++ % DMC_RPNBFS) == 0)
686: goto report;
687: break;
688: case DMC_DISCONN:
689: if ((sc->sc_disc++ % DMC_RPDSC) == 0)
690: goto report;
691: break;
692: case DMC_TIMEOUT:
693: if ((sc->sc_timeo++ % DMC_RPTMO) == 0)
694: goto report;
695: break;
696: case DMC_DATACK:
697: ifp->if_oerrors++;
698: if ((sc->sc_datck++ % DMC_RPDCK) == 0)
699: goto report;
700: break;
701: default:
702: goto report;
703: }
704: break;
705: report:
706: printd("dmc%d: soft error, flags=%b\n", unit,
707: arg, CNTLO_BITS);
708: if ((sc->sc_flag & DMC_RESTART) == 0) {
709: /*
710: * kill off the dmc to get things
711: * going again by generating a
712: * procedure error
713: */
714: sc->sc_flag |= DMC_RESTART;
715: arg = sc->sc_ubinfo & 0x3ffff;
716: dmcload(sc, DMC_BASEI, arg, (arg>>2)&DMC_XMEM);
717: }
718: break;
719:
720: default:
721: printf("dmc%d: bad control %o\n", unit, cmd);
722: break;
723: }
724: }
725: dmcstart(unit);
726: return;
727: }
728:
729: /*
730: * DMC output routine.
731: * Encapsulate a packet of type family for the dmc.
732: * Use trailer local net encapsulation if enough data in first
733: * packet leaves a multiple of 512 bytes of data in remainder.
734: */
735: dmcoutput(ifp, m0, dst)
736: register struct ifnet *ifp;
737: register struct mbuf *m0;
738: struct sockaddr *dst;
739: {
740: int type, error, s;
741: register struct mbuf *m = m0;
742: register struct dmc_header *dh;
743: register int off;
744:
745: if ((ifp->if_flags & IFF_UP) == 0) {
746: error = ENETDOWN;
747: goto bad;
748: }
749:
750: switch (dst->sa_family) {
751: #ifdef INET
752: case AF_INET:
753: off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
754: if ((ifp->if_flags & IFF_NOTRAILERS) == 0)
755: if (off > 0 && (off & 0x1ff) == 0 &&
756: m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
757: type = DMC_TRAILER + (off>>9);
758: m->m_off -= 2 * sizeof (u_short);
759: m->m_len += 2 * sizeof (u_short);
760: *mtod(m, u_short *) = htons((u_short)DMC_IPTYPE);
761: *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
762: goto gottrailertype;
763: }
764: type = DMC_IPTYPE;
765: off = 0;
766: goto gottype;
767: #endif
768:
769: case AF_UNSPEC:
770: dh = (struct dmc_header *)dst->sa_data;
771: type = dh->dmc_type;
772: goto gottype;
773:
774: default:
775: printf("dmc%d: can't handle af%d\n", ifp->if_unit,
776: dst->sa_family);
777: error = EAFNOSUPPORT;
778: goto bad;
779: }
780:
781: gottrailertype:
782: /*
783: * Packet to be sent as a trailer; move first packet
784: * (control information) to end of chain.
785: */
786: while (m->m_next)
787: m = m->m_next;
788: m->m_next = m0;
789: m = m0->m_next;
790: m0->m_next = 0;
791: m0 = m;
792:
793: gottype:
794: /*
795: * Add local network header
796: * (there is space for a uba on a vax to step on)
797: */
798: if (m->m_off > MMAXOFF ||
799: MMINOFF + sizeof(struct dmc_header) > m->m_off) {
800: m = m_get(M_DONTWAIT, MT_HEADER);
801: if (m == 0) {
802: error = ENOBUFS;
803: goto bad;
804: }
805: m->m_next = m0;
806: m->m_off = MMINOFF;
807: m->m_len = sizeof (struct dmc_header);
808: } else {
809: m->m_off -= sizeof (struct dmc_header);
810: m->m_len += sizeof (struct dmc_header);
811: }
812: dh = mtod(m, struct dmc_header *);
813: dh->dmc_type = htons((u_short)type);
814:
815: /*
816: * Queue message on interface, and start output if interface
817: * not yet active.
818: */
819: s = splimp();
820: if (IF_QFULL(&ifp->if_snd)) {
821: IF_DROP(&ifp->if_snd);
822: m_freem(m);
823: splx(s);
824: return (ENOBUFS);
825: }
826: IF_ENQUEUE(&ifp->if_snd, m);
827: dmcstart(ifp->if_unit);
828: splx(s);
829: return (0);
830:
831: bad:
832: m_freem(m0);
833: return (error);
834: }
835:
836:
837: /*
838: * Process an ioctl request.
839: */
840: /* ARGSUSED */
841: dmcioctl(ifp, cmd, data)
842: register struct ifnet *ifp;
843: int cmd;
844: caddr_t data;
845: {
846: int s = splimp(), error = 0;
847: register struct dmc_softc *sc = &dmc_softc[ifp->if_unit];
848:
849: switch (cmd) {
850:
851: case SIOCSIFADDR:
852: ifp->if_flags |= IFF_UP;
853: if ((ifp->if_flags & IFF_RUNNING) == 0)
854: dmcinit(ifp->if_unit);
855: break;
856:
857: case SIOCSIFDSTADDR:
858: if ((ifp->if_flags & IFF_RUNNING) == 0)
859: dmcinit(ifp->if_unit);
860: break;
861:
862: case SIOCSIFFLAGS:
863: if ((ifp->if_flags & IFF_UP) == 0 &&
864: sc->sc_flag & DMC_RUNNING)
865: dmcdown(ifp->if_unit);
866: else if (ifp->if_flags & IFF_UP &&
867: (sc->sc_flag & DMC_RUNNING) == 0)
868: dmcrestart(ifp->if_unit);
869: break;
870:
871: default:
872: error = EINVAL;
873: }
874: splx(s);
875: return (error);
876: }
877:
878: /*
879: * Restart after a fatal error.
880: * Clear device and reinitialize.
881: */
882: dmcrestart(unit)
883: int unit;
884: {
885: register struct dmc_softc *sc = &dmc_softc[unit];
886: register struct dmcdevice *addr;
887: register int i;
888: int s;
889:
890: #ifdef DEBUG
891: /* dump base table */
892: printf("dmc%d base table:\n", unit);
893: for (i = 0; i < sizeof (struct dmc_base); i++)
894: printf("%o\n" ,dmc_base[unit].d_base[i]);
895: #endif
896:
897: dmcdown(unit);
898:
899: /*
900: * Let the DMR finish the MCLR. At 1 Mbit, it should do so
901: * in about a max of 6.4 milliseconds with diagnostics enabled.
902: */
903: addr = (struct dmcdevice *)(dmcinfo[unit]->ui_addr);
904: for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
905: ;
906: /* Did the timer expire or did the DMR finish? */
907: if ((addr->bsel1 & DMC_RUN) == 0) {
908: log(LOG_ERR, "dmc%d: M820 Test Failed\n", unit);
909: return;
910: }
911:
912: /* restart DMC */
913: dmcinit(unit);
914: sc->sc_flag &= ~DMC_RESTART;
915: s = spl5();
916: dmcstart(unit);
917: splx(s);
918: sc->sc_if.if_collisions++; /* why not? */
919: }
920:
921: /*
922: * Reset a device and mark down.
923: * Flush output queue and drop queue limit.
924: */
925: dmcdown(unit)
926: int unit;
927: {
928: register struct dmc_softc *sc = &dmc_softc[unit];
929: register struct ifxmt *ifxp;
930:
931: ((struct dmcdevice *)(dmcinfo[unit]->ui_addr))->bsel1 = DMC_MCLR;
932: sc->sc_flag &= ~(DMC_RUNNING | DMC_ONLINE);
933:
934: for (ifxp = sc->sc_ifw; ifxp < &sc->sc_ifw[NXMT]; ifxp++) {
935: if (ifxp->ifw_xtofree) {
936: (void) m_freem(ifxp->ifw_xtofree);
937: ifxp->ifw_xtofree = 0;
938: }
939: }
940: if_qflush(&sc->sc_if.if_snd);
941: }
942:
943: /*
944: * Watchdog timeout to see that transmitted packets don't
945: * lose interrupts. The device has to be online (the first
946: * transmission may block until the other side comes up).
947: */
948: dmctimeout(unit)
949: int unit;
950: {
951: register struct dmc_softc *sc;
952: struct dmcdevice *addr;
953:
954: sc = &dmc_softc[unit];
955: if (sc->sc_flag & DMC_ONLINE) {
956: addr = (struct dmcdevice *)(dmcinfo[unit]->ui_addr);
957: log(LOG_ERR, "dmc%d: output timeout, bsel0=%b bsel2=%b\n",
958: unit, addr->bsel0 & 0xff, DMC0BITS,
959: addr->bsel2 & 0xff, DMC2BITS);
960: dmcrestart(unit);
961: }
962: }
963: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.