|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6:
7: /*
8: * headland chip set for the safari.
9: */
10: typedef struct DMAport DMAport;
11: typedef struct DMA DMA;
12: typedef struct DMAxfer DMAxfer;
13:
14: enum
15: {
16: /*
17: * the byte registers for DMA0 are all one byte apart
18: */
19: Dma0= 0x00,
20: Dma0status= Dma0+0x8, /* status port */
21: Dma0reset= Dma0+0xD, /* reset port */
22:
23: /*
24: * the byte registers for DMA1 are all two bytes apart (why?)
25: */
26: Dma1= 0xC0,
27: Dma1status= Dma1+2*0x8, /* status port */
28: Dma1reset= Dma1+2*0xD, /* reset port */
29: };
30:
31: /*
32: * state of a dma transfer
33: */
34: struct DMAxfer
35: {
36: Page pg; /* page used by dma */
37: void *va; /* virtual address destination/src */
38: long len; /* bytes to be transferred */
39: int isread;
40: };
41:
42: /*
43: * the dma controllers. the first half of this structure specifies
44: * the I/O ports used by the DMA controllers.
45: */
46: struct DMAport
47: {
48: uchar addr[4]; /* current address (4 channels) */
49: uchar count[4]; /* current count (4 channels) */
50: uchar page[4]; /* page registers (4 channels) */
51: uchar cmd; /* command status register */
52: uchar req; /* request registers */
53: uchar sbm; /* single bit mask register */
54: uchar mode; /* mode register */
55: uchar cbp; /* clear byte pointer */
56: uchar mc; /* master clear */
57: uchar cmask; /* clear mask register */
58: uchar wam; /* write all mask register bit */
59: };
60:
61: struct DMA
62: {
63: DMAport;
64: int shift;
65: Lock;
66: DMAxfer x[4];
67: };
68:
69: DMA dma[2] = {
70: { 0x00, 0x02, 0x04, 0x06,
71: 0x01, 0x03, 0x05, 0x07,
72: 0x87, 0x83, 0x81, 0x82,
73: 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
74: 0 },
75:
76: { 0xc0, 0xc4, 0xc8, 0xcc,
77: 0xc2, 0xc6, 0xca, 0xce,
78: 0x8f, 0x8b, 0x89, 0x8a,
79: 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
80: 1 },
81: };
82:
83: /*
84: * DMA must be in the first 16 meg. This gets called early by main() to
85: * ensure that.
86: */
87: void
88: dmainit(void)
89: {
90: int i, chan;
91: DMA *dp;
92: DMAxfer *xp;
93:
94: for(i = 0; i < 2; i++){
95: dp = &dma[i];
96: for(chan = 0; chan < 4; chan++){
97: xp = &dp->x[chan];
98: xp->pg.pa = (ulong)xspanalloc(BY2PG, BY2PG, 0);
99: xp->pg.va = KZERO|xp->pg.pa;
100: xp->len = 0;
101: xp->isread = 0;
102: }
103: }
104: }
105:
106: /*
107: * setup a dma transfer. if the destination is not in kernel
108: * memory, allocate a page for the transfer.
109: *
110: * we assume BIOS has set up the command register before we
111: * are booted.
112: *
113: * return the updated transfer length (we can't transfer across 64k
114: * boundaries)
115: */
116: long
117: dmasetup(int chan, void *va, long len, int isread)
118: {
119: DMA *dp;
120: DMAxfer *xp;
121: ulong pa;
122: uchar mode;
123:
124: dp = &dma[(chan>>2)&1];
125: chan = chan & 3;
126: xp = &dp->x[chan];
127:
128: /*
129: * if this isn't kernel memory or crossing 64k boundary or above 16 meg
130: * use the allocated low memory page.
131: */
132: pa = PADDR(va);
133: if((((ulong)va)&0xF0000000) != KZERO
134: || (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
135: || pa > 16*MB){
136: if(len > BY2PG)
137: len = BY2PG;
138: if(!isread)
139: memmove((void*)(xp->pg.va), va, len);
140: xp->va = va;
141: xp->len = len;
142: xp->isread = isread;
143: pa = xp->pg.pa;
144: } else
145: xp->len = 0;
146:
147: /*
148: * this setup must be atomic
149: */
150: ilock(dp);
151: mode = (isread ? 0x44 : 0x48) | chan;
152: outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */
153: outb(dp->page[chan], pa>>16);
154: outb(dp->cbp, 0); /* set count & address to their first byte */
155: outb(dp->addr[chan], pa>>dp->shift); /* set address */
156: outb(dp->addr[chan], pa>>(8+dp->shift));
157: outb(dp->count[chan], (len>>dp->shift)-1); /* set count */
158: outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
159: outb(dp->sbm, chan); /* enable the channel */
160: iunlock(dp);
161:
162: return len;
163: }
164:
165: /*
166: * this must be called after a dma has been completed.
167: *
168: * if a page has been allocated for the dma,
169: * copy the data into the actual destination
170: * and free the page.
171: */
172: void
173: dmaend(int chan)
174: {
175: DMA *dp;
176: DMAxfer *xp;
177:
178: dp = &dma[(chan>>2)&1];
179: chan = chan & 3;
180:
181: /*
182: * disable the channel
183: */
184: ilock(dp);
185: outb(dp->sbm, 4|chan);
186: iunlock(dp);
187:
188: xp = &dp->x[chan];
189: if(xp->len == 0 || !xp->isread)
190: return;
191:
192: /*
193: * copy out of temporary page
194: */
195: memmove(xp->va, (void*)(xp->pg.va), xp->len);
196: xp->len = 0;
197: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.