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 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
};
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] & 0xFF00FFFF)|((val
& 0xFF) << 16); break;
205 case 0x83: DMA_BaseAddress
[1]=(DMA_BaseAddress
[1] & 0xFF00FFFF)|((val
& 0xFF) << 16); break;
206 case 0x81: DMA_BaseAddress
[2]=(DMA_BaseAddress
[2] & 0xFF00FFFF)|((val
& 0xFF) << 16); break;
207 case 0x82: DMA_BaseAddress
[3]=(DMA_BaseAddress
[3] & 0xFF00FFFF)|((val
& 0xFF) << 16); break;
208 case 0x8B: DMA_BaseAddress
[5]=(DMA_BaseAddress
[5] & 0xFF00FFFF)|((val
& 0xFF) << 16); break;
209 case 0x89: DMA_BaseAddress
[6]=(DMA_BaseAddress
[6] & 0xFF00FFFF)|((val
& 0xFF) << 16); break;
210 case 0x8A: DMA_BaseAddress
[7]=(DMA_BaseAddress
[7] & 0xFF00FFFF)|((val
& 0xFF) << 16); break;
212 /* Low Page Base Address (only 4 lower bits are significant) */
213 case 0x487: DMA_BaseAddress
[0]=(DMA_BaseAddress
[0] & 0x00FFFFFF)|((val
& 0x0F) << 24); break;
214 case 0x483: DMA_BaseAddress
[1]=(DMA_BaseAddress
[1] & 0x00FFFFFF)|((val
& 0x0F) << 24); break;
215 case 0x481: DMA_BaseAddress
[2]=(DMA_BaseAddress
[2] & 0x00FFFFFF)|((val
& 0x0F) << 24); break;
216 case 0x482: DMA_BaseAddress
[3]=(DMA_BaseAddress
[3] & 0x00FFFFFF)|((val
& 0x0F) << 24); break;
217 case 0x48B: DMA_BaseAddress
[5]=(DMA_BaseAddress
[5] & 0x00FFFFFF)|((val
& 0x0F) << 24); break;
218 case 0x489: DMA_BaseAddress
[6]=(DMA_BaseAddress
[6] & 0x00FFFFFF)|((val
& 0x0F) << 24); break;
219 case 0x48A: DMA_BaseAddress
[7]=(DMA_BaseAddress
[7] & 0x00FFFFFF)|((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
];
347 res
= DMA_CurrentByteCount
[channel
] >> 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] >> 16; break;
355 case 0x83: res
= DMA_BaseAddress
[1] >> 16; break;
356 case 0x81: res
= DMA_BaseAddress
[2] >> 16; break;
357 case 0x82: res
= DMA_BaseAddress
[3] >> 16; break;
358 case 0x8B: res
= DMA_BaseAddress
[5] >> 16; break;
359 case 0x89: res
= DMA_BaseAddress
[6] >> 16; break;
360 case 0x8A: res
= DMA_BaseAddress
[7] >> 16; break;
362 /* High Page Base Address */
363 case 0x487: res
= DMA_BaseAddress
[0] >> 24; break;
364 case 0x483: res
= DMA_BaseAddress
[1] >> 24; break;
365 case 0x481: res
= DMA_BaseAddress
[2] >> 24; break;
366 case 0x482: res
= DMA_BaseAddress
[3] >> 24; break;
367 case 0x48B: res
= DMA_BaseAddress
[5] >> 24; break;
368 case 0x489: res
= DMA_BaseAddress
[6] >> 24; break;
369 case 0x48A: res
= DMA_BaseAddress
[7] >> 24; break;
374 TRACE("Status Register Read\n");
375 res
= DMA_Status
[(port
==0x08)?0:1];
381 FIXME("Temporary Register Read- Not Implemented\n");