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