~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/krnl386.exe16/dma.c

Version: ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * DMA Emulation
  3  *
  4  * Copyright 2002 Christian Costa
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #include "config.h"
 22 
 23 #include <stdarg.h>
 24 
 25 #include "windef.h"
 26 #include "winbase.h"
 27 #include "dosexe.h"
 28 #include "wine/debug.h"
 29 
 30 WINE_DEFAULT_DEBUG_CHANNEL(dma);
 31 
 32 /* Internal registers of the 2 DMA chips which control 8 DMA channels */
 33 static DWORD DMA_BaseAddress[8];
 34 static WORD  DMA_ByteCount[8];
 35 static DWORD DMA_CurrentBaseAddress[8];
 36 static WORD  DMA_CurrentByteCount[8];
 37 static BYTE  DMA_Command[8];
 38 static BYTE  DMA_Mask[2]={0x0F,0x0F};
 39 static BYTE  DMA_Status[2]={0x00,0x00};
 40 static BOOL  DMA_Toggle[2]={FALSE,FALSE};
 41 
 42 /*
 43  * DMA_Transfer : Try to perform a transfer of reqlen elements (8 or 16 bits)
 44  * on the specified channel and return the elements transferred
 45  */
 46 int DMA_Transfer(int channel,int reqlen,void* buffer)
 47 {
 48     int i,size,ret=0;
 49     int opmode,increment,autoinit,trmode,dmachip;
 50     int regmode = DMA_Command[channel];
 51     char *p,*dmabuf;
 52 
 53     dmabuf = buffer;
 54     dmachip = (channel<4) ? 0 : 1;
 55 
 56     TRACE("DMA_Command = %x reqlen=%d\n",regmode,reqlen);
 57 
 58     /* Exit if channel is masked */
 59     if (DMA_Mask[dmachip]&(1<<(channel&3)))
 60         return 0;
 61 
 62     opmode = (regmode & 0xC0) >> 6;
 63     increment = !(regmode & 0x20);
 64     autoinit = regmode & 0x10;
 65     trmode = (regmode & 0x0C) >> 2;
 66 
 67     /* Transfer size : 8 bits for channels 0..3, 16 bits for channels 4..7 */
 68     size = (channel<4) ? 1 : 2;
 69 
 70     /* Process operating mode */
 71     switch(opmode)
 72     {
 73     case 0:
 74         /* Request mode */
 75         FIXME("Request Mode - Not Implemented\n");
 76         return 0;
 77     case 1:
 78         /* Single Mode */
 79         break;
 80     case 2:
 81         /* Request mode */
 82         FIXME("Block Mode - Not Implemented\n");
 83         return 0;
 84     case 3:
 85         /* Cascade Mode */
 86         ERR("Cascade Mode should not be used by regular apps\n");
 87         return 0;
 88     }
 89 
 90     /* Perform one the 4 transfer modes */
 91     if (trmode == 4) {
 92         /* Illegal */
 93         ERR("DMA Transfer Type Illegal\n");
 94         return 0;
 95     }
 96 
 97     ret = min(DMA_CurrentByteCount[channel],reqlen);
 98 
 99     /* Update DMA registers */
100     DMA_CurrentByteCount[channel]-=ret;
101     if (increment)
102         DMA_CurrentBaseAddress[channel] += ret * size;
103     else
104         DMA_CurrentBaseAddress[channel] -= ret * size;
105 
106     switch(trmode)
107     {
108     case 0:
109         /* Verification (no real transfer)*/
110         TRACE("Verification DMA operation\n");
111         break;
112     case 1:
113         /* Write */
114         TRACE("Perform Write transfer of %d bytes at %x with count %x\n",ret,
115             DMA_CurrentBaseAddress[channel],DMA_CurrentByteCount[channel]);
116         if (increment)
117             memcpy((void*)DMA_CurrentBaseAddress[channel],dmabuf,ret*size);
118         else
119             for(i=0,p=(char*)DMA_CurrentBaseAddress[channel];i<ret*size;i++)
120                 /* FIXME: possible endianness issue for 16 bits DMA */
121                 *(p-i) = dmabuf[i];
122         break;
123     case 2:
124         /* Read */
125         TRACE("Perform Read transfer of %d bytes at %x with count %x\n",ret,
126             DMA_CurrentBaseAddress[channel],DMA_CurrentByteCount[channel]);
127         if (increment)
128             memcpy(dmabuf,(void*)DMA_CurrentBaseAddress[channel],ret*size);
129         else
130             for(i=0,p=(char*)DMA_CurrentBaseAddress[channel];i<ret*size;i++)
131                 /* FIXME: possible endianness issue for 16 bits DMA */
132                 dmabuf[i] = *(p-i);
133         break;
134     }
135 
136     /* Check for end of transfer */
137     if (DMA_CurrentByteCount[channel]==0) {
138         TRACE("DMA buffer empty\n");
139 
140         /* Update status register of the DMA chip corresponding to the channel */
141         DMA_Status[dmachip] |= 1 << (channel & 0x3); /* Mark transfer as finished */
142         DMA_Status[dmachip] &= ~(1 << ((channel & 0x3) + 4)); /* Reset soft request if any */
143 
144         if (autoinit) {
145             /* Reload Current* register to their initial values */
146             DMA_CurrentBaseAddress[channel] = DMA_BaseAddress[channel];
147             DMA_CurrentByteCount[channel] = DMA_ByteCount[channel];
148         }
149     }
150 
151     return ret;
152 }
153 
154 
155 void DMA_ioport_out( WORD port, BYTE val )
156 {
157     int channel,dmachip;
158 
159     switch(port)
160     {
161     case 0x00:
162     case 0x02:
163     case 0x04:
164     case 0x06:
165     case 0xC0:
166     case 0xC4:
167     case 0xC8:
168     case 0xCC:
169         /* Base Address*/
170         channel = (port&0xC0)?((port-0xC0)>>2):(port>>1);
171         dmachip = (channel<4) ? 0 : 1;
172         if (!DMA_Toggle[dmachip])
173             DMA_BaseAddress[channel]=(DMA_BaseAddress[channel] & ~0xFF)|(val & 0xFF);
174         else {
175             DMA_BaseAddress[channel]=(DMA_BaseAddress[channel] & (~(0xFF << 8)))|((val & 0xFF) << 8);
176             DMA_CurrentBaseAddress[channel] = DMA_BaseAddress[channel];
177             TRACE("Write Base Address = %x\n",DMA_BaseAddress[channel]);
178         }
179         DMA_Toggle[dmachip] = !DMA_Toggle[dmachip];
180         break;
181 
182     case 0x01:
183     case 0x03:
184     case 0x05:
185     case 0x07:
186     case 0xC2:
187     case 0xC6:
188     case 0xCA:
189     case 0xCE:
190         /* Count*/
191         channel = ((port-1)&0xC0)?(((port-1)-0xC0)>>2):(port>>1);
192         dmachip = (channel<4) ? 0 : 1;
193         if (!DMA_Toggle[dmachip])
194             DMA_ByteCount[channel]=(DMA_ByteCount[channel] & ~0xFF)|((val+1) & 0xFF);
195         else {
196             DMA_ByteCount[channel]=(DMA_ByteCount[channel] & (~(0xFF << 8)))|(((val+1) & 0xFF) << 8);
197             DMA_CurrentByteCount[channel] = DMA_ByteCount[channel];
198             TRACE("Write Count = %x.\n",DMA_ByteCount[channel]);
199         }
200         DMA_Toggle[dmachip] = !DMA_Toggle[dmachip];
201         break;
202 
203     /* Low Page Base Address */
204     case 0x87: DMA_BaseAddress[0]=(DMA_BaseAddress[0] & (~0xFF << 16))|((val & 0xFF) << 16); break;
205     case 0x83: DMA_BaseAddress[1]=(DMA_BaseAddress[1] & (~0xFF << 16))|((val & 0xFF) << 16); break;
206     case 0x81: DMA_BaseAddress[2]=(DMA_BaseAddress[2] & (~0xFF << 16))|((val & 0xFF) << 16); break;
207     case 0x82: DMA_BaseAddress[3]=(DMA_BaseAddress[3] & (~0xFF << 16))|((val & 0xFF) << 16); break;
208     case 0x8B: DMA_BaseAddress[5]=(DMA_BaseAddress[5] & (~0xFF << 16))|((val & 0xFF) << 16); break;
209     case 0x89: DMA_BaseAddress[6]=(DMA_BaseAddress[6] & (~0xFF << 16))|((val & 0xFF) << 16); break;
210     case 0x8A: DMA_BaseAddress[7]=(DMA_BaseAddress[7] & (~0xFF << 16))|((val & 0xFF) << 16); break;
211 
212     /* Low Page Base Address (only 4 lower bits are significant) */
213     case 0x487: DMA_BaseAddress[0]=(DMA_BaseAddress[0] & (~0xFF << 24))|((val & 0x0F) << 24); break;
214     case 0x483: DMA_BaseAddress[1]=(DMA_BaseAddress[1] & (~0xFF << 24))|((val & 0x0F) << 24); break;
215     case 0x481: DMA_BaseAddress[2]=(DMA_BaseAddress[2] & (~0xFF << 24))|((val & 0x0F) << 24); break;
216     case 0x482: DMA_BaseAddress[3]=(DMA_BaseAddress[3] & (~0xFF << 24))|((val & 0x0F) << 24); break;
217     case 0x48B: DMA_BaseAddress[5]=(DMA_BaseAddress[5] & (~0xFF << 24))|((val & 0x0F) << 24); break;
218     case 0x489: DMA_BaseAddress[6]=(DMA_BaseAddress[6] & (~0xFF << 24))|((val & 0x0F) << 24); break;
219     case 0x48A: DMA_BaseAddress[7]=(DMA_BaseAddress[7] & (~0xFF << 24))|((val & 0x0F) << 24); break;
220 
221     case 0x08:
222     case 0xD0:
223         /* Command */
224         FIXME("Write Command (%x) - Not Implemented\n",val);
225         break;
226 
227     case 0x0B:
228     case 0xD6:
229         /* Mode */
230         TRACE("Write Mode (%x)\n",val);
231         DMA_Command[((port==0xD6)?4:0)+(val&0x3)]=val;
232         switch(val>>6)
233         {
234         case 0:
235             /* Request mode */
236             FIXME("Request Mode - Not Implemented\n");
237             break;
238         case 1:
239             /* Single Mode */
240             break;
241         case 2:
242             /* Block mode */
243             FIXME("Block Mode - Not Implemented\n");
244             break;
245         case 3:
246             /* Cascade Mode */
247             ERR("Cascade Mode should not be used by regular apps\n");
248             break;
249         }
250         break;
251 
252     case 0x0A:
253     case 0xD4:
254         /* Write Single Mask Bit */
255         TRACE("Write Single Mask Bit (%x)\n",val);
256         dmachip = (port==0x0A) ? 0 : 1;
257         if (val&4)
258             DMA_Mask[dmachip] |= 1<<(val&3);
259         else
260             DMA_Mask[dmachip] &= ~(1<<(val&3));
261         break;
262 
263     case 0x0F:
264     case 0xDE:
265         /* Write All Mask Bits (only 4 lower bits are significant */
266         FIXME("Write All Mask Bits (%x)\n",val);
267         dmachip = (port==0x0F) ? 0 : 1;
268         DMA_Mask[dmachip] = val & 0x0F;
269         break;
270 
271     case 0x09:
272     case 0xD2:
273         /* Software DRQx Request */
274         FIXME("Software DRQx Request (%x) - Not Implemented\n",val);
275         break;
276 
277     case 0x0C:
278     case 0xD8:
279         /* Reset DMA Pointer Flip-Flop */
280         TRACE("Reset Flip-Flop\n");
281         DMA_Toggle[port==0xD8]=FALSE;
282         break;
283 
284     case 0x0D:
285     case 0xDA:
286         /* Master Reset */
287         TRACE("Master Reset\n");
288         dmachip = (port==0x0D) ? 0 : 1;
289         /* Reset DMA Pointer Flip-Flop */
290         DMA_Toggle[dmachip]=FALSE;
291         /* Mask all channels */
292         DMA_Mask[dmachip] = 0x0F;
293         break;
294 
295     case 0x0E:
296     case 0xDC:
297         /* Reset Mask Register */
298         FIXME("Reset Mask Register\n");
299         dmachip = (port==0x0E) ? 0 : 1;
300         /* Unmask all channels */
301         DMA_Mask[dmachip] = 0x00;
302         break;
303     }
304 }
305 
306 BYTE DMA_ioport_in( WORD port )
307 {
308     int channel,dmachip;
309     BYTE res = 0;
310 
311     switch(port)
312     {
313     case 0x00:
314     case 0x02:
315     case 0x04:
316     case 0x06:
317     case 0xC0:
318     case 0xC4:
319     case 0xC8:
320     case 0xCC:
321         /* Base Address*/
322         channel = (port&0xC0)?((port-0xC0)>>2):(port>>1);
323         dmachip = (channel<4) ? 0 : 1;
324         if (!DMA_Toggle[dmachip])
325             res = DMA_CurrentBaseAddress[channel] & 0xFF;
326         else {
327             res = (DMA_CurrentBaseAddress[channel] & (0xFF << 8))>>8;
328             TRACE("Read Current Base Address = %x\n",DMA_CurrentBaseAddress[channel]);
329         }
330         DMA_Toggle[dmachip] = !DMA_Toggle[dmachip];
331         break;
332 
333     case 0x01:
334     case 0x03:
335     case 0x05:
336     case 0x07:
337     case 0xC2:
338     case 0xC6:
339     case 0xCA:
340     case 0xCE:
341         /* Count*/
342         channel = ((port-1)&0xC0)?(((port-1)-0xC0)>>2):(port>>1);
343         dmachip = (channel<4) ? 0 : 1;
344         if (!DMA_Toggle[dmachip])
345             res = DMA_CurrentByteCount[channel] & 0xFF;
346         else {
347             res = (DMA_CurrentByteCount[channel] & (0xFF << 8))>>8;
348             TRACE("Read Current Count = %x.\n",DMA_CurrentByteCount[channel]);
349         }
350         DMA_Toggle[dmachip] = !DMA_Toggle[dmachip];
351         break;
352 
353     /* Low Page Base Address */
354     case 0x87: res = (DMA_BaseAddress[0]&(0xFF<<16))>>16; break;
355     case 0x83: res = (DMA_BaseAddress[1]&(0xFF<<16))>>16; break;
356     case 0x81: res = (DMA_BaseAddress[2]&(0xFF<<16))>>16; break;
357     case 0x82: res = (DMA_BaseAddress[3]&(0xFF<<16))>>16; break;
358     case 0x8B: res = (DMA_BaseAddress[5]&(0xFF<<16))>>16; break;
359     case 0x89: res = (DMA_BaseAddress[6]&(0xFF<<16))>>16; break;
360     case 0x8A: res = (DMA_BaseAddress[7]&(0xFF<<16))>>16; break;
361 
362     /* High Page Base Address */
363     case 0x487: res = (DMA_BaseAddress[0]&(0xFF<<24))>>24; break;
364     case 0x483: res = (DMA_BaseAddress[1]&(0xFF<<24))>>24; break;
365     case 0x481: res = (DMA_BaseAddress[2]&(0xFF<<24))>>24; break;
366     case 0x482: res = (DMA_BaseAddress[3]&(0xFF<<24))>>24; break;
367     case 0x48B: res = (DMA_BaseAddress[5]&(0xFF<<24))>>24; break;
368     case 0x489: res = (DMA_BaseAddress[6]&(0xFF<<24))>>24; break;
369     case 0x48A: res = (DMA_BaseAddress[7]&(0xFF<<24))>>24; break;
370 
371     case 0x08:
372     case 0xD0:
373         /* Status */
374         TRACE("Status Register Read\n");
375         res = DMA_Status[(port==0x08)?0:1];
376         break;
377 
378     case 0x0D:
379     case 0xDA:
380         /* Temporary */
381         FIXME("Temporary Register Read- Not Implemented\n");
382         break;
383     }
384     return res;
385 }
386 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.