debuggers.hg

view tools/ioemu/iodev/dma.cc @ 3680:26a00896163a

bitkeeper revision 1.1159.240.3 (4202bd17uoTYqnlSeqvW9fHjznmCHg)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into labyrinth.cl.cam.ac.uk:/auto/groups/xeno/users/iap10/xeno-clone/xen-unstable.bk
author iap10@labyrinth.cl.cam.ac.uk
date Fri Feb 04 00:08:55 2005 +0000 (2005-02-04)
parents 2c56c6b39a48 f89816eaeaad
children d3f0465c034e
line source
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: dma.cc,v 1.30 2003/07/31 15:29:34 vruppert Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2002 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
12 //
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
17 //
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
30 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
31 // is used to know when we are exporting symbols and when we are importing.
32 #define BX_PLUGGABLE
34 #include "bochs.h"
36 #define LOG_THIS theDmaDevice->
38 #define DMA_MODE_DEMAND 0
39 #define DMA_MODE_SINGLE 1
40 #define DMA_MODE_BLOCK 2
41 #define DMA_MODE_CASCADE 3
43 bx_dma_c *theDmaDevice = NULL;
45 int
46 libdma_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
47 {
48 theDmaDevice = new bx_dma_c ();
49 bx_devices.pluginDmaDevice = theDmaDevice;
50 BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theDmaDevice, BX_PLUGIN_DMA);
51 return(0); // Success
52 }
54 void
55 libdma_LTX_plugin_fini(void)
56 {
57 }
59 bx_dma_c::bx_dma_c(void)
60 {
61 put("DMA");
62 settype(DMALOG);
63 }
65 bx_dma_c::~bx_dma_c(void)
66 {
67 BX_DEBUG(("Exit."));
68 }
70 unsigned
71 bx_dma_c::registerDMA8Channel(
72 unsigned channel,
73 void (* dmaRead)(Bit8u *data_byte),
74 void (* dmaWrite)(Bit8u *data_byte),
75 const char *name
76 )
77 {
78 if (channel > 3) {
79 BX_PANIC(("registerDMA8Channel: invalid channel number(%u).", channel));
80 return 0; // Fail.
81 }
82 if (BX_DMA_THIS s[0].chan[channel].used) {
83 BX_PANIC(("registerDMA8Channel: channel(%u) already in use.", channel));
84 return 0; // Fail.
85 }
86 BX_INFO(("channel %u used by %s", channel, name));
87 BX_DMA_THIS h[channel].dmaRead8 = dmaRead;
88 BX_DMA_THIS h[channel].dmaWrite8 = dmaWrite;
89 BX_DMA_THIS s[0].chan[channel].used = 1;
90 return 1; // OK.
91 }
93 unsigned
94 bx_dma_c::registerDMA16Channel(
95 unsigned channel,
96 void (* dmaRead)(Bit16u *data_word),
97 void (* dmaWrite)(Bit16u *data_word),
98 const char *name
99 )
100 {
101 if ((channel < 4) || (channel > 7)) {
102 BX_PANIC(("registerDMA16Channel: invalid channel number(%u).", channel));
103 return 0; // Fail.
104 }
105 if (BX_DMA_THIS s[1].chan[channel & 0x03].used) {
106 BX_PANIC(("registerDMA16Channel: channel(%u) already in use.", channel));
107 return 0; // Fail.
108 }
109 BX_INFO(("channel %u used by %s", channel, name));
110 channel &= 0x03;
111 BX_DMA_THIS h[channel].dmaRead16 = dmaRead;
112 BX_DMA_THIS h[channel].dmaWrite16 = dmaWrite;
113 BX_DMA_THIS s[1].chan[channel].used = 1;
114 return 1; // OK.
115 }
117 unsigned
118 bx_dma_c::unregisterDMAChannel(unsigned channel)
119 {
120 bx_bool ma_sl = (channel > 3);
121 BX_DMA_THIS s[ma_sl].chan[channel & 0x03].used = 0;
122 BX_INFO(("channel %u no longer used", channel));
123 return 1;
124 }
126 unsigned
127 bx_dma_c::get_TC(void)
128 {
129 return BX_DMA_THIS TC;
130 }
133 void
134 bx_dma_c::init(void)
135 {
136 unsigned c, i, j;
137 BX_DEBUG(("Init $Id: dma.cc,v 1.30 2003/07/31 15:29:34 vruppert Exp $"));
139 /* 8237 DMA controller */
141 for (i=0; i < 2; i++) {
142 for (j=0; j < 4; j++) {
143 BX_DMA_THIS s[i].DRQ[j] = 0;
144 BX_DMA_THIS s[i].DACK[j] = 0;
145 }
146 }
147 BX_DMA_THIS HLDA = 0;
148 BX_DMA_THIS TC = 0;
150 // 0000..000F
151 for (i=0x0000; i<=0x000F; i++) {
152 DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1);
153 DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3);
154 }
156 // 00081..008F
157 for (i=0x0081; i<=0x008F; i++) {
158 DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1);
159 DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3);
160 }
162 // 000C0..00DE
163 for (i=0x00C0; i<=0x00DE; i+=2) {
164 DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1);
165 DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3);
166 }
169 for (i=0; i<2; i++) {
170 for (c=0; c<4; c++) {
171 BX_DMA_THIS s[i].chan[c].mode.mode_type = 0; // demand mode
172 BX_DMA_THIS s[i].chan[c].mode.address_decrement = 0; // address increment
173 BX_DMA_THIS s[i].chan[c].mode.autoinit_enable = 0; // autoinit disable
174 BX_DMA_THIS s[i].chan[c].mode.transfer_type = 0; // verify
175 BX_DMA_THIS s[i].chan[c].base_address = 0;
176 BX_DMA_THIS s[i].chan[c].current_address = 0;
177 BX_DMA_THIS s[i].chan[c].base_count = 0;
178 BX_DMA_THIS s[i].chan[c].current_count = 0;
179 BX_DMA_THIS s[i].chan[c].page_reg = 0;
180 BX_DMA_THIS s[i].chan[c].used = 0;
181 }
182 }
183 BX_DMA_THIS s[1].chan[0].used = 1; // cascade channel in use
184 BX_INFO(("channel 4 used by cascade"));
185 bios_init();
186 }
188 /* Remove it when guest fw ready*/
189 void
190 bx_dma_c::bios_init(void){
191 BX_DMA_THIS s[1].mask[0] = 0; // unmask cascade channel
192 BX_DMA_THIS s[1].chan[0].mode.mode_type = 3; // cascade mode for channel 4
193 }
195 void
196 bx_dma_c::reset(unsigned type)
197 {
198 reset_controller(0);
199 reset_controller(1);
200 bios_init();
201 }
203 void
204 bx_dma_c::reset_controller(unsigned num)
205 {
206 BX_DMA_THIS s[num].mask[0] = 1;
207 BX_DMA_THIS s[num].mask[1] = 1;
208 BX_DMA_THIS s[num].mask[2] = 1;
209 BX_DMA_THIS s[num].mask[3] = 1;
210 BX_DMA_THIS s[num].command_reg = 0;
211 BX_DMA_THIS s[num].status_reg = 0;
212 BX_DMA_THIS s[num].request_reg = 0;
213 BX_DMA_THIS s[num].temporary_reg = 0;
214 BX_DMA_THIS s[num].flip_flop = 0;
215 }
217 // index to find channel from register number (only [0],[1],[2],[6] used)
218 Bit8u channelindex[7] = {2, 3, 1, 0, 0, 0, 0};
221 // static IO port read callback handler
222 // redirects to non-static class handler to avoid virtual functions
224 Bit32u
225 bx_dma_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
226 {
227 #if !BX_USE_DMA_SMF
228 bx_dma_c *class_ptr = (bx_dma_c *) this_ptr;
230 return( class_ptr->read(address, io_len) );
231 }
233 /* 8237 DMA controller */
234 Bit32u BX_CPP_AttrRegparmN(2)
235 bx_dma_c::read( Bit32u address, unsigned io_len)
236 {
237 #else
238 UNUSED(this_ptr);
239 #endif // !BX_USE_DMA_SMF
241 Bit8u retval;
242 Bit8u channel;
243 bx_bool ma_sl;
245 BX_DEBUG(("read addr=%04x", (unsigned) address));
247 #if BX_DMA_FLOPPY_IO < 1
248 /* if we're not supporting DMA/floppy IO just return a bogus value */
249 return(0xff);
250 #endif
252 switch (address) {
253 case 0x00: /* DMA-1 current address, channel 0 */
254 case 0x02: /* DMA-1 current address, channel 1 */
255 case 0x04: /* DMA-1 current address, channel 2 */
256 case 0x06: /* DMA-1 current address, channel 3 */
257 case 0xc0: /* DMA-2 current address, channel 0 */
258 case 0xc4: /* DMA-2 current address, channel 1 */
259 case 0xc8: /* DMA-2 current address, channel 2 */
260 case 0xcc: /* DMA-2 current address, channel 3 */
261 ma_sl = (address >= 0xc0);
262 channel = (address >> (1 + ma_sl)) & 0x03;
263 if (BX_DMA_THIS s[ma_sl].flip_flop==0) {
264 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
265 return(BX_DMA_THIS s[ma_sl].chan[channel].current_address & 0xff);
266 }
267 else {
268 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
269 return(BX_DMA_THIS s[ma_sl].chan[channel].current_address >> 8);
270 }
272 case 0x01: /* DMA-1 current count, channel 0 */
273 case 0x03: /* DMA-1 current count, channel 1 */
274 case 0x05: /* DMA-1 current count, channel 2 */
275 case 0x07: /* DMA-1 current count, channel 3 */
276 case 0xc2: /* DMA-2 current count, channel 0 */
277 case 0xc6: /* DMA-2 current count, channel 1 */
278 case 0xca: /* DMA-2 current count, channel 2 */
279 case 0xce: /* DMA-2 current count, channel 3 */
280 ma_sl = (address >= 0xc2);
281 channel = (address >> (1 + ma_sl)) & 0x03;
282 if (BX_DMA_THIS s[ma_sl].flip_flop==0) {
283 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
284 return(BX_DMA_THIS s[ma_sl].chan[channel].current_count & 0xff);
285 }
286 else {
287 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
288 return(BX_DMA_THIS s[ma_sl].chan[channel].current_count >> 8);
289 }
291 case 0x08: // DMA-1 Status Register
292 case 0xd0: // DMA-2 Status Register
293 // bit 7: 1 = channel 3 request
294 // bit 6: 1 = channel 2 request
295 // bit 5: 1 = channel 1 request
296 // bit 4: 1 = channel 0 request
297 // bit 3: 1 = channel 3 has reached terminal count
298 // bit 2: 1 = channel 2 has reached terminal count
299 // bit 1: 1 = channel 1 has reached terminal count
300 // bit 0: 1 = channel 0 has reached terminal count
301 // reading this register clears lower 4 bits (hold flags)
302 ma_sl = (address == 0xd0);
303 retval = BX_DMA_THIS s[ma_sl].status_reg;
304 BX_DMA_THIS s[ma_sl].status_reg &= 0xf0;
305 return(retval);
306 break;
307 case 0x0d: // DMA-1: temporary register
308 case 0xda: // DMA-2: temporary register
309 ma_sl = (address == 0xda);
310 BX_ERROR(("DMA-%d: read of temporary register", ma_sl+1));
311 // Note: write to 0x0D clears temporary register
312 return(0);
313 break;
315 case 0x0081: // DMA-1 page register, channel 2
316 case 0x0082: // DMA-1 page register, channel 3
317 case 0x0083: // DMA-1 page register, channel 1
318 case 0x0087: // DMA-1 page register, channel 0
319 channel = channelindex[address - 0x81];
320 return( BX_DMA_THIS s[0].chan[channel].page_reg );
322 case 0x0089: // DMA-2 page register, channel 2
323 case 0x008a: // DMA-2 page register, channel 3
324 case 0x008b: // DMA-2 page register, channel 1
325 case 0x008f: // DMA-2 page register, channel 0
326 channel = channelindex[address - 0x89];
327 return( BX_DMA_THIS s[1].chan[channel].page_reg );
329 case 0x0084:
330 case 0x0085:
331 case 0x0086:
332 case 0x0088:
333 case 0x008c:
334 case 0x008d:
335 case 0x008e:
336 BX_DEBUG(("read: extra page register 0x%04x unsupported", (unsigned) address));
337 return(0);
339 default:
340 BX_ERROR(("read: unsupported address=%04x", (unsigned) address));
341 return(0);
342 }
343 }
346 // static IO port write callback handler
347 // redirects to non-static class handler to avoid virtual functions
349 void
350 bx_dma_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
351 {
352 #if !BX_USE_DMA_SMF
353 bx_dma_c *class_ptr = (bx_dma_c *) this_ptr;
355 class_ptr->write(address, value, io_len);
356 }
359 /* 8237 DMA controller */
360 void BX_CPP_AttrRegparmN(3)
361 bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len)
362 {
363 #else
364 UNUSED(this_ptr);
365 #endif // !BX_USE_DMA_SMF
366 Bit8u set_mask_bit;
367 Bit8u channel;
368 bx_bool ma_sl;
370 if (io_len > 1) {
371 if ( (io_len == 2) && (address == 0x0b) ) {
372 #if BX_USE_DMA_SMF
373 BX_DMA_THIS write_handler(NULL, address, value & 0xff, 1);
374 BX_DMA_THIS write_handler(NULL, address+1, value >> 8, 1);
375 #else
376 BX_DMA_THIS write(address, value & 0xff, 1);
377 BX_DMA_THIS write(address+1, value >> 8, 1);
378 #endif
379 return;
380 }
382 BX_ERROR(("io write to address %08x, len=%u",
383 (unsigned) address, (unsigned) io_len));
384 return;
385 }
387 BX_DEBUG(("write: address=%04x value=%02x",
388 (unsigned) address, (unsigned) value));
390 #if BX_DMA_FLOPPY_IO < 1
391 /* if we're not supporting DMA/floppy IO just return */
392 return;
393 #endif
395 switch (address) {
396 case 0x00:
397 case 0x02:
398 case 0x04:
399 case 0x06:
400 case 0xc0:
401 case 0xc4:
402 case 0xc8:
403 case 0xcc:
404 ma_sl = (address >= 0xc0);
405 channel = (address >> (1 + ma_sl)) & 0x03;
406 BX_DEBUG((" DMA-%d base and current address, channel %d", ma_sl+1, channel));
407 if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */
408 BX_DMA_THIS s[ma_sl].chan[channel].base_address = value;
409 BX_DMA_THIS s[ma_sl].chan[channel].current_address = value;
410 }
411 else { /* 2nd byte */
412 BX_DMA_THIS s[ma_sl].chan[channel].base_address |= (value << 8);
413 BX_DMA_THIS s[ma_sl].chan[channel].current_address |= (value << 8);
414 BX_DEBUG((" base = %04x",
415 (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_address));
416 BX_DEBUG((" curr = %04x",
417 (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].current_address));
418 }
419 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
420 return;
421 break;
423 case 0x01:
424 case 0x03:
425 case 0x05:
426 case 0x07:
427 case 0xc2:
428 case 0xc6:
429 case 0xca:
430 case 0xce:
431 ma_sl = (address >= 0xc2);
432 channel = (address >> (1 + ma_sl)) & 0x03;
433 BX_DEBUG((" DMA-%d base and current count, channel %d", ma_sl+1, channel));
434 if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */
435 BX_DMA_THIS s[ma_sl].chan[channel].base_count = value;
436 BX_DMA_THIS s[ma_sl].chan[channel].current_count = value;
437 }
438 else { /* 2nd byte */
439 BX_DMA_THIS s[ma_sl].chan[channel].base_count |= (value << 8);
440 BX_DMA_THIS s[ma_sl].chan[channel].current_count |= (value << 8);
441 BX_DEBUG((" base = %04x",
442 (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_count));
443 BX_DEBUG((" curr = %04x",
444 (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].current_count));
445 }
446 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
447 return;
448 break;
450 case 0x08: /* DMA-1: command register */
451 case 0xd0: /* DMA-2: command register */
452 ma_sl = (address == 0xd0);
453 if (value != 0x00)
454 BX_ERROR(("write to command register: value(%02xh) not 0x00",
455 (unsigned) value));
456 BX_DMA_THIS s[ma_sl].command_reg = value;
457 return;
458 break;
460 case 0x09: // DMA-1: request register
461 case 0xd2: // DMA-2: request register
462 ma_sl = (address == 0xd2);
463 channel = value & 0x03;
464 BX_ERROR(("DMA-%d: write to request register (%02x)", ma_sl+1, (unsigned) value));
465 // note: write to 0x0d clears this register
466 if (value & 0x04) {
467 // set request bit
468 BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4));
469 BX_DEBUG(("DMA-%d: set request bit for channel %u", ma_sl+1, (unsigned) channel));
470 }
471 else {
472 // clear request bit
473 BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4));
474 BX_DEBUG(("DMA-%d: cleared request bit for channel %u", ma_sl+1, (unsigned) channel));
475 }
476 control_HRQ(ma_sl);
477 return;
478 break;
480 case 0x0a:
481 case 0xd4:
482 ma_sl = (address == 0xd4);
483 set_mask_bit = value & 0x04;
484 channel = value & 0x03;
485 BX_DMA_THIS s[ma_sl].mask[channel] = (set_mask_bit > 0);
486 BX_DEBUG(("DMA-%d: set_mask_bit=%u, channel=%u, mask now=%02xh", ma_sl+1,
487 (unsigned) set_mask_bit, (unsigned) channel, (unsigned) BX_DMA_THIS s[ma_sl].mask[channel]));
488 control_HRQ(ma_sl);
489 return;
490 break;
492 case 0x0b: /* DMA-1 mode register */
493 case 0xd6: /* DMA-2 mode register */
494 ma_sl = (address == 0xd6);
495 channel = value & 0x03;
496 BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type = (value >> 6) & 0x03;
497 BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement = (value >> 5) & 0x01;
498 BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable = (value >> 4) & 0x01;
499 BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type = (value >> 2) & 0x03;
500 BX_DEBUG(("DMA-%d: mode register[%u] = %02x", ma_sl+1,
501 (unsigned) channel, (unsigned) value));
502 return;
503 break;
505 case 0x0c: /* DMA-1 clear byte flip/flop */
506 case 0xd8: /* DMA-2 clear byte flip/flop */
507 ma_sl = (address == 0xd8);
508 BX_DEBUG(("DMA-%d: clear flip/flop", ma_sl+1));
509 BX_DMA_THIS s[ma_sl].flip_flop = 0;
510 return;
511 break;
513 case 0x0d: // DMA-1: master clear
514 case 0xda: // DMA-2: master clear
515 ma_sl = (address == 0xda);
516 BX_DEBUG(("DMA-%d: master clear", ma_sl+1));
517 // writing any value to this port resets DMA controller 1 / 2
518 // same action as a hardware reset
519 // mask register is set (chan 0..3 disabled)
520 // command, status, request, temporary, and byte flip-flop are all cleared
521 reset_controller(ma_sl);
522 return;
523 break;
525 case 0x0e: // DMA-1: clear mask register
526 case 0xdc: // DMA-2: clear mask register
527 ma_sl = (address == 0xdc);
528 BX_DEBUG(("DMA-%d: clear mask register", ma_sl+1));
529 BX_DMA_THIS s[ma_sl].mask[0] = 0;
530 BX_DMA_THIS s[ma_sl].mask[1] = 0;
531 BX_DMA_THIS s[ma_sl].mask[2] = 0;
532 BX_DMA_THIS s[ma_sl].mask[3] = 0;
533 control_HRQ(ma_sl);
534 return;
535 break;
537 case 0x0f: // DMA-1: write all mask bits
538 case 0xde: // DMA-2: write all mask bits
539 ma_sl = (address == 0xde);
540 BX_DEBUG(("DMA-%d: write all mask bits", ma_sl+1));
541 BX_DMA_THIS s[ma_sl].mask[0] = value & 0x01; value >>= 1;
542 BX_DMA_THIS s[ma_sl].mask[1] = value & 0x01; value >>= 1;
543 BX_DMA_THIS s[ma_sl].mask[2] = value & 0x01; value >>= 1;
544 BX_DMA_THIS s[ma_sl].mask[3] = value & 0x01;
545 control_HRQ(ma_sl);
546 return;
547 break;
549 case 0x81: /* DMA-1 page register, channel 2 */
550 case 0x82: /* DMA-1 page register, channel 3 */
551 case 0x83: /* DMA-1 page register, channel 1 */
552 case 0x87: /* DMA-1 page register, channel 0 */
553 /* address bits A16-A23 for DMA channel */
554 channel = channelindex[address - 0x81];
555 BX_DMA_THIS s[0].chan[channel].page_reg = value;
556 BX_DEBUG(("DMA-1: page register %d = %02x", channel, (unsigned) value));
557 return;
558 break;
560 case 0x89: /* DMA-2 page register, channel 2 */
561 case 0x8a: /* DMA-2 page register, channel 3 */
562 case 0x8b: /* DMA-2 page register, channel 1 */
563 case 0x8f: /* DMA-2 page register, channel 0 */
564 /* address bits A16-A23 for DMA channel */
565 channel = channelindex[address - 0x89];
566 BX_DMA_THIS s[1].chan[channel].page_reg = value;
567 BX_DEBUG(("DMA-2: page register %d = %02x", channel + 4, (unsigned) value));
568 return;
569 break;
571 case 0x0084:
572 case 0x0085:
573 case 0x0086:
574 case 0x0088:
575 case 0x008c:
576 case 0x008d:
577 case 0x008e:
578 BX_DEBUG(("write: extra page register 0x%04x unsupported", (unsigned) address));
579 return;
580 break;
582 default:
583 BX_ERROR(("write ignored: %04xh = %02xh",
584 (unsigned) address, (unsigned) value));
585 }
586 }
588 void
589 bx_dma_c::set_DRQ(unsigned channel, bx_bool val)
590 {
591 Bit32u dma_base, dma_roof;
592 bx_bool ma_sl;
594 if (channel > 7) {
595 BX_PANIC(("set_DRQ() channel > 7"));
596 return;
597 }
598 ma_sl = (channel > 3);
599 BX_DMA_THIS s[ma_sl].DRQ[channel & 0x03] = val;
600 if (!BX_DMA_THIS s[ma_sl].chan[channel & 0x03].used) {
601 BX_PANIC(("set_DRQ(): channel %d not connected to device", channel));
602 return;
603 }
604 channel &= 0x03;
605 if (!val) {
606 //BX_DEBUG(("bx_dma_c::DRQ(): val == 0"));
607 // clear bit in status reg
608 BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4));
610 control_HRQ(ma_sl);
611 return;
612 }
614 #if 0
615 BX_INFO(("mask[%d]: %02x", channel, (unsigned) BX_DMA_THIS s[0].mask[channel]));
616 BX_INFO(("flip_flop: %u", (unsigned) BX_DMA_THIS s[0].flip_flop));
617 BX_INFO(("status_reg: %02x", (unsigned) BX_DMA_THIS s[0].status_reg));
618 BX_INFO(("mode_type: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.mode_type));
619 BX_INFO(("address_decrement: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.address_decrement));
620 BX_INFO(("autoinit_enable: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.autoinit_enable));
621 BX_INFO(("transfer_type: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.transfer_type));
622 BX_INFO(("base_address: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].base_address));
623 BX_INFO(("current_address: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].current_address));
624 BX_INFO(("base_count: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].base_count));
625 BX_INFO(("current_count: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].current_count));
626 BX_INFO(("page_reg: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].page_reg));
627 #endif
629 BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4));
631 if ( (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_SINGLE) &&
632 (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_DEMAND) &&
633 (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_CASCADE) )
634 BX_PANIC(("set_DRQ: mode_type(%02x) not handled",
635 (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type));
637 dma_base = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) |
638 (BX_DMA_THIS s[ma_sl].chan[channel].base_address << ma_sl);
639 if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement==0) {
640 dma_roof = dma_base + (BX_DMA_THIS s[ma_sl].chan[channel].base_count << ma_sl);
641 } else {
642 dma_roof = dma_base - (BX_DMA_THIS s[ma_sl].chan[channel].base_count << ma_sl);
643 }
644 if ( (dma_base & (0x7fff0000 << ma_sl)) != (dma_roof & (0x7fff0000 << ma_sl)) ) {
645 BX_INFO(("dma_base = %08x", (unsigned) dma_base));
646 BX_INFO(("dma_base_count = %08x", (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_count));
647 BX_INFO(("dma_roof = %08x", (unsigned) dma_roof));
648 BX_PANIC(("request outside %dk boundary", 64 << ma_sl));
649 }
651 control_HRQ(ma_sl);
652 }
654 void
655 bx_dma_c::control_HRQ(bx_bool ma_sl)
656 {
657 unsigned channel;
659 // deassert HRQ if no DRQ is pending
660 if ((BX_DMA_THIS s[ma_sl].status_reg & 0xf0) == 0) {
661 if (ma_sl) {
662 bx_pc_system.set_HRQ(0);
663 } else {
664 BX_DMA_THIS set_DRQ(4, 0);
665 }
666 return;
667 }
668 // find highest priority channel
669 for (channel=0; channel<4; channel++) {
670 if ( (BX_DMA_THIS s[ma_sl].status_reg & (1 << (channel+4))) &&
671 (BX_DMA_THIS s[ma_sl].mask[channel]==0) ) {
672 if (ma_sl) {
673 // assert Hold ReQuest line to CPU
674 bx_pc_system.set_HRQ(1);
675 } else {
676 // send DRQ to cascade channel of the master
677 BX_DMA_THIS set_DRQ(4, 1);
678 }
679 break;
680 }
681 }
682 }
684 void
685 bx_dma_c::raise_HLDA(void)
686 {
687 unsigned channel;
688 Bit32u phy_addr;
689 bx_bool count_expired = 0;
690 bx_bool ma_sl = 0;
692 BX_DMA_THIS HLDA = 1;
693 // find highest priority channel
694 for (channel=0; channel<4; channel++) {
695 if ( (BX_DMA_THIS s[1].status_reg & (1 << (channel+4))) &&
696 (BX_DMA_THIS s[1].mask[channel]==0) ) {
697 ma_sl = 1;
698 break;
699 }
700 }
701 if (channel == 0) { // master cascade channel
702 BX_DMA_THIS s[1].DACK[0] = 1;
703 for (channel=0; channel<4; channel++) {
704 if ( (BX_DMA_THIS s[0].status_reg & (1 << (channel+4))) &&
705 (BX_DMA_THIS s[0].mask[channel]==0) ) {
706 ma_sl = 0;
707 break;
708 }
709 }
710 }
711 if (channel >= 4) {
712 // wait till they're unmasked
713 return;
714 }
716 //BX_DEBUG(("hlda: OK in response to DRQ(%u)", (unsigned) channel));
717 phy_addr = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) |
718 (BX_DMA_THIS s[ma_sl].chan[channel].current_address << ma_sl);
720 BX_DMA_THIS s[ma_sl].DACK[channel] = 1;
721 // check for expiration of count, so we can signal TC and DACK(n)
722 // at the same time.
723 if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement==0)
724 BX_DMA_THIS s[ma_sl].chan[channel].current_address++;
725 else
726 BX_DMA_THIS s[ma_sl].chan[channel].current_address--;
727 BX_DMA_THIS s[ma_sl].chan[channel].current_count--;
728 if (BX_DMA_THIS s[ma_sl].chan[channel].current_count == 0xffff) {
729 // count expired, done with transfer
730 // assert TC, deassert HRQ & DACK(n) lines
731 BX_DMA_THIS s[ma_sl].status_reg |= (1 << channel); // hold TC in status reg
732 BX_DMA_THIS TC = 1;
733 count_expired = 1;
734 if (BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable == 0) {
735 // set mask bit if not in autoinit mode
736 BX_DMA_THIS s[ma_sl].mask[channel] = 1;
737 }
738 else {
739 // count expired, but in autoinit mode
740 // reload count and base address
741 BX_DMA_THIS s[ma_sl].chan[channel].current_address =
742 BX_DMA_THIS s[ma_sl].chan[channel].base_address;
743 BX_DMA_THIS s[ma_sl].chan[channel].current_count =
744 BX_DMA_THIS s[ma_sl].chan[channel].base_count;
745 }
746 }
748 Bit8u data_byte;
749 Bit16u data_word;
751 if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 1) { // write
752 // DMA controlled xfer of byte from I/O to Memory
754 if (!ma_sl) {
755 if (BX_DMA_THIS h[channel].dmaWrite8)
756 BX_DMA_THIS h[channel].dmaWrite8(&data_byte);
757 else
758 BX_PANIC(("no dmaWrite handler for channel %u.", channel));
760 BX_MEM_WRITE_PHYSICAL(phy_addr, 1, &data_byte);
762 BX_DBG_DMA_REPORT(phy_addr, 1, BX_WRITE, data_byte);
763 }
764 else {
765 if (BX_DMA_THIS h[channel].dmaWrite16)
766 BX_DMA_THIS h[channel].dmaWrite16(&data_word);
767 else
768 BX_PANIC(("no dmaWrite handler for channel %u.", channel));
770 BX_MEM_WRITE_PHYSICAL(phy_addr, 2, &data_word);
772 BX_DBG_DMA_REPORT(phy_addr, 2, BX_WRITE, data_word);
773 }
774 }
775 else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 2) { // read
776 // DMA controlled xfer of byte from Memory to I/O
778 if (!ma_sl) {
779 BX_MEM_READ_PHYSICAL(phy_addr, 1, &data_byte);
781 if (BX_DMA_THIS h[channel].dmaRead8)
782 BX_DMA_THIS h[channel].dmaRead8(&data_byte);
784 BX_DBG_DMA_REPORT(phy_addr, 1, BX_READ, data_byte);
785 }
786 else {
787 BX_MEM_READ_PHYSICAL(phy_addr, 2, &data_word);
789 if (BX_DMA_THIS h[channel].dmaRead16)
790 BX_DMA_THIS h[channel].dmaRead16(&data_word);
792 BX_DBG_DMA_REPORT(phy_addr, 2, BX_READ, data_word);
793 }
794 }
795 else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 0) {
796 // verify
798 if (!ma_sl) {
799 if (BX_DMA_THIS h[channel].dmaWrite8)
800 BX_DMA_THIS h[channel].dmaWrite8(&data_byte);
801 else
802 BX_PANIC(("no dmaWrite handler for channel %u.", channel));
803 }
804 else {
805 if (BX_DMA_THIS h[channel].dmaWrite16)
806 BX_DMA_THIS h[channel].dmaWrite16(&data_word);
807 else
808 BX_PANIC(("no dmaWrite handler for channel %u.", channel));
809 }
810 }
811 else {
812 BX_PANIC(("hlda: transfer_type 3 is undefined"));
813 }
815 if (count_expired) {
816 BX_DMA_THIS TC = 0; // clear TC, adapter card already notified
817 BX_DMA_THIS HLDA = 0;
818 bx_pc_system.set_HRQ(0); // clear HRQ to CPU
819 BX_DMA_THIS s[ma_sl].DACK[channel] = 0; // clear DACK to adapter card
820 if (!ma_sl) {
821 BX_DMA_THIS set_DRQ(4, 0); // clear DRQ to cascade
822 BX_DMA_THIS s[1].DACK[0] = 0; // clear DACK to cascade
823 }
824 }
825 }