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