4 * Copyright 2002 Christian Costa
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.
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.
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
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dma);
32 /* Internal registers of the 2 DMA chips wich 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};
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
46 int DMA_Transfer(int channel,int reqlen,void* buffer)
49 int opmode,increment,autoinit,trmode,dmachip;
50 int regmode = DMA_Command[channel];
54 dmachip = (channel<4) ? 0 : 1;
56 TRACE("DMA_Command = %x reqlen=%d\n",regmode,reqlen);
58 /* Exit if channel is masked */
59 if (DMA_Mask[dmachip]&(1<<(channel&3)))
62 opmode = (regmode & 0xC0) >> 6;
63 increment = !(regmode & 0x20);
64 autoinit = regmode & 0x10;
65 trmode = (regmode & 0x0C) >> 2;
67 /* Transfer size : 8 bits for channels 0..3, 16 bits for channels 4..7 */
68 size = (channel<4) ? 1 : 2;
70 /* Process operating mode */
75 FIXME("Request Mode - Not Implemented\n");
82 FIXME("Block Mode - Not Implemented\n");
86 ERR("Cascade Mode should not be used by regular apps\n");
90 /* Perform one the 4 transfer modes */
93 ERR("DMA Transfer Type Illegal\n");
97 ret = min(DMA_CurrentByteCount[channel],reqlen);
99 /* Update DMA registers */
100 DMA_CurrentByteCount[channel]-=ret;
102 DMA_CurrentBaseAddress[channel] += ret * size;
104 DMA_CurrentBaseAddress[channel] -= ret * size;
109 /* Verification (no real transfer)*/
110 TRACE("Verification DMA operation\n");
114 TRACE("Perform Write transfer of %d bytes at %x with count %x\n",ret,
115 DMA_CurrentBaseAddress[channel],DMA_CurrentByteCount[channel]);
117 memcpy((void*)DMA_CurrentBaseAddress[channel],dmabuf,ret*size);
119 for(i=0,p=(char*)DMA_CurrentBaseAddress[channel];i<ret*size;i++)
120 /* FIXME: possible endianness issue for 16 bits DMA */
125 TRACE("Perform Read transfer of %d bytes at %x with count %x\n",ret,
126 DMA_CurrentBaseAddress[channel],DMA_CurrentByteCount[channel]);
128 memcpy(dmabuf,(void*)DMA_CurrentBaseAddress[channel],ret*size);
130 for(i=0,p=(char*)DMA_CurrentBaseAddress[channel];i<ret*size;i++)
131 /* FIXME: possible endianness issue for 16 bits DMA */
136 /* Check for end of transfer */
137 if (DMA_CurrentByteCount[channel]==0) {
138 TRACE("DMA buffer empty\n");
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 */
145 /* Reload Current* register to their initial values */
146 DMA_CurrentBaseAddress[channel] = DMA_BaseAddress[channel];
147 DMA_CurrentByteCount[channel] = DMA_ByteCount[channel];
155 void DMA_ioport_out( WORD port, BYTE val )
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);
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]);
179 DMA_Toggle[dmachip] = !DMA_Toggle[dmachip];
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);
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]);
200 DMA_Toggle[dmachip] = !DMA_Toggle[dmachip];
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;
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;
224 FIXME("Write Command (%x) - Not Implemented\n",val);
230 TRACE("Write Mode (%x)\n",val);
231 DMA_Command[((port==0xD6)?4:0)+(val&0x3)]=val;
236 FIXME("Request Mode - Not Implemented\n");
243 FIXME("Block Mode - Not Implemented\n");
247 ERR("Cascade Mode should not be used by regular apps\n");
254 /* Write Single Mask Bit */
255 TRACE("Write Single Mask Bit (%x)\n",val);
256 dmachip = (port==0x0A) ? 0 : 1;
258 DMA_Mask[dmachip] |= 1<<(val&3);
260 DMA_Mask[dmachip] &= ~(1<<(val&3));
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;
273 /* Software DRQx Request */
274 FIXME("Software DRQx Request (%x) - Not Implemented\n",val);
279 /* Reset DMA Pointer Flip-Flop */
280 TRACE("Reset Flip-Flop\n");
281 DMA_Toggle[port==0xD8]=FALSE;
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;
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;
306 BYTE DMA_ioport_in( WORD port )
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;
327 res = (DMA_CurrentBaseAddress[channel] & (0xFF << 8))>>8;
328 TRACE("Read Current Base Address = %x\n",DMA_CurrentBaseAddress[channel]);
330 DMA_Toggle[dmachip] = !DMA_Toggle[dmachip];
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;
347 res = (DMA_CurrentByteCount[channel] & (0xFF << 8))>>8;
348 TRACE("Read Current Count = %x.\n",DMA_CurrentByteCount[channel]);
350 DMA_Toggle[dmachip] = !DMA_Toggle[dmachip];
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;
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;
374 TRACE("Status Register Read\n");
375 res = DMA_Status[(port==0x08)?0:1];
380 FIXME("Temporary Register Read- Not Implemented\n");