dma.c revision 1.4 1 1.1 cgd /*
2 1.4 mycroft * Copyright (c) 1982, 1990, 1993
3 1.4 mycroft * The Regents of the University of California. All rights reserved.
4 1.1 cgd *
5 1.1 cgd * Redistribution and use in source and binary forms, with or without
6 1.1 cgd * modification, are permitted provided that the following conditions
7 1.1 cgd * are met:
8 1.1 cgd * 1. Redistributions of source code must retain the above copyright
9 1.1 cgd * notice, this list of conditions and the following disclaimer.
10 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
11 1.1 cgd * notice, this list of conditions and the following disclaimer in the
12 1.1 cgd * documentation and/or other materials provided with the distribution.
13 1.1 cgd * 3. All advertising materials mentioning features or use of this software
14 1.1 cgd * must display the following acknowledgement:
15 1.1 cgd * This product includes software developed by the University of
16 1.1 cgd * California, Berkeley and its contributors.
17 1.1 cgd * 4. Neither the name of the University nor the names of its contributors
18 1.1 cgd * may be used to endorse or promote products derived from this software
19 1.1 cgd * without specific prior written permission.
20 1.1 cgd *
21 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.1 cgd * SUCH DAMAGE.
32 1.1 cgd *
33 1.4 mycroft * from: @(#)dma.c 8.1 (Berkeley) 6/10/93
34 1.4 mycroft * $Id: dma.c,v 1.4 1994/05/23 05:58:46 mycroft Exp $
35 1.1 cgd */
36 1.1 cgd
37 1.1 cgd /*
38 1.1 cgd * DMA driver
39 1.1 cgd */
40 1.1 cgd
41 1.4 mycroft #include <sys/param.h>
42 1.4 mycroft #include <sys/systm.h>
43 1.4 mycroft #include <sys/time.h>
44 1.4 mycroft #include <sys/kernel.h>
45 1.4 mycroft #include <sys/proc.h>
46 1.4 mycroft
47 1.4 mycroft #include <machine/cpu.h>
48 1.4 mycroft
49 1.4 mycroft #include <hp300/dev/device.h>
50 1.4 mycroft #include <hp300/dev/dmareg.h>
51 1.4 mycroft #include <hp300/dev/dmavar.h>
52 1.1 cgd
53 1.4 mycroft #include <hp300/hp300/isr.h>
54 1.1 cgd
55 1.1 cgd extern void isrlink();
56 1.1 cgd extern void _insque();
57 1.1 cgd extern void _remque();
58 1.1 cgd extern u_int kvtop();
59 1.1 cgd extern void PCIA();
60 1.1 cgd
61 1.1 cgd /*
62 1.1 cgd * The largest single request will be MAXPHYS bytes which will require
63 1.1 cgd * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of
64 1.1 cgd * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the
65 1.1 cgd * buffer is not page aligned (+1).
66 1.1 cgd */
67 1.1 cgd #define DMAMAXIO (MAXPHYS/NBPG+1)
68 1.1 cgd
69 1.1 cgd struct dma_chain {
70 1.1 cgd int dc_count;
71 1.1 cgd char *dc_addr;
72 1.1 cgd };
73 1.1 cgd
74 1.1 cgd struct dma_softc {
75 1.1 cgd struct dmadevice *sc_hwaddr;
76 1.1 cgd struct dmaBdevice *sc_Bhwaddr;
77 1.1 cgd char sc_type;
78 1.1 cgd char sc_flags;
79 1.1 cgd u_short sc_cmd;
80 1.1 cgd struct dma_chain *sc_cur;
81 1.1 cgd struct dma_chain *sc_last;
82 1.1 cgd struct dma_chain sc_chain[DMAMAXIO];
83 1.1 cgd } dma_softc[NDMA];
84 1.1 cgd
85 1.1 cgd /* types */
86 1.1 cgd #define DMA_B 0
87 1.1 cgd #define DMA_C 1
88 1.1 cgd
89 1.1 cgd /* flags */
90 1.1 cgd #define DMAF_PCFLUSH 0x01
91 1.1 cgd #define DMAF_VCFLUSH 0x02
92 1.1 cgd #define DMAF_NOINTR 0x04
93 1.1 cgd
94 1.1 cgd struct devqueue dmachan[NDMA + 1];
95 1.1 cgd int dmaintr();
96 1.1 cgd
97 1.1 cgd #ifdef DEBUG
98 1.1 cgd int dmadebug = 0;
99 1.1 cgd #define DDB_WORD 0x01 /* same as DMAGO_WORD */
100 1.1 cgd #define DDB_LWORD 0x02 /* same as DMAGO_LWORD */
101 1.1 cgd #define DDB_FOLLOW 0x04
102 1.1 cgd #define DDB_IO 0x08
103 1.1 cgd
104 1.3 mycroft void dmatimeout __P((void *));
105 1.1 cgd int dmatimo[NDMA];
106 1.1 cgd
107 1.1 cgd long dmahits[NDMA];
108 1.1 cgd long dmamisses[NDMA];
109 1.1 cgd long dmabyte[NDMA];
110 1.1 cgd long dmaword[NDMA];
111 1.1 cgd long dmalword[NDMA];
112 1.1 cgd #endif
113 1.1 cgd
114 1.1 cgd void
115 1.1 cgd dmainit()
116 1.1 cgd {
117 1.1 cgd register struct dmareg *dma = (struct dmareg *)DMA_BASE;
118 1.1 cgd register struct dma_softc *dc;
119 1.1 cgd register int i;
120 1.1 cgd char rev;
121 1.1 cgd
122 1.1 cgd /*
123 1.1 cgd * Determine the DMA type.
124 1.1 cgd * Don't know how to easily differentiate the A and B cards,
125 1.1 cgd * so we just hope nobody has an A card (A cards will work if
126 1.1 cgd * DMAINTLVL is set to 3).
127 1.1 cgd */
128 1.1 cgd if (!badbaddr((char *)&dma->dma_id[2]))
129 1.1 cgd rev = dma->dma_id[2];
130 1.1 cgd else {
131 1.1 cgd rev = 'B';
132 1.1 cgd #if !defined(HP320)
133 1.1 cgd panic("dmainit: DMA card requires hp320 support");
134 1.1 cgd #endif
135 1.1 cgd }
136 1.1 cgd
137 1.1 cgd dc = &dma_softc[0];
138 1.1 cgd for (i = 0; i < NDMA; i++) {
139 1.1 cgd dc->sc_hwaddr = (i & 1) ? &dma->dma_chan1 : &dma->dma_chan0;
140 1.1 cgd dc->sc_Bhwaddr = (i & 1) ? &dma->dma_Bchan1 : &dma->dma_Bchan0;
141 1.1 cgd dc->sc_type = rev == 'B' ? DMA_B : DMA_C;
142 1.1 cgd dc++;
143 1.1 cgd dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i];
144 1.1 cgd }
145 1.1 cgd dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i];
146 1.1 cgd #ifdef DEBUG
147 1.1 cgd /* make sure timeout is really not needed */
148 1.4 mycroft timeout(dmatimeout, (void *)0, 30 * hz);
149 1.1 cgd #endif
150 1.1 cgd
151 1.1 cgd printf("dma: 98620%c with 2 channels, %d bit DMA\n",
152 1.1 cgd rev, rev == 'B' ? 16 : 32);
153 1.1 cgd }
154 1.1 cgd
155 1.1 cgd int
156 1.1 cgd dmareq(dq)
157 1.1 cgd register struct devqueue *dq;
158 1.1 cgd {
159 1.1 cgd register int i;
160 1.1 cgd register int chan;
161 1.1 cgd register int s = splbio();
162 1.1 cgd
163 1.1 cgd chan = dq->dq_ctlr;
164 1.1 cgd i = NDMA;
165 1.1 cgd while (--i >= 0) {
166 1.1 cgd if ((chan & (1 << i)) == 0)
167 1.1 cgd continue;
168 1.1 cgd if (dmachan[i].dq_forw != &dmachan[i])
169 1.1 cgd continue;
170 1.1 cgd insque(dq, &dmachan[i]);
171 1.1 cgd dq->dq_ctlr = i;
172 1.1 cgd splx(s);
173 1.1 cgd return(1);
174 1.1 cgd }
175 1.1 cgd insque(dq, dmachan[NDMA].dq_back);
176 1.1 cgd splx(s);
177 1.1 cgd return(0);
178 1.1 cgd }
179 1.1 cgd
180 1.1 cgd void
181 1.1 cgd dmafree(dq)
182 1.1 cgd register struct devqueue *dq;
183 1.1 cgd {
184 1.1 cgd int unit = dq->dq_ctlr;
185 1.1 cgd register struct dma_softc *dc = &dma_softc[unit];
186 1.1 cgd register struct devqueue *dn;
187 1.1 cgd register int chan, s;
188 1.1 cgd
189 1.1 cgd s = splbio();
190 1.1 cgd #ifdef DEBUG
191 1.1 cgd dmatimo[unit] = 0;
192 1.1 cgd #endif
193 1.1 cgd DMA_CLEAR(dc);
194 1.4 mycroft #if defined(HP360) || defined(HP370) || defined(HP380)
195 1.1 cgd /*
196 1.1 cgd * XXX we may not always go thru the flush code in dmastop()
197 1.1 cgd */
198 1.1 cgd if (dc->sc_flags & DMAF_PCFLUSH) {
199 1.1 cgd PCIA();
200 1.1 cgd dc->sc_flags &= ~DMAF_PCFLUSH;
201 1.1 cgd }
202 1.1 cgd #endif
203 1.1 cgd #if defined(HP320) || defined(HP350)
204 1.1 cgd if (dc->sc_flags & DMAF_VCFLUSH) {
205 1.1 cgd /*
206 1.1 cgd * 320/350s have VACs that may also need flushing.
207 1.1 cgd * In our case we only flush the supervisor side
208 1.1 cgd * because we know that if we are DMAing to user
209 1.1 cgd * space, the physical pages will also be mapped
210 1.1 cgd * in kernel space (via vmapbuf) and hence cache-
211 1.1 cgd * inhibited by the pmap module due to the multiple
212 1.1 cgd * mapping.
213 1.1 cgd */
214 1.1 cgd DCIS();
215 1.1 cgd dc->sc_flags &= ~DMAF_VCFLUSH;
216 1.1 cgd }
217 1.1 cgd #endif
218 1.1 cgd remque(dq);
219 1.1 cgd chan = 1 << unit;
220 1.1 cgd for (dn = dmachan[NDMA].dq_forw;
221 1.1 cgd dn != &dmachan[NDMA]; dn = dn->dq_forw) {
222 1.1 cgd if (dn->dq_ctlr & chan) {
223 1.1 cgd remque((caddr_t)dn);
224 1.1 cgd insque((caddr_t)dn, (caddr_t)dq->dq_back);
225 1.1 cgd splx(s);
226 1.1 cgd dn->dq_ctlr = dq->dq_ctlr;
227 1.1 cgd (dn->dq_driver->d_start)(dn->dq_unit);
228 1.1 cgd return;
229 1.1 cgd }
230 1.1 cgd }
231 1.1 cgd splx(s);
232 1.1 cgd }
233 1.1 cgd
234 1.1 cgd void
235 1.1 cgd dmago(unit, addr, count, flags)
236 1.1 cgd int unit;
237 1.1 cgd register char *addr;
238 1.1 cgd register int count;
239 1.1 cgd register int flags;
240 1.1 cgd {
241 1.1 cgd register struct dma_softc *dc = &dma_softc[unit];
242 1.1 cgd register struct dma_chain *dcp;
243 1.1 cgd register char *dmaend = NULL;
244 1.1 cgd register int tcount;
245 1.1 cgd
246 1.1 cgd if (count > MAXPHYS)
247 1.1 cgd panic("dmago: count > MAXPHYS");
248 1.1 cgd #if defined(HP320)
249 1.1 cgd if (dc->sc_type == DMA_B && (flags & DMAGO_LWORD))
250 1.1 cgd panic("dmago: no can do 32-bit DMA");
251 1.1 cgd #endif
252 1.1 cgd #ifdef DEBUG
253 1.1 cgd if (dmadebug & DDB_FOLLOW)
254 1.1 cgd printf("dmago(%d, %x, %x, %x)\n",
255 1.1 cgd unit, addr, count, flags);
256 1.1 cgd if (flags & DMAGO_LWORD)
257 1.1 cgd dmalword[unit]++;
258 1.1 cgd else if (flags & DMAGO_WORD)
259 1.1 cgd dmaword[unit]++;
260 1.1 cgd else
261 1.1 cgd dmabyte[unit]++;
262 1.1 cgd #endif
263 1.1 cgd /*
264 1.1 cgd * Build the DMA chain
265 1.1 cgd */
266 1.1 cgd for (dcp = dc->sc_chain; count > 0; dcp++) {
267 1.1 cgd dcp->dc_addr = (char *) kvtop(addr);
268 1.4 mycroft #if defined(HP380)
269 1.4 mycroft /*
270 1.4 mycroft * Push back dirty cache lines
271 1.4 mycroft */
272 1.4 mycroft if (mmutype == MMU_68040)
273 1.4 mycroft DCFP(dcp->dc_addr);
274 1.4 mycroft #endif
275 1.1 cgd if (count < (tcount = NBPG - ((int)addr & PGOFSET)))
276 1.1 cgd tcount = count;
277 1.1 cgd dcp->dc_count = tcount;
278 1.1 cgd addr += tcount;
279 1.1 cgd count -= tcount;
280 1.1 cgd if (flags & DMAGO_LWORD)
281 1.1 cgd tcount >>= 2;
282 1.1 cgd else if (flags & DMAGO_WORD)
283 1.1 cgd tcount >>= 1;
284 1.1 cgd if (dcp->dc_addr == dmaend
285 1.1 cgd #if defined(HP320)
286 1.1 cgd /* only 16-bit count on 98620B */
287 1.1 cgd && (dc->sc_type != DMA_B ||
288 1.1 cgd (dcp-1)->dc_count + tcount <= 65536)
289 1.1 cgd #endif
290 1.1 cgd ) {
291 1.1 cgd #ifdef DEBUG
292 1.1 cgd dmahits[unit]++;
293 1.1 cgd #endif
294 1.1 cgd dmaend += dcp->dc_count;
295 1.1 cgd (--dcp)->dc_count += tcount;
296 1.1 cgd } else {
297 1.1 cgd #ifdef DEBUG
298 1.1 cgd dmamisses[unit]++;
299 1.1 cgd #endif
300 1.1 cgd dmaend = dcp->dc_addr + dcp->dc_count;
301 1.1 cgd dcp->dc_count = tcount;
302 1.1 cgd }
303 1.1 cgd }
304 1.1 cgd dc->sc_cur = dc->sc_chain;
305 1.1 cgd dc->sc_last = --dcp;
306 1.1 cgd dc->sc_flags = 0;
307 1.1 cgd /*
308 1.1 cgd * Set up the command word based on flags
309 1.1 cgd */
310 1.1 cgd dc->sc_cmd = DMA_ENAB | DMA_IPL(DMAINTLVL) | DMA_START;
311 1.1 cgd if ((flags & DMAGO_READ) == 0)
312 1.1 cgd dc->sc_cmd |= DMA_WRT;
313 1.1 cgd if (flags & DMAGO_LWORD)
314 1.1 cgd dc->sc_cmd |= DMA_LWORD;
315 1.1 cgd else if (flags & DMAGO_WORD)
316 1.1 cgd dc->sc_cmd |= DMA_WORD;
317 1.1 cgd if (flags & DMAGO_PRI)
318 1.1 cgd dc->sc_cmd |= DMA_PRI;
319 1.4 mycroft #if defined(HP380)
320 1.4 mycroft /*
321 1.4 mycroft * On the 68040 we need to flush (push) the data cache before a
322 1.4 mycroft * DMA (already done above) and flush again after DMA completes.
323 1.4 mycroft * In theory we should only need to flush prior to a write DMA
324 1.4 mycroft * and purge after a read DMA but if the entire page is not
325 1.4 mycroft * involved in the DMA we might purge some valid data.
326 1.4 mycroft */
327 1.4 mycroft if (mmutype == MMU_68040 && (flags & DMAGO_READ))
328 1.4 mycroft dc->sc_flags |= DMAF_PCFLUSH;
329 1.4 mycroft #endif
330 1.1 cgd #if defined(HP360) || defined(HP370)
331 1.1 cgd /*
332 1.1 cgd * Remember if we need to flush external physical cache when
333 1.1 cgd * DMA is done. We only do this if we are reading (writing memory).
334 1.1 cgd */
335 1.1 cgd if (ectype == EC_PHYS && (flags & DMAGO_READ))
336 1.1 cgd dc->sc_flags |= DMAF_PCFLUSH;
337 1.1 cgd #endif
338 1.1 cgd #if defined(HP320) || defined(HP350)
339 1.1 cgd if (ectype == EC_VIRT && (flags & DMAGO_READ))
340 1.1 cgd dc->sc_flags |= DMAF_VCFLUSH;
341 1.1 cgd #endif
342 1.1 cgd /*
343 1.1 cgd * Remember if we can skip the dma completion interrupt on
344 1.1 cgd * the last segment in the chain.
345 1.1 cgd */
346 1.1 cgd if (flags & DMAGO_NOINT) {
347 1.1 cgd if (dc->sc_cur == dc->sc_last)
348 1.1 cgd dc->sc_cmd &= ~DMA_ENAB;
349 1.1 cgd else
350 1.1 cgd dc->sc_flags |= DMAF_NOINTR;
351 1.1 cgd }
352 1.1 cgd #ifdef DEBUG
353 1.1 cgd if (dmadebug & DDB_IO)
354 1.1 cgd if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) ||
355 1.1 cgd (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) {
356 1.1 cgd printf("dmago: cmd %x, flags %x\n",
357 1.1 cgd dc->sc_cmd, dc->sc_flags);
358 1.1 cgd for (dcp = dc->sc_chain; dcp <= dc->sc_last; dcp++)
359 1.1 cgd printf(" %d: %d@%x\n", dcp-dc->sc_chain,
360 1.1 cgd dcp->dc_count, dcp->dc_addr);
361 1.1 cgd }
362 1.1 cgd dmatimo[unit] = 1;
363 1.1 cgd #endif
364 1.1 cgd DMA_ARM(dc);
365 1.1 cgd }
366 1.1 cgd
367 1.1 cgd void
368 1.1 cgd dmastop(unit)
369 1.1 cgd register int unit;
370 1.1 cgd {
371 1.1 cgd register struct dma_softc *dc = &dma_softc[unit];
372 1.1 cgd register struct devqueue *dq;
373 1.1 cgd
374 1.1 cgd #ifdef DEBUG
375 1.1 cgd if (dmadebug & DDB_FOLLOW)
376 1.1 cgd printf("dmastop(%d)\n", unit);
377 1.1 cgd dmatimo[unit] = 0;
378 1.1 cgd #endif
379 1.1 cgd DMA_CLEAR(dc);
380 1.4 mycroft #if defined(HP360) || defined(HP370) || defined(HP380)
381 1.1 cgd if (dc->sc_flags & DMAF_PCFLUSH) {
382 1.1 cgd PCIA();
383 1.1 cgd dc->sc_flags &= ~DMAF_PCFLUSH;
384 1.1 cgd }
385 1.1 cgd #endif
386 1.1 cgd #if defined(HP320) || defined(HP350)
387 1.1 cgd if (dc->sc_flags & DMAF_VCFLUSH) {
388 1.1 cgd /*
389 1.1 cgd * 320/350s have VACs that may also need flushing.
390 1.1 cgd * In our case we only flush the supervisor side
391 1.1 cgd * because we know that if we are DMAing to user
392 1.1 cgd * space, the physical pages will also be mapped
393 1.1 cgd * in kernel space (via vmapbuf) and hence cache-
394 1.1 cgd * inhibited by the pmap module due to the multiple
395 1.1 cgd * mapping.
396 1.1 cgd */
397 1.1 cgd DCIS();
398 1.1 cgd dc->sc_flags &= ~DMAF_VCFLUSH;
399 1.1 cgd }
400 1.1 cgd #endif
401 1.1 cgd /*
402 1.1 cgd * We may get this interrupt after a device service routine
403 1.1 cgd * has freed the dma channel. So, ignore the intr if there's
404 1.1 cgd * nothing on the queue.
405 1.1 cgd */
406 1.1 cgd dq = dmachan[unit].dq_forw;
407 1.1 cgd if (dq != &dmachan[unit])
408 1.1 cgd (dq->dq_driver->d_done)(dq->dq_unit);
409 1.1 cgd }
410 1.1 cgd
411 1.1 cgd int
412 1.1 cgd dmaintr()
413 1.1 cgd {
414 1.1 cgd register struct dma_softc *dc;
415 1.1 cgd register int i, stat;
416 1.1 cgd int found = 0;
417 1.1 cgd
418 1.1 cgd #ifdef DEBUG
419 1.1 cgd if (dmadebug & DDB_FOLLOW)
420 1.1 cgd printf("dmaintr\n");
421 1.1 cgd #endif
422 1.1 cgd for (i = 0, dc = dma_softc; i < NDMA; i++, dc++) {
423 1.1 cgd stat = DMA_STAT(dc);
424 1.1 cgd if ((stat & DMA_INTR) == 0)
425 1.1 cgd continue;
426 1.1 cgd found++;
427 1.1 cgd #ifdef DEBUG
428 1.1 cgd if (dmadebug & DDB_IO) {
429 1.1 cgd if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) ||
430 1.1 cgd (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD))
431 1.1 cgd printf("dmaintr: unit %d stat %x next %d\n",
432 1.1 cgd i, stat, (dc->sc_cur-dc->sc_chain)+1);
433 1.1 cgd }
434 1.1 cgd if (stat & DMA_ARMED)
435 1.1 cgd printf("dma%d: intr when armed\n", i);
436 1.1 cgd #endif
437 1.1 cgd if (++dc->sc_cur <= dc->sc_last) {
438 1.1 cgd #ifdef DEBUG
439 1.1 cgd dmatimo[i] = 1;
440 1.1 cgd #endif
441 1.1 cgd /*
442 1.1 cgd * Last chain segment, disable DMA interrupt.
443 1.1 cgd */
444 1.1 cgd if (dc->sc_cur == dc->sc_last &&
445 1.1 cgd (dc->sc_flags & DMAF_NOINTR))
446 1.1 cgd dc->sc_cmd &= ~DMA_ENAB;
447 1.1 cgd DMA_CLEAR(dc);
448 1.1 cgd DMA_ARM(dc);
449 1.1 cgd } else
450 1.1 cgd dmastop(i);
451 1.1 cgd }
452 1.1 cgd return(found);
453 1.1 cgd }
454 1.1 cgd
455 1.1 cgd #ifdef DEBUG
456 1.1 cgd void
457 1.3 mycroft dmatimeout(arg)
458 1.3 mycroft void *arg;
459 1.1 cgd {
460 1.1 cgd register int i, s;
461 1.1 cgd
462 1.1 cgd for (i = 0; i < NDMA; i++) {
463 1.1 cgd s = splbio();
464 1.1 cgd if (dmatimo[i]) {
465 1.1 cgd if (dmatimo[i] > 1)
466 1.1 cgd printf("dma%d: timeout #%d\n",
467 1.1 cgd i, dmatimo[i]-1);
468 1.1 cgd dmatimo[i]++;
469 1.1 cgd }
470 1.1 cgd splx(s);
471 1.1 cgd }
472 1.4 mycroft timeout(dmatimeout, (void *)0, 30 * hz);
473 1.1 cgd }
474 1.1 cgd #endif
475