|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)dma.c 7.1 (Berkeley) 5/8/90
21: */
22:
23: /*
24: * DMA driver
25: */
26:
27: #include "param.h"
28: #include "systm.h"
29: #include "time.h"
30: #include "kernel.h"
31: #include "proc.h"
32: #include "dmareg.h"
33: #include "dmavar.h"
34: #include "device.h"
35:
36: #include "machine/cpu.h"
37: #include "machine/isr.h"
38:
39: extern void isrlink();
40: extern void printf();
41: extern void panic();
42: extern void _insque();
43: extern void _remque();
44: extern void timeout();
45: extern int splbio();
46: extern void splx();
47: extern u_int kvtop();
48: extern void PCIA();
49:
50: /*
51: * The largest single request will be MAXPHYS bytes which will require
52: * at most MAXPHYS/NBPG+1 chain elements to describe, i.e. if none of
53: * the buffer pages are physically contiguous (MAXPHYS/NBPG) and the
54: * buffer is not page aligned (+1).
55: */
56: #define DMAMAXIO (MAXPHYS/NBPG+1)
57:
58: #define DMATIMO 15
59:
60: struct dma_softc {
61: struct dmadevice *sc_hwaddr;
62: struct dmaBdevice *sc_Bhwaddr;
63: int sc_type;
64: int sc_cur;
65: int sc_cmd;
66: int sc_timo;
67: int sc_count[DMAMAXIO+1];
68: char *sc_addr[DMAMAXIO+1];
69: } dma_softc[NDMA];
70:
71: /* types */
72: #define DMA_B 0
73: #define DMA_C 1
74:
75: struct devqueue dmachan[NDMA + 1];
76: int dmaintr();
77: void dmatimo();
78:
79: #ifdef DEBUG
80: int dmadebug = 0;
81: #define DDB_WORD 0x01 /* same as DMAGO_WORD */
82: #define DDB_LWORD 0x02 /* same as DMAGO_LWORD */
83: #define DDB_FOLLOW 0x04
84: #define DDB_IO 0x08
85:
86: long dmahits[NDMA];
87: long dmamisses[NDMA];
88: long dmabyte[NDMA];
89: long dmaword[NDMA];
90: long dmalword[NDMA];
91: #endif
92:
93: void
94: dmainit()
95: {
96: register struct dmareg *dma = (struct dmareg *)DMA_BASE;
97: register struct dma_softc *dc;
98: register int i;
99: char rev;
100:
101: /*
102: * Determine the DMA type.
103: * Don't know how to easily differentiate the A and B cards,
104: * so we just hope nobody has an A card (A cards will work if
105: * DMAINTLVL is set to 3).
106: */
107: if (!badbaddr((char *)&dma->dma_id[2]))
108: rev = dma->dma_id[2];
109: else {
110: rev = 'B';
111: #if !defined(HP320)
112: panic("dmainit: DMA card requires hp320 support");
113: #endif
114: }
115:
116: dc = &dma_softc[0];
117: for (i = 0; i < NDMA; i++) {
118: dc->sc_hwaddr = (i & 1) ? &dma->dma_chan1 : &dma->dma_chan0;
119: dc->sc_Bhwaddr = (i & 1) ? &dma->dma_Bchan1 : &dma->dma_Bchan0;
120: dc->sc_type = rev == 'B' ? DMA_B : DMA_C;
121: dc++;
122: dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i];
123: }
124: dmachan[i].dq_forw = dmachan[i].dq_back = &dmachan[i];
125: timeout(dmatimo, (caddr_t)0, DMATIMO * hz);
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: dc->sc_timo = 0;
167: DMA_CLEAR(dc);
168: remque(dq);
169: chan = 1 << unit;
170: for (dn = dmachan[NDMA].dq_forw;
171: dn != &dmachan[NDMA]; dn = dn->dq_forw) {
172: if (dn->dq_ctlr & chan) {
173: remque((caddr_t)dn);
174: insque((caddr_t)dn, (caddr_t)dq->dq_back);
175: splx(s);
176: dn->dq_ctlr = dq->dq_ctlr;
177: (dn->dq_driver->d_start)(dn->dq_unit);
178: return;
179: }
180: }
181: splx(s);
182: }
183:
184: void
185: dmago(unit, addr, count, flags)
186: int unit;
187: register char *addr;
188: register int count;
189: register int flags;
190: {
191: register struct dma_softc *dc = &dma_softc[unit];
192: register char *dmaend = NULL;
193: register int tcount, i;
194:
195: #ifdef DEBUG
196: if (dmadebug & DDB_FOLLOW)
197: printf("dmago(%d, %x, %x, %x)\n",
198: unit, addr, count, flags);
199: if (flags & DMAGO_LWORD)
200: dmalword[unit]++;
201: else if (flags & DMAGO_WORD)
202: dmaword[unit]++;
203: else
204: dmabyte[unit]++;
205: #endif
206: #if defined(HP320)
207: if (dc->sc_type == DMA_B && (flags & DMAGO_LWORD))
208: panic("dmago: no can do 32-bit DMA");
209: #endif
210: /*
211: * Build the DMA chain
212: */
213: for (i = 0; i < DMAMAXIO && count; i++) {
214: dc->sc_addr[i] = (char *)kvtop(addr);
215: tcount = dc->sc_count[i] =
216: MIN(count, NBPG - ((int)addr & PGOFSET));
217: addr += dc->sc_count[i];
218: count -= tcount;
219: if (flags & (DMAGO_WORD|DMAGO_LWORD))
220: tcount >>= (flags & DMAGO_WORD) ? 1 : 2;
221: if (dc->sc_addr[i] == dmaend
222: #if defined(HP320)
223: /* only 16-bit count on 98620B */
224: && (dc->sc_type != DMA_B ||
225: dc->sc_count[i-1] + tcount <= 65536)
226: #endif
227: ) {
228: #ifdef DEBUG
229: dmahits[unit]++;
230: #endif
231: dmaend += dc->sc_count[i];
232: dc->sc_count[i-1] += tcount;
233: i--;
234: } else {
235: #ifdef DEBUG
236: dmamisses[unit]++;
237: #endif
238: dmaend = dc->sc_addr[i] + dc->sc_count[i];
239: dc->sc_count[i] = tcount;
240: }
241: }
242: if (count)
243: panic("dmago maxphys");
244: dc->sc_count[i] = 0;
245: dc->sc_cur = 0;
246: /*
247: * Set up the command word based on flags
248: */
249: dc->sc_cmd = DMA_ENAB | DMA_IPL(DMAINTLVL) | DMA_START;
250: if ((flags & DMAGO_READ) == 0)
251: dc->sc_cmd |= DMA_WRT;
252: if (flags & DMAGO_LWORD)
253: dc->sc_cmd |= DMA_LWORD;
254: else if (flags & DMAGO_WORD)
255: dc->sc_cmd |= DMA_WORD;
256: if (flags & DMAGO_PRI)
257: dc->sc_cmd |= DMA_PRI;
258:
259: /*
260: * We should be able to skip the dma completion interrupt
261: * if we only have one segment in the chain since many
262: * devices generate their own completion interrupt.
263: * However, on a 370 we have to take the interrupt on
264: * read transfers to invalidate the external cache.
265: */
266: if ((flags & DMAGO_NOINT) && i == 1
267: #if defined(HP370)
268: && ((flags & DMAGO_READ) == 0 || ectype != EC_PHYS)
269: #endif
270: )
271: dc->sc_cmd &= ~DMA_ENAB;
272: #ifdef DEBUG
273: #if defined(HP320)
274: /* would this hurt? */
275: if (dc->sc_type == DMA_B)
276: dc->sc_cmd &= ~DMA_START;
277: #endif
278: if (dmadebug & DDB_IO)
279: if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) ||
280: (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD)) {
281: printf("dmago: cmd %x\n", dc->sc_cmd);
282: for (i = 0; dc->sc_count[i]; i++)
283: printf(" %d: %d@%x\n",
284: i, dc->sc_count[i], dc->sc_addr[i]);
285: }
286: #endif
287:
288: /*
289: * Load and arm the channel
290: */
291: dc->sc_timo = 1;
292: DMA_ARM(dc, 0);
293: }
294:
295: void
296: dmastop(unit)
297: register int unit;
298: {
299: register struct dma_softc *dc = &dma_softc[unit];
300: register struct devqueue *dq;
301:
302: #ifdef DEBUG
303: if (dmadebug & DDB_FOLLOW)
304: printf("dmastop(%d)\n", unit);
305: #endif
306: dc->sc_timo = 0;
307: DMA_CLEAR(dc);
308:
309: /*
310: * We may get this interrupt after a device service routine
311: * has freed the dma channel. So, ignore the intr if there's
312: * nothing on the queue.
313: */
314: dq = dmachan[unit].dq_forw;
315: if (dq != &dmachan[unit]) {
316: #if defined(HP370)
317: /*
318: * The 370 has an 64k external physical address cache.
319: * In theory, we should only need to flush it when
320: * DMAing to memory.
321: */
322: if (ectype == EC_PHYS && (dc->sc_cmd & DMA_WRT) == 0)
323: PCIA();
324: #endif
325: (dq->dq_driver->d_done)(dq->dq_unit);
326: }
327: }
328:
329: int
330: dmaintr()
331: {
332: register struct dma_softc *dc;
333: register int i, j, stat;
334: int found = 0;
335:
336: #ifdef DEBUG
337: if (dmadebug & DDB_FOLLOW)
338: printf("dmaintr\n");
339: #endif
340: for (i = 0, dc = dma_softc; i < NDMA; i++, dc++) {
341: stat = DMA_STAT(dc);
342: if ((stat & DMA_INTR) == 0)
343: continue;
344: found++;
345: #ifdef DEBUG
346: if (dmadebug & DDB_IO) {
347: if ((dmadebug&DDB_WORD) && (dc->sc_cmd&DMA_WORD) ||
348: (dmadebug&DDB_LWORD) && (dc->sc_cmd&DMA_LWORD))
349: printf("dmaintr: unit %d stat %x next %d\n",
350: i, stat, dc->sc_cur+1);
351: }
352: if (stat & DMA_ARMED)
353: printf("dma%d: intr when armed\n", i);
354: #endif
355: j = ++dc->sc_cur;
356: if (j < DMAMAXIO && dc->sc_count[j]) {
357: dc->sc_timo = 1;
358: DMA_CLEAR(dc);
359: DMA_ARM(dc, j);
360: } else
361: dmastop(i);
362: }
363: return(found);
364: }
365:
366: void
367: dmatimo()
368: {
369: register int i, s;
370: register struct dma_softc *dc = &dma_softc[0];
371:
372: for (i = 0; i < NDMA; i++, dc++) {
373: s = splbio();
374: if (dc->sc_timo) {
375: if (dc->sc_timo == 1)
376: dc->sc_timo++;
377: else
378: dmastop(i);
379: }
380: splx(s);
381: }
382: timeout(dmatimo, (caddr_t)0, DMATIMO * hz);
383: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.