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