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