xref: /csrg-svn/sys/hp300/dev/dma.c (revision 41480)
1*41480Smckusick /*
2*41480Smckusick  * Copyright (c) 1982, 1990 The Regents of the University of California.
3*41480Smckusick  * All rights reserved.
4*41480Smckusick  *
5*41480Smckusick  * %sccs.include.redist.c%
6*41480Smckusick  *
7*41480Smckusick  *	@(#)dma.c	7.1 (Berkeley) 05/08/90
8*41480Smckusick  */
9*41480Smckusick 
10*41480Smckusick /*
11*41480Smckusick  * DMA driver
12*41480Smckusick  */
13*41480Smckusick 
14*41480Smckusick #include "param.h"
15*41480Smckusick #include "systm.h"
16*41480Smckusick #include "time.h"
17*41480Smckusick #include "kernel.h"
18*41480Smckusick #include "proc.h"
19*41480Smckusick #include "dmareg.h"
20*41480Smckusick #include "dmavar.h"
21*41480Smckusick #include "device.h"
22*41480Smckusick 
23*41480Smckusick #include "machine/cpu.h"
24*41480Smckusick #include "machine/isr.h"
25*41480Smckusick 
26*41480Smckusick extern void isrlink();
27*41480Smckusick extern void printf();
28*41480Smckusick extern void panic();
29*41480Smckusick extern void _insque();
30*41480Smckusick extern void _remque();
31*41480Smckusick extern void timeout();
32*41480Smckusick extern int splbio();
33*41480Smckusick extern void splx();
34*41480Smckusick extern u_int kvtop();
35*41480Smckusick extern void PCIA();
36*41480Smckusick 
37*41480Smckusick /*
38*41480Smckusick  * The largest single request will be MAXPHYS bytes which will require
39*41480Smckusick  * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of
40*41480Smckusick  * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the
41*41480Smckusick  * buffer is not page aligned (+1).
42*41480Smckusick  */
43*41480Smckusick #define	DMAMAXIO	(MAXPHYS/NBPG+1)
44*41480Smckusick 
45*41480Smckusick #define	DMATIMO		15
46*41480Smckusick 
47*41480Smckusick struct	dma_softc {
48*41480Smckusick 	struct dmadevice *sc_hwaddr;
49*41480Smckusick 	struct dmaBdevice *sc_Bhwaddr;
50*41480Smckusick 	int	sc_type;
51*41480Smckusick 	int	sc_cur;
52*41480Smckusick 	int	sc_cmd;
53*41480Smckusick 	int	sc_timo;
54*41480Smckusick 	int	sc_count[DMAMAXIO+1];
55*41480Smckusick 	char	*sc_addr[DMAMAXIO+1];
56*41480Smckusick } dma_softc[NDMA];
57*41480Smckusick 
58*41480Smckusick /* types */
59*41480Smckusick #define	DMA_B	0
60*41480Smckusick #define DMA_C	1
61*41480Smckusick 
62*41480Smckusick struct	devqueue dmachan[NDMA + 1];
63*41480Smckusick int	dmaintr();
64*41480Smckusick void	dmatimo();
65*41480Smckusick 
66*41480Smckusick #ifdef DEBUG
67*41480Smckusick int	dmadebug = 0;
68*41480Smckusick #define DDB_WORD	0x01	/* same as DMAGO_WORD */
69*41480Smckusick #define DDB_LWORD	0x02	/* same as DMAGO_LWORD */
70*41480Smckusick #define	DDB_FOLLOW	0x04
71*41480Smckusick #define DDB_IO		0x08
72*41480Smckusick 
73*41480Smckusick long	dmahits[NDMA];
74*41480Smckusick long	dmamisses[NDMA];
75*41480Smckusick long	dmabyte[NDMA];
76*41480Smckusick long	dmaword[NDMA];
77*41480Smckusick long	dmalword[NDMA];
78*41480Smckusick #endif
79*41480Smckusick 
80*41480Smckusick void
81*41480Smckusick dmainit()
82*41480Smckusick {
83*41480Smckusick 	register struct dmareg *dma = (struct dmareg *)DMA_BASE;
84*41480Smckusick 	register struct dma_softc *dc;
85*41480Smckusick 	register int i;
86*41480Smckusick 	char rev;
87*41480Smckusick 
88*41480Smckusick 	/*
89*41480Smckusick 	 * Determine the DMA type.
90*41480Smckusick 	 * Don't know how to easily differentiate the A and B cards,
91*41480Smckusick 	 * so we just hope nobody has an A card (A cards will work if
92*41480Smckusick 	 * DMAINTLVL is set to 3).
93*41480Smckusick 	 */
94*41480Smckusick 	if (!badbaddr((char *)&dma->dma_id[2]))
95*41480Smckusick 		rev = dma->dma_id[2];
96*41480Smckusick 	else {
97*41480Smckusick 		rev = 'B';
98*41480Smckusick #if !defined(HP320)
99*41480Smckusick 		panic("dmainit: DMA card requires hp320 support");
100*41480Smckusick #endif
101*41480Smckusick 	}
102*41480Smckusick 
103*41480Smckusick 	dc = &dma_softc[0];
104*41480Smckusick 	for (i = 0; i < NDMA; i++) {
105*41480Smckusick 		dc->sc_hwaddr = (i & 1) ? &dma->dma_chan1 : &dma->dma_chan0;
106*41480Smckusick 		dc->sc_Bhwaddr = (i & 1) ? &dma->dma_Bchan1 : &dma->dma_Bchan0;
107*41480Smckusick 		dc->sc_type = rev == 'B' ? DMA_B : DMA_C;
108*41480Smckusick 		dc++;
109*41480Smckusick 		dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i];
110*41480Smckusick 	}
111*41480Smckusick 	dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i];
112*41480Smckusick 	timeout(dmatimo, (caddr_t)0, DMATIMO * hz);
113*41480Smckusick 
114*41480Smckusick 	printf("dma: 98620%c with 2 channels, %d bit DMA\n",
115*41480Smckusick 	       rev, rev == 'B' ? 16 : 32);
116*41480Smckusick }
117*41480Smckusick 
118*41480Smckusick int
119*41480Smckusick dmareq(dq)
120*41480Smckusick 	register struct devqueue *dq;
121*41480Smckusick {
122*41480Smckusick 	register int i;
123*41480Smckusick 	register int chan;
124*41480Smckusick 	register int s = splbio();
125*41480Smckusick 
126*41480Smckusick 	chan = dq->dq_ctlr;
127*41480Smckusick 	i = NDMA;
128*41480Smckusick 	while (--i >= 0) {
129*41480Smckusick 		if ((chan & (1 << i)) == 0)
130*41480Smckusick 			continue;
131*41480Smckusick 		if (dmachan[i].dq_forw != &dmachan[i])
132*41480Smckusick 			continue;
133*41480Smckusick 		insque(dq, &dmachan[i]);
134*41480Smckusick 		dq->dq_ctlr = i;
135*41480Smckusick 		splx(s);
136*41480Smckusick 		return(1);
137*41480Smckusick 	}
138*41480Smckusick 	insque(dq, dmachan[NDMA].dq_back);
139*41480Smckusick 	splx(s);
140*41480Smckusick 	return(0);
141*41480Smckusick }
142*41480Smckusick 
143*41480Smckusick void
144*41480Smckusick dmafree(dq)
145*41480Smckusick 	register struct devqueue *dq;
146*41480Smckusick {
147*41480Smckusick 	int unit = dq->dq_ctlr;
148*41480Smckusick 	register struct dma_softc *dc = &dma_softc[unit];
149*41480Smckusick 	register struct devqueue *dn;
150*41480Smckusick 	register int chan, s;
151*41480Smckusick 
152*41480Smckusick 	s = splbio();
153*41480Smckusick 	dc->sc_timo = 0;
154*41480Smckusick 	DMA_CLEAR(dc);
155*41480Smckusick 	remque(dq);
156*41480Smckusick 	chan = 1 << unit;
157*41480Smckusick 	for (dn = dmachan[NDMA].dq_forw;
158*41480Smckusick 	     dn != &dmachan[NDMA]; dn = dn->dq_forw) {
159*41480Smckusick 		if (dn->dq_ctlr & chan) {
160*41480Smckusick 			remque((caddr_t)dn);
161*41480Smckusick 			insque((caddr_t)dn, (caddr_t)dq->dq_back);
162*41480Smckusick 			splx(s);
163*41480Smckusick 			dn->dq_ctlr = dq->dq_ctlr;
164*41480Smckusick 			(dn->dq_driver->d_start)(dn->dq_unit);
165*41480Smckusick 			return;
166*41480Smckusick 		}
167*41480Smckusick 	}
168*41480Smckusick 	splx(s);
169*41480Smckusick }
170*41480Smckusick 
171*41480Smckusick void
172*41480Smckusick dmago(unit, addr, count, flags)
173*41480Smckusick 	int unit;
174*41480Smckusick 	register char *addr;
175*41480Smckusick 	register int count;
176*41480Smckusick 	register int flags;
177*41480Smckusick {
178*41480Smckusick 	register struct dma_softc *dc = &dma_softc[unit];
179*41480Smckusick 	register char *dmaend = NULL;
180*41480Smckusick 	register int tcount, i;
181*41480Smckusick 
182*41480Smckusick #ifdef DEBUG
183*41480Smckusick 	if (dmadebug & DDB_FOLLOW)
184*41480Smckusick 		printf("dmago(%d, %x, %x, %x)\n",
185*41480Smckusick 		       unit, addr, count, flags);
186*41480Smckusick 	if (flags & DMAGO_LWORD)
187*41480Smckusick 		dmalword[unit]++;
188*41480Smckusick 	else if (flags & DMAGO_WORD)
189*41480Smckusick 		dmaword[unit]++;
190*41480Smckusick 	else
191*41480Smckusick 		dmabyte[unit]++;
192*41480Smckusick #endif
193*41480Smckusick #if defined(HP320)
194*41480Smckusick 	if (dc->sc_type == DMA_B && (flags & DMAGO_LWORD))
195*41480Smckusick 		panic("dmago: no can do 32-bit DMA");
196*41480Smckusick #endif
197*41480Smckusick 	/*
198*41480Smckusick 	 * Build the DMA chain
199*41480Smckusick 	 */
200*41480Smckusick 	for (i = 0; i < DMAMAXIO && count; i++) {
201*41480Smckusick 		dc->sc_addr[i] = (char *)kvtop(addr);
202*41480Smckusick 		tcount = dc->sc_count[i] =
203*41480Smckusick 			MIN(count, NBPG - ((int)addr & PGOFSET));
204*41480Smckusick 		addr += dc->sc_count[i];
205*41480Smckusick 		count -= tcount;
206*41480Smckusick 		if (flags & (DMAGO_WORD|DMAGO_LWORD))
207*41480Smckusick 			tcount >>= (flags & DMAGO_WORD) ? 1 : 2;
208*41480Smckusick 		if (dc->sc_addr[i] == dmaend
209*41480Smckusick #if defined(HP320)
210*41480Smckusick 		    /* only 16-bit count on 98620B */
211*41480Smckusick 		    && (dc->sc_type != DMA_B ||
212*41480Smckusick 			dc->sc_count[i-1] + tcount <= 65536)
213*41480Smckusick #endif
214*41480Smckusick 		) {
215*41480Smckusick #ifdef DEBUG
216*41480Smckusick 			dmahits[unit]++;
217*41480Smckusick #endif
218*41480Smckusick 			dmaend += dc->sc_count[i];
219*41480Smckusick 			dc->sc_count[i-1] += tcount;
220*41480Smckusick 			i--;
221*41480Smckusick 		} else {
222*41480Smckusick #ifdef DEBUG
223*41480Smckusick 			dmamisses[unit]++;
224*41480Smckusick #endif
225*41480Smckusick 			dmaend = dc->sc_addr[i] + dc->sc_count[i];
226*41480Smckusick 			dc->sc_count[i] = tcount;
227*41480Smckusick 		}
228*41480Smckusick 	}
229*41480Smckusick 	if (count)
230*41480Smckusick 		panic("dmago maxphys");
231*41480Smckusick 	dc->sc_count[i] = 0;
232*41480Smckusick 	dc->sc_cur = 0;
233*41480Smckusick 	/*
234*41480Smckusick 	 * Set up the command word based on flags
235*41480Smckusick 	 */
236*41480Smckusick 	dc->sc_cmd = DMA_ENAB | DMA_IPL(DMAINTLVL) | DMA_START;
237*41480Smckusick 	if ((flags & DMAGO_READ) == 0)
238*41480Smckusick 		dc->sc_cmd |= DMA_WRT;
239*41480Smckusick 	if (flags & DMAGO_LWORD)
240*41480Smckusick 		dc->sc_cmd |= DMA_LWORD;
241*41480Smckusick 	else if (flags & DMAGO_WORD)
242*41480Smckusick 		dc->sc_cmd |= DMA_WORD;
243*41480Smckusick 	if (flags & DMAGO_PRI)
244*41480Smckusick 		dc->sc_cmd |= DMA_PRI;
245*41480Smckusick 
246*41480Smckusick 	/*
247*41480Smckusick 	 * We should be able to skip the dma completion interrupt
248*41480Smckusick 	 * if we only have one segment in the chain since many
249*41480Smckusick 	 * devices generate their own completion interrupt.
250*41480Smckusick 	 * However, on a 370 we have to take the interrupt on
251*41480Smckusick 	 * read transfers to invalidate the external cache.
252*41480Smckusick 	 */
253*41480Smckusick 	if ((flags & DMAGO_NOINT) && i == 1
254*41480Smckusick #if defined(HP370)
255*41480Smckusick 	    && ((flags & DMAGO_READ) == 0 || ectype != EC_PHYS)
256*41480Smckusick #endif
257*41480Smckusick 	)
258*41480Smckusick 		dc->sc_cmd &= ~DMA_ENAB;
259*41480Smckusick #ifdef DEBUG
260*41480Smckusick #if defined(HP320)
261*41480Smckusick 	/* would this hurt? */
262*41480Smckusick 	if (dc->sc_type == DMA_B)
263*41480Smckusick 		dc->sc_cmd &= ~DMA_START;
264*41480Smckusick #endif
265*41480Smckusick 	if (dmadebug & DDB_IO)
266*41480Smckusick 		if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) ||
267*41480Smckusick 		    (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) {
268*41480Smckusick 			printf("dmago: cmd %x\n", dc->sc_cmd);
269*41480Smckusick 			for (i = 0; dc->sc_count[i]; i++)
270*41480Smckusick 				printf("  %d: %d@%x\n",
271*41480Smckusick 				       i, dc->sc_count[i], dc->sc_addr[i]);
272*41480Smckusick 		}
273*41480Smckusick #endif
274*41480Smckusick 
275*41480Smckusick 	/*
276*41480Smckusick 	 * Load and arm the channel
277*41480Smckusick 	 */
278*41480Smckusick 	dc->sc_timo = 1;
279*41480Smckusick 	DMA_ARM(dc, 0);
280*41480Smckusick }
281*41480Smckusick 
282*41480Smckusick void
283*41480Smckusick dmastop(unit)
284*41480Smckusick 	register int unit;
285*41480Smckusick {
286*41480Smckusick 	register struct dma_softc *dc = &dma_softc[unit];
287*41480Smckusick 	register struct devqueue *dq;
288*41480Smckusick 
289*41480Smckusick #ifdef DEBUG
290*41480Smckusick 	if (dmadebug & DDB_FOLLOW)
291*41480Smckusick 		printf("dmastop(%d)\n", unit);
292*41480Smckusick #endif
293*41480Smckusick 	dc->sc_timo = 0;
294*41480Smckusick 	DMA_CLEAR(dc);
295*41480Smckusick 
296*41480Smckusick 	/*
297*41480Smckusick 	 * We may get this interrupt after a device service routine
298*41480Smckusick 	 * has freed the dma channel.  So, ignore the intr if there's
299*41480Smckusick 	 * nothing on the queue.
300*41480Smckusick 	 */
301*41480Smckusick 	dq = dmachan[unit].dq_forw;
302*41480Smckusick 	if (dq != &dmachan[unit]) {
303*41480Smckusick #if defined(HP370)
304*41480Smckusick 		/*
305*41480Smckusick 		 * The 370 has an 64k external physical address cache.
306*41480Smckusick 		 * In theory, we should only need to flush it when
307*41480Smckusick 		 * DMAing to memory.
308*41480Smckusick 		 */
309*41480Smckusick 		if (ectype == EC_PHYS && (dc->sc_cmd & DMA_WRT) == 0)
310*41480Smckusick 			PCIA();
311*41480Smckusick #endif
312*41480Smckusick 		(dq->dq_driver->d_done)(dq->dq_unit);
313*41480Smckusick 	}
314*41480Smckusick }
315*41480Smckusick 
316*41480Smckusick int
317*41480Smckusick dmaintr()
318*41480Smckusick {
319*41480Smckusick 	register struct dma_softc *dc;
320*41480Smckusick 	register int i, j, stat;
321*41480Smckusick 	int found = 0;
322*41480Smckusick 
323*41480Smckusick #ifdef DEBUG
324*41480Smckusick 	if (dmadebug & DDB_FOLLOW)
325*41480Smckusick 		printf("dmaintr\n");
326*41480Smckusick #endif
327*41480Smckusick 	for (i = 0, dc = dma_softc; i < NDMA; i++, dc++) {
328*41480Smckusick 		stat = DMA_STAT(dc);
329*41480Smckusick 		if ((stat & DMA_INTR) == 0)
330*41480Smckusick 			continue;
331*41480Smckusick 		found++;
332*41480Smckusick #ifdef DEBUG
333*41480Smckusick 		if (dmadebug & DDB_IO) {
334*41480Smckusick 			if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) ||
335*41480Smckusick 			    (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD))
336*41480Smckusick 				printf("dmaintr: unit %d stat %x next %d\n",
337*41480Smckusick 				       i, stat, dc->sc_cur+1);
338*41480Smckusick 		}
339*41480Smckusick 		if (stat & DMA_ARMED)
340*41480Smckusick 			printf("dma%d: intr when armed\n", i);
341*41480Smckusick #endif
342*41480Smckusick 		j = ++dc->sc_cur;
343*41480Smckusick 		if (j < DMAMAXIO && dc->sc_count[j]) {
344*41480Smckusick 			dc->sc_timo = 1;
345*41480Smckusick 			DMA_CLEAR(dc);
346*41480Smckusick 			DMA_ARM(dc, j);
347*41480Smckusick 		} else
348*41480Smckusick 			dmastop(i);
349*41480Smckusick 	}
350*41480Smckusick 	return(found);
351*41480Smckusick }
352*41480Smckusick 
353*41480Smckusick void
354*41480Smckusick dmatimo()
355*41480Smckusick {
356*41480Smckusick 	register int i, s;
357*41480Smckusick 	register struct dma_softc *dc = &dma_softc[0];
358*41480Smckusick 
359*41480Smckusick 	for (i = 0; i < NDMA; i++, dc++) {
360*41480Smckusick 		s = splbio();
361*41480Smckusick 		if (dc->sc_timo) {
362*41480Smckusick 			if (dc->sc_timo == 1)
363*41480Smckusick 				dc->sc_timo++;
364*41480Smckusick 			else
365*41480Smckusick 				dmastop(i);
366*41480Smckusick 		}
367*41480Smckusick 		splx(s);
368*41480Smckusick 	}
369*41480Smckusick 	timeout(dmatimo, (caddr_t)0, DMATIMO * hz);
370*41480Smckusick }
371