xref: /csrg-svn/sys/vax/if/if_dmc.c (revision 5725)
1*5725Sroot /*	if_dmc.c	4.1	82/02/08	*/
2*5725Sroot 
3*5725Sroot #include "dmc.h"
4*5725Sroot #if NDMC > 0
5*5725Sroot #define printd if(dmcdebug)printf
6*5725Sroot int dmcdebug = 1;
7*5725Sroot /*
8*5725Sroot  * DMC11 device driver, internet version
9*5725Sroot  *
10*5725Sroot  * TODO
11*5725Sroot  *	allow more than one outstanding read or write.
12*5725Sroot  */
13*5725Sroot 
14*5725Sroot #include "../h/param.h"
15*5725Sroot #include "../h/systm.h"
16*5725Sroot #include "../h/mbuf.h"
17*5725Sroot #include "../h/pte.h"
18*5725Sroot #include "../h/buf.h"
19*5725Sroot #include "../h/tty.h"
20*5725Sroot #include "../h/protosw.h"
21*5725Sroot #include "../h/socket.h"
22*5725Sroot #include "../h/ubareg.h"
23*5725Sroot #include "../h/ubavar.h"
24*5725Sroot #include "../h/cpu.h"
25*5725Sroot #include "../h/mtpr.h"
26*5725Sroot #include "../h/vmmac.h"
27*5725Sroot #include "../net/in.h"
28*5725Sroot #include "../net/in_systm.h"
29*5725Sroot #include "../net/if.h"
30*5725Sroot #include "../net/if_uba.h"
31*5725Sroot #include "../net/ip.h"
32*5725Sroot #include "../net/ip_var.h"
33*5725Sroot 
34*5725Sroot /*
35*5725Sroot  * Driver information for auto-configuration stuff.
36*5725Sroot  */
37*5725Sroot int	dmcprobe(), dmcattach(), dmcinit(), dmcoutput(), dmcreset();
38*5725Sroot struct	uba_device *dmcinfo[NDMC];
39*5725Sroot u_short	dmcstd[] = { 0 };
40*5725Sroot struct	uba_driver dmcdriver =
41*5725Sroot 	{ dmcprobe, 0, dmcattach, 0, dmcstd, "dmc", dmcinfo };
42*5725Sroot 
43*5725Sroot struct dmcdevice {
44*5725Sroot 	union {
45*5725Sroot 		char	b[8];
46*5725Sroot 		short	w[4];
47*5725Sroot 	} un;
48*5725Sroot };
49*5725Sroot 
50*5725Sroot #define	bsel0	un.b[0]
51*5725Sroot #define	bsel1	un.b[1]
52*5725Sroot #define	bsel2	un.b[2]
53*5725Sroot #define	bsel3	un.b[3]
54*5725Sroot #define	bsel4	un.b[4]
55*5725Sroot #define	bsel5	un.b[5]
56*5725Sroot #define	bsel6	un.b[6]
57*5725Sroot #define	bsel7	un.b[7]
58*5725Sroot #define	sel0	un.w[0]
59*5725Sroot #define	sel2	un.w[1]
60*5725Sroot #define	sel4	un.w[2]
61*5725Sroot #define	sel6	un.w[3]
62*5725Sroot 
63*5725Sroot #define	DMCMTU	(2048)
64*5725Sroot 
65*5725Sroot #define RDYSCAN	16	/* loop delay for RDYI after RQI */
66*5725Sroot 
67*5725Sroot /* defines for bsel0 */
68*5725Sroot #define	DMC_BACCI	0
69*5725Sroot #define	DMC_CNTLI	1
70*5725Sroot #define	DMC_PERR	2
71*5725Sroot #define	DMC_BASEI	3
72*5725Sroot #define	DMC_WRITE	0		/* transmit block */
73*5725Sroot #define	DMC_READ	4		/* read block */
74*5725Sroot #define	DMC_RQI		0040		/* port request bit */
75*5725Sroot #define	DMC_IEI		0100		/* enable input interrupts */
76*5725Sroot #define	DMC_RDYI	0200		/* port ready */
77*5725Sroot 
78*5725Sroot /* defines for bsel1 */
79*5725Sroot #define	DMC_MCLR	0100		/* DMC11 Master Clear */
80*5725Sroot #define	DMC_RUN		0200		/* clock running */
81*5725Sroot 
82*5725Sroot /* defines for bsel2 */
83*5725Sroot #define	DMC_BACCO	0
84*5725Sroot #define	DMC_CNTLO	1
85*5725Sroot #define	DMC_OUX		0		/* transmit block */
86*5725Sroot #define	DMC_OUR		4		/* read block */
87*5725Sroot #define	DMC_IEO		0100		/* enable output interrupts */
88*5725Sroot #define	DMC_RDYO	0200		/* port available */
89*5725Sroot 
90*5725Sroot /* defines for CNTLI mode */
91*5725Sroot #define	DMC_HDPLX	02000		/* half duplex DDCMP operation */
92*5725Sroot #define	DMC_SEC		04000		/* half duplex secondary station */
93*5725Sroot #define	DMC_MAINT	00400		/* enter maintenance mode */
94*5725Sroot 
95*5725Sroot /* defines for BACCI/O and BASEI mode */
96*5725Sroot #define	DMC_XMEM	0140000		/* xmem bit position */
97*5725Sroot #define	DMC_CCOUNT	0037777		/* character count mask */
98*5725Sroot #define	DMC_RESUME	0002000		/* resume (BASEI only) */
99*5725Sroot 
100*5725Sroot /* defines for CNTLO */
101*5725Sroot #define	DMC_CNTMASK	01777
102*5725Sroot #define DMC_FATAL	01620
103*5725Sroot 
104*5725Sroot #define	DMC_PF	0xff		/* 8 bits of protocol type in ui_flags */
105*5725Sroot #define	DMC_NET	0xff00		/* 8 bits of net number in ui_flags */
106*5725Sroot 
107*5725Sroot /*
108*5725Sroot  * DMC software status per interface.
109*5725Sroot  *
110*5725Sroot  * Each interface is referenced by a network interface structure,
111*5725Sroot  * sc_if, which the routing code uses to locate the interface.
112*5725Sroot  * This structure contains the output queue for the interface, its address, ...
113*5725Sroot  * We also have, for each interface, a UBA interface structure, which
114*5725Sroot  * contains information about the UNIBUS resources held by the interface:
115*5725Sroot  * map registers, buffered data paths, etc.  Information is cached in this
116*5725Sroot  * structure for use by the if_uba.c routines in running the interface
117*5725Sroot  * efficiently.
118*5725Sroot  */
119*5725Sroot struct dmc_softc {
120*5725Sroot 	struct	ifnet sc_if;		/* network-visible interface */
121*5725Sroot 	struct	ifuba sc_ifuba;		/* UNIBUS resources */
122*5725Sroot 	short	sc_flag;		/* flags */
123*5725Sroot 	short	sc_oactive;		/* output active */
124*5725Sroot 	int	sc_ubinfo;		/* UBA mapping info for base table */
125*5725Sroot 	struct clist sc_que;		/* command queue */
126*5725Sroot } dmc_softc[NDMC];
127*5725Sroot 
128*5725Sroot /* flags */
129*5725Sroot #define	DMCRUN		01
130*5725Sroot #define	DMCBMAPPED	02		/* base table mapped */
131*5725Sroot 
132*5725Sroot struct dmc_base {
133*5725Sroot 	short	d_base[128];		/* DMC base table */
134*5725Sroot } dmc_base[NDMC];
135*5725Sroot 
136*5725Sroot #define	loword(x)	((short *)&x)[0]
137*5725Sroot #define	hiword(x)	((short *)&x)[1]
138*5725Sroot 
139*5725Sroot dmcprobe(reg)
140*5725Sroot 	caddr_t reg;
141*5725Sroot {
142*5725Sroot 	register int br, cvec;
143*5725Sroot 	register struct dmcdevice *addr = (struct dmcdevice *)reg;
144*5725Sroot 	register int i;
145*5725Sroot 
146*5725Sroot #ifdef lint
147*5725Sroot 	br = 0; cvec = br; br = cvec;
148*5725Sroot 	dmcrint(0); dmcxint(0);
149*5725Sroot #endif
150*5725Sroot 	addr->bsel1 = DMC_MCLR;
151*5725Sroot 	for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
152*5725Sroot 		;
153*5725Sroot 	if ((addr->bsel1 & DMC_RUN) == 0)
154*5725Sroot 		return(0);
155*5725Sroot 	addr->bsel1 &= ~DMC_MCLR;
156*5725Sroot 	addr->bsel0 = DMC_RQI|DMC_IEI;
157*5725Sroot 	DELAY(100000);
158*5725Sroot 	addr->bsel1 = DMC_MCLR;
159*5725Sroot 	for (i = 100000; i && (addr->bsel1 & DMC_RUN) == 0; i--)
160*5725Sroot 		;
161*5725Sroot 	return(1);
162*5725Sroot }
163*5725Sroot 
164*5725Sroot /*
165*5725Sroot  * Interface exists: make available by filling in network interface
166*5725Sroot  * record.  System will initialize the interface when it is ready
167*5725Sroot  * to accept packets.
168*5725Sroot  */
169*5725Sroot dmcattach(ui)
170*5725Sroot 	register struct uba_device *ui;
171*5725Sroot {
172*5725Sroot 	register struct dmc_softc *sc = &dmc_softc[ui->ui_unit];
173*5725Sroot 
174*5725Sroot 	sc->sc_if.if_unit = ui->ui_unit;
175*5725Sroot 	sc->sc_if.if_name = "dmc";
176*5725Sroot 	sc->sc_if.if_mtu = DMCMTU;
177*5725Sroot 	sc->sc_if.if_net = (ui->ui_flags & DMC_NET) >> 8;
178*5725Sroot 	sc->sc_if.if_host[0] = 17;	/* random number */
179*5725Sroot 	sc->sc_if.if_addr =
180*5725Sroot 	    if_makeaddr(sc->sc_if.if_net, sc->sc_if.if_host[0]);
181*5725Sroot 	sc->sc_if.if_init = dmcinit;
182*5725Sroot 	sc->sc_if.if_output = dmcoutput;
183*5725Sroot 	sc->sc_if.if_ubareset = dmcreset;
184*5725Sroot 	if_attach(&sc->sc_if);
185*5725Sroot }
186*5725Sroot 
187*5725Sroot /*
188*5725Sroot  * Reset of interface after UNIBUS reset.
189*5725Sroot  * If interface is on specified UBA, reset it's state.
190*5725Sroot  */
191*5725Sroot dmcreset(unit, uban)
192*5725Sroot 	int unit, uban;
193*5725Sroot {
194*5725Sroot 	register struct uba_device *ui;
195*5725Sroot 
196*5725Sroot 	if (unit >= NDMC || (ui = dmcinfo[unit]) == 0 || ui->ui_alive == 0 ||
197*5725Sroot 	    ui->ui_ubanum != uban)
198*5725Sroot 		return;
199*5725Sroot 	printf(" dmc%d", unit);
200*5725Sroot 	dmcinit(unit);
201*5725Sroot }
202*5725Sroot 
203*5725Sroot /*
204*5725Sroot  * Initialization of interface; reinitialize UNIBUS usage.
205*5725Sroot  */
206*5725Sroot dmcinit(unit)
207*5725Sroot 	int unit;
208*5725Sroot {
209*5725Sroot 	register struct dmc_softc *sc = &dmc_softc[unit];
210*5725Sroot 	register struct uba_device *ui = dmcinfo[unit];
211*5725Sroot 	register struct dmcdevice *addr;
212*5725Sroot 	int base;
213*5725Sroot 
214*5725Sroot 	printd("dmcinit\n");
215*5725Sroot 	if ((sc->sc_flag&DMCBMAPPED) == 0) {
216*5725Sroot 		sc->sc_ubinfo = uballoc(ui->ui_ubanum,
217*5725Sroot 		    (caddr_t)&dmc_base[unit], sizeof (struct dmc_base), 0);
218*5725Sroot 		sc->sc_flag |= DMCBMAPPED;
219*5725Sroot 	}
220*5725Sroot 	if (if_ubainit(&sc->sc_ifuba, ui->ui_ubanum, 0,
221*5725Sroot 	    (int)btop(DMCMTU)) == 0) {
222*5725Sroot 		printf("dmc%d: can't initialize\n", unit);
223*5725Sroot 		return;
224*5725Sroot 	}
225*5725Sroot 	addr = (struct dmcdevice *)ui->ui_addr;
226*5725Sroot 	addr->bsel2 |= DMC_IEO;
227*5725Sroot 	base = sc->sc_ubinfo & 0x3ffff;
228*5725Sroot 	printd("  base 0x%x\n", base);
229*5725Sroot 	dmcload(sc, DMC_BASEI, base, (base>>2)&DMC_XMEM);
230*5725Sroot 	dmcload(sc, DMC_CNTLI, 0, 0);
231*5725Sroot 	base = sc->sc_ifuba.ifu_r.ifrw_info & 0x3ffff;
232*5725Sroot 	dmcload(sc, DMC_READ, base, ((base>>2)&DMC_XMEM)|DMCMTU);
233*5725Sroot 	printd("  first read queued, addr 0x%x\n", base);
234*5725Sroot }
235*5725Sroot 
236*5725Sroot /*
237*5725Sroot  * Start output on interface.  Get another datagram
238*5725Sroot  * to send from the interface queue and map it to
239*5725Sroot  * the interface before starting output.
240*5725Sroot  */
241*5725Sroot dmcstart(dev)
242*5725Sroot 	dev_t dev;
243*5725Sroot {
244*5725Sroot 	int unit = minor(dev);
245*5725Sroot 	struct uba_device *ui = dmcinfo[unit];
246*5725Sroot 	register struct dmc_softc *sc = &dmc_softc[unit];
247*5725Sroot 	int addr, len;
248*5725Sroot 	struct mbuf *m;
249*5725Sroot 
250*5725Sroot 	printd("dmcstart\n");
251*5725Sroot 	/*
252*5725Sroot 	 * Dequeue a request and map it to the UNIBUS.
253*5725Sroot 	 * If no more requests, just return.
254*5725Sroot 	 */
255*5725Sroot 	IF_DEQUEUE(&sc->sc_if.if_snd, m);
256*5725Sroot 	if (m == 0)
257*5725Sroot 		return;
258*5725Sroot 	len = if_wubaput(&sc->sc_ifuba, m);
259*5725Sroot 
260*5725Sroot 	/*
261*5725Sroot 	 * Have request mapped to UNIBUS for transmission.
262*5725Sroot 	 * Purge any stale data from this BDP and start the output.
263*5725Sroot 	 */
264*5725Sroot 	UBAPURGE(sc->sc_ifuba.ifu_uba, sc->sc_ifuba.ifu_w.ifrw_bdp);
265*5725Sroot 	addr = sc->sc_ifuba.ifu_w.ifrw_info & 0x3ffff;
266*5725Sroot 	printd("  len %d, addr 0x%x, ", len, addr);
267*5725Sroot 	printd("mr 0x%x\n", sc->sc_ifuba.ifu_w.ifrw_mr[0]);
268*5725Sroot 	dmcload(sc, DMC_WRITE, addr, (len&DMC_CCOUNT)|((addr>>2)&DMC_XMEM));
269*5725Sroot 	sc->sc_oactive = 1;
270*5725Sroot }
271*5725Sroot 
272*5725Sroot /*
273*5725Sroot  * Utility routine to load the DMC device registers.
274*5725Sroot  */
275*5725Sroot dmcload(sc, type, w0, w1)
276*5725Sroot 	register struct dmc_softc *sc;
277*5725Sroot 	int type, w0, w1;
278*5725Sroot {
279*5725Sroot 	register struct dmcdevice *addr;
280*5725Sroot 	register int unit, sps, n;
281*5725Sroot 
282*5725Sroot 	printd("dmcload: 0x%x 0x%x 0x%x\n", type, w0, w1);
283*5725Sroot 	unit = sc - dmc_softc;
284*5725Sroot 	addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
285*5725Sroot 	sps = spl5();
286*5725Sroot 	if ((n = sc->sc_que.c_cc) == 0)
287*5725Sroot 		addr->bsel0 = type | DMC_RQI;
288*5725Sroot 	else
289*5725Sroot 		putc(type | DMC_RQI, &sc->sc_que);
290*5725Sroot 	putw(w0, &sc->sc_que);
291*5725Sroot 	putw(w1, &sc->sc_que);
292*5725Sroot 	if (n == 0)
293*5725Sroot 		dmcrint(unit);
294*5725Sroot 	splx(sps);
295*5725Sroot }
296*5725Sroot 
297*5725Sroot /*
298*5725Sroot  * DMC interface receiver interrupt.
299*5725Sroot  * Ready to accept another command,
300*5725Sroot  * pull one off the command queue.
301*5725Sroot  */
302*5725Sroot dmcrint(unit)
303*5725Sroot 	int unit;
304*5725Sroot {
305*5725Sroot 	register struct dmc_softc *sc;
306*5725Sroot 	register struct dmcdevice *addr;
307*5725Sroot 	register int n;
308*5725Sroot 	int w0, w1; /* DEBUG */
309*5725Sroot 
310*5725Sroot 	addr = (struct dmcdevice *)dmcinfo[unit]->ui_addr;
311*5725Sroot 	sc = &dmc_softc[unit];
312*5725Sroot 	while (addr->bsel0&DMC_RDYI) {
313*5725Sroot 		w0 = getw(&sc->sc_que); /* DEBUG */
314*5725Sroot 		addr->sel4 = w0; /* DEBUG */
315*5725Sroot 		w1 = getw(&sc->sc_que); /* DEBUG */
316*5725Sroot 		addr->sel6 = w1; /* DEBUG */
317*5725Sroot 		/* DEBUG
318*5725Sroot 		addr->sel4 = getw(&sc->sc_que);
319*5725Sroot 		addr->sel6 = getw(&sc->sc_que);
320*5725Sroot 		DEBUG */
321*5725Sroot 		addr->bsel0 &= ~(DMC_IEI|DMC_RQI);
322*5725Sroot 		printd("  w0 0x%x, w1 0x%x\n", w0, w1);
323*5725Sroot 		while (addr->bsel0&DMC_RDYI)
324*5725Sroot 			;
325*5725Sroot 		if (sc->sc_que.c_cc == 0)
326*5725Sroot 			return;
327*5725Sroot 		addr->bsel0 = getc(&sc->sc_que);
328*5725Sroot 		n = RDYSCAN;
329*5725Sroot 		while (n-- && (addr->bsel0&DMC_RDYI) == 0)
330*5725Sroot 			;
331*5725Sroot 	}
332*5725Sroot 	if (sc->sc_que.c_cc)
333*5725Sroot 		addr->bsel0 |= DMC_IEI;
334*5725Sroot }
335*5725Sroot 
336*5725Sroot /*
337*5725Sroot  * DMC interface transmitter interrupt.
338*5725Sroot  * A transfer has completed, check for errors.
339*5725Sroot  * If it was a read, notify appropriate protocol.
340*5725Sroot  * If it was a write, pull the next one off the queue.
341*5725Sroot  */
342*5725Sroot dmcxint(unit)
343*5725Sroot 	int unit;
344*5725Sroot {
345*5725Sroot 	register struct dmc_softc *sc;
346*5725Sroot 	struct uba_device *ui = dmcinfo[unit];
347*5725Sroot 	struct dmcdevice *addr;
348*5725Sroot 	struct mbuf *m;
349*5725Sroot 	register struct ifqueue *inq;
350*5725Sroot 	int arg, cmd, len;
351*5725Sroot 
352*5725Sroot 	addr = (struct dmcdevice *)ui->ui_addr;
353*5725Sroot 	arg = addr->sel6;
354*5725Sroot 	cmd = addr->bsel2&7;
355*5725Sroot 	addr->bsel2 &= ~DMC_RDYO;
356*5725Sroot 	sc = &dmc_softc[unit];
357*5725Sroot 	printd("dmcxint\n");
358*5725Sroot 	switch (cmd) {
359*5725Sroot 
360*5725Sroot 	case DMC_OUR:
361*5725Sroot 		/*
362*5725Sroot 		 * A read has completed.  Purge input buffered
363*5725Sroot 		 * data path.  Pass packet to type specific
364*5725Sroot 		 * higher-level input routine.
365*5725Sroot 		 */
366*5725Sroot 		sc->sc_if.if_ipackets++;
367*5725Sroot 		UBAPURGE(sc->sc_ifuba.ifu_uba, sc->sc_ifuba.ifu_r.ifrw_bdp);
368*5725Sroot 		len = arg & DMC_CCOUNT;
369*5725Sroot 		printd("  read done, len %d\n", len);
370*5725Sroot 		switch (ui->ui_flags & DMC_PF) {
371*5725Sroot #ifdef INET
372*5725Sroot 		case PF_INET:
373*5725Sroot 			setipintr();
374*5725Sroot 			inq = &ipintrq;
375*5725Sroot 			break;
376*5725Sroot #endif
377*5725Sroot 
378*5725Sroot 		default:
379*5725Sroot 			printf("dmc%d: unknown packet type %d\n", unit,
380*5725Sroot 			    ui->ui_flags & DMC_NET);
381*5725Sroot 			goto setup;
382*5725Sroot 		}
383*5725Sroot 		m = if_rubaget(&sc->sc_ifuba, len, 0);
384*5725Sroot 		if (m == 0)
385*5725Sroot 			goto setup;
386*5725Sroot 		IF_ENQUEUE(inq, m);
387*5725Sroot 
388*5725Sroot setup:
389*5725Sroot 		arg = sc->sc_ifuba.ifu_r.ifrw_info & 0x3ffff;
390*5725Sroot 		dmcload(sc, DMC_READ, arg, ((arg >> 2) & DMC_XMEM) | DMCMTU);
391*5725Sroot 		return;
392*5725Sroot 
393*5725Sroot 	case DMC_OUX:
394*5725Sroot 		/*
395*5725Sroot 		 * A write has completed, start another
396*5725Sroot 		 * transfer if there is more data to send.
397*5725Sroot 		 */
398*5725Sroot 		if (sc->sc_oactive == 0)
399*5725Sroot 			return;		/* SHOULD IT BE A FATAL ERROR? */
400*5725Sroot 		printd("  write done\n");
401*5725Sroot 		sc->sc_if.if_opackets++;
402*5725Sroot 		sc->sc_oactive = 0;
403*5725Sroot 		if (sc->sc_ifuba.ifu_xtofree) {
404*5725Sroot 			m_freem(sc->sc_ifuba.ifu_xtofree);
405*5725Sroot 			sc->sc_ifuba.ifu_xtofree = 0;
406*5725Sroot 		}
407*5725Sroot 		if (sc->sc_if.if_snd.ifq_head == 0)
408*5725Sroot 			return;
409*5725Sroot 		dmcstart(unit);
410*5725Sroot 		return;
411*5725Sroot 
412*5725Sroot 	case DMC_CNTLO:
413*5725Sroot 		arg &= DMC_CNTMASK;
414*5725Sroot 		if (arg&DMC_FATAL) {
415*5725Sroot 			addr->bsel1 = DMC_MCLR;
416*5725Sroot 			sc->sc_flag &= ~DMCRUN;
417*5725Sroot 			/*** DO SOMETHING TO RESTART DEVICE ***/
418*5725Sroot 			printf("DMC FATAL ERROR 0%o\n", arg);
419*5725Sroot 		} else {
420*5725Sroot 			/* ACCUMULATE STATISTICS */
421*5725Sroot 			printf("DMC SOFT ERROR 0%o\n", arg);
422*5725Sroot 		}
423*5725Sroot 		return;
424*5725Sroot 
425*5725Sroot 	default:
426*5725Sroot 		printf("dmc%d: bad control %o\n", unit, cmd);
427*5725Sroot 	}
428*5725Sroot }
429*5725Sroot 
430*5725Sroot /*
431*5725Sroot  * DMC output routine.
432*5725Sroot  * Just send the data, header was supplied by
433*5725Sroot  * upper level protocol routines.
434*5725Sroot  */
435*5725Sroot dmcoutput(ifp, m, pf)
436*5725Sroot 	register struct ifnet *ifp;
437*5725Sroot 	register struct mbuf *m;
438*5725Sroot 	int pf;
439*5725Sroot {
440*5725Sroot 	struct uba_device *ui = dmcinfo[ifp->if_unit];
441*5725Sroot 	int s;
442*5725Sroot 
443*5725Sroot 	printd("dmcoutput\n");
444*5725Sroot 	if (pf != (ui->ui_flags & DMC_PF)) {
445*5725Sroot 		printf("dmc%d: protocol %d not supported\n", ifp->if_unit, pf);
446*5725Sroot 		m_freem(m);
447*5725Sroot 		return (0);
448*5725Sroot 	}
449*5725Sroot 	s = splimp();
450*5725Sroot 	IF_ENQUEUE(&ifp->if_snd, m);
451*5725Sroot 	if (dmc_softc[ifp->if_unit].sc_oactive == 0)
452*5725Sroot 		dmcstart(ifp->if_unit);
453*5725Sroot 	splx(s);
454*5725Sroot 	return (1);
455*5725Sroot }
456