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