debuggers.hg

view tools/ioemu/iodev/dma.cc @ 3491:2c56c6b39a48

bitkeeper revision 1.1159.212.18 (41ebe1caQQ_SlJestrvsT95t1oER-Q)

Merge arcadians.cl.cam.ac.uk:/auto/groups/xeno/BK/xen-unstable.bk
into arcadians.cl.cam.ac.uk:/auto/groups/xeno/users/cl349/BK/xen-unstable.bk
author cl349@arcadians.cl.cam.ac.uk
date Mon Jan 17 16:03:22 2005 +0000 (2005-01-17)
parents 9ad7af5b3f9b
children f89816eaeaad 26a00896163a d3f0465c034e bbe8541361dd
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 }
187 void
188 bx_dma_c::reset(unsigned type)
189 {
190 reset_controller(0);
191 reset_controller(1);
192 }
194 void
195 bx_dma_c::reset_controller(unsigned num)
196 {
197 BX_DMA_THIS s[num].mask[0] = 1;
198 BX_DMA_THIS s[num].mask[1] = 1;
199 BX_DMA_THIS s[num].mask[2] = 1;
200 BX_DMA_THIS s[num].mask[3] = 1;
201 BX_DMA_THIS s[num].command_reg = 0;
202 BX_DMA_THIS s[num].status_reg = 0;
203 BX_DMA_THIS s[num].request_reg = 0;
204 BX_DMA_THIS s[num].temporary_reg = 0;
205 BX_DMA_THIS s[num].flip_flop = 0;
206 }
208 // index to find channel from register number (only [0],[1],[2],[6] used)
209 Bit8u channelindex[7] = {2, 3, 1, 0, 0, 0, 0};
212 // static IO port read callback handler
213 // redirects to non-static class handler to avoid virtual functions
215 Bit32u
216 bx_dma_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
217 {
218 #if !BX_USE_DMA_SMF
219 bx_dma_c *class_ptr = (bx_dma_c *) this_ptr;
221 return( class_ptr->read(address, io_len) );
222 }
224 /* 8237 DMA controller */
225 Bit32u BX_CPP_AttrRegparmN(2)
226 bx_dma_c::read( Bit32u address, unsigned io_len)
227 {
228 #else
229 UNUSED(this_ptr);
230 #endif // !BX_USE_DMA_SMF
232 Bit8u retval;
233 Bit8u channel;
234 bx_bool ma_sl;
236 BX_DEBUG(("read addr=%04x", (unsigned) address));
238 #if BX_DMA_FLOPPY_IO < 1
239 /* if we're not supporting DMA/floppy IO just return a bogus value */
240 return(0xff);
241 #endif
243 switch (address) {
244 case 0x00: /* DMA-1 current address, channel 0 */
245 case 0x02: /* DMA-1 current address, channel 1 */
246 case 0x04: /* DMA-1 current address, channel 2 */
247 case 0x06: /* DMA-1 current address, channel 3 */
248 case 0xc0: /* DMA-2 current address, channel 0 */
249 case 0xc4: /* DMA-2 current address, channel 1 */
250 case 0xc8: /* DMA-2 current address, channel 2 */
251 case 0xcc: /* DMA-2 current address, channel 3 */
252 ma_sl = (address >= 0xc0);
253 channel = (address >> (1 + ma_sl)) & 0x03;
254 if (BX_DMA_THIS s[ma_sl].flip_flop==0) {
255 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
256 return(BX_DMA_THIS s[ma_sl].chan[channel].current_address & 0xff);
257 }
258 else {
259 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
260 return(BX_DMA_THIS s[ma_sl].chan[channel].current_address >> 8);
261 }
263 case 0x01: /* DMA-1 current count, channel 0 */
264 case 0x03: /* DMA-1 current count, channel 1 */
265 case 0x05: /* DMA-1 current count, channel 2 */
266 case 0x07: /* DMA-1 current count, channel 3 */
267 case 0xc2: /* DMA-2 current count, channel 0 */
268 case 0xc6: /* DMA-2 current count, channel 1 */
269 case 0xca: /* DMA-2 current count, channel 2 */
270 case 0xce: /* DMA-2 current count, channel 3 */
271 ma_sl = (address >= 0xc2);
272 channel = (address >> (1 + ma_sl)) & 0x03;
273 if (BX_DMA_THIS s[ma_sl].flip_flop==0) {
274 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
275 return(BX_DMA_THIS s[ma_sl].chan[channel].current_count & 0xff);
276 }
277 else {
278 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
279 return(BX_DMA_THIS s[ma_sl].chan[channel].current_count >> 8);
280 }
282 case 0x08: // DMA-1 Status Register
283 case 0xd0: // DMA-2 Status Register
284 // bit 7: 1 = channel 3 request
285 // bit 6: 1 = channel 2 request
286 // bit 5: 1 = channel 1 request
287 // bit 4: 1 = channel 0 request
288 // bit 3: 1 = channel 3 has reached terminal count
289 // bit 2: 1 = channel 2 has reached terminal count
290 // bit 1: 1 = channel 1 has reached terminal count
291 // bit 0: 1 = channel 0 has reached terminal count
292 // reading this register clears lower 4 bits (hold flags)
293 ma_sl = (address == 0xd0);
294 retval = BX_DMA_THIS s[ma_sl].status_reg;
295 BX_DMA_THIS s[ma_sl].status_reg &= 0xf0;
296 return(retval);
297 break;
298 case 0x0d: // DMA-1: temporary register
299 case 0xda: // DMA-2: temporary register
300 ma_sl = (address == 0xda);
301 BX_ERROR(("DMA-%d: read of temporary register", ma_sl+1));
302 // Note: write to 0x0D clears temporary register
303 return(0);
304 break;
306 case 0x0081: // DMA-1 page register, channel 2
307 case 0x0082: // DMA-1 page register, channel 3
308 case 0x0083: // DMA-1 page register, channel 1
309 case 0x0087: // DMA-1 page register, channel 0
310 channel = channelindex[address - 0x81];
311 return( BX_DMA_THIS s[0].chan[channel].page_reg );
313 case 0x0089: // DMA-2 page register, channel 2
314 case 0x008a: // DMA-2 page register, channel 3
315 case 0x008b: // DMA-2 page register, channel 1
316 case 0x008f: // DMA-2 page register, channel 0
317 channel = channelindex[address - 0x89];
318 return( BX_DMA_THIS s[1].chan[channel].page_reg );
320 case 0x0084:
321 case 0x0085:
322 case 0x0086:
323 case 0x0088:
324 case 0x008c:
325 case 0x008d:
326 case 0x008e:
327 BX_DEBUG(("read: extra page register 0x%04x unsupported", (unsigned) address));
328 return(0);
330 default:
331 BX_ERROR(("read: unsupported address=%04x", (unsigned) address));
332 return(0);
333 }
334 }
337 // static IO port write callback handler
338 // redirects to non-static class handler to avoid virtual functions
340 void
341 bx_dma_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
342 {
343 #if !BX_USE_DMA_SMF
344 bx_dma_c *class_ptr = (bx_dma_c *) this_ptr;
346 class_ptr->write(address, value, io_len);
347 }
350 /* 8237 DMA controller */
351 void BX_CPP_AttrRegparmN(3)
352 bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len)
353 {
354 #else
355 UNUSED(this_ptr);
356 #endif // !BX_USE_DMA_SMF
357 Bit8u set_mask_bit;
358 Bit8u channel;
359 bx_bool ma_sl;
361 if (io_len > 1) {
362 if ( (io_len == 2) && (address == 0x0b) ) {
363 #if BX_USE_DMA_SMF
364 BX_DMA_THIS write_handler(NULL, address, value & 0xff, 1);
365 BX_DMA_THIS write_handler(NULL, address+1, value >> 8, 1);
366 #else
367 BX_DMA_THIS write(address, value & 0xff, 1);
368 BX_DMA_THIS write(address+1, value >> 8, 1);
369 #endif
370 return;
371 }
373 BX_ERROR(("io write to address %08x, len=%u",
374 (unsigned) address, (unsigned) io_len));
375 return;
376 }
378 BX_DEBUG(("write: address=%04x value=%02x",
379 (unsigned) address, (unsigned) value));
381 #if BX_DMA_FLOPPY_IO < 1
382 /* if we're not supporting DMA/floppy IO just return */
383 return;
384 #endif
386 switch (address) {
387 case 0x00:
388 case 0x02:
389 case 0x04:
390 case 0x06:
391 case 0xc0:
392 case 0xc4:
393 case 0xc8:
394 case 0xcc:
395 ma_sl = (address >= 0xc0);
396 channel = (address >> (1 + ma_sl)) & 0x03;
397 BX_DEBUG((" DMA-%d base and current address, channel %d", ma_sl+1, channel));
398 if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */
399 BX_DMA_THIS s[ma_sl].chan[channel].base_address = value;
400 BX_DMA_THIS s[ma_sl].chan[channel].current_address = value;
401 }
402 else { /* 2nd byte */
403 BX_DMA_THIS s[ma_sl].chan[channel].base_address |= (value << 8);
404 BX_DMA_THIS s[ma_sl].chan[channel].current_address |= (value << 8);
405 BX_DEBUG((" base = %04x",
406 (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_address));
407 BX_DEBUG((" curr = %04x",
408 (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].current_address));
409 }
410 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
411 return;
412 break;
414 case 0x01:
415 case 0x03:
416 case 0x05:
417 case 0x07:
418 case 0xc2:
419 case 0xc6:
420 case 0xca:
421 case 0xce:
422 ma_sl = (address >= 0xc2);
423 channel = (address >> (1 + ma_sl)) & 0x03;
424 BX_DEBUG((" DMA-%d base and current count, channel %d", ma_sl+1, channel));
425 if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */
426 BX_DMA_THIS s[ma_sl].chan[channel].base_count = value;
427 BX_DMA_THIS s[ma_sl].chan[channel].current_count = value;
428 }
429 else { /* 2nd byte */
430 BX_DMA_THIS s[ma_sl].chan[channel].base_count |= (value << 8);
431 BX_DMA_THIS s[ma_sl].chan[channel].current_count |= (value << 8);
432 BX_DEBUG((" base = %04x",
433 (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_count));
434 BX_DEBUG((" curr = %04x",
435 (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].current_count));
436 }
437 BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
438 return;
439 break;
441 case 0x08: /* DMA-1: command register */
442 case 0xd0: /* DMA-2: command register */
443 ma_sl = (address == 0xd0);
444 if (value != 0x00)
445 BX_ERROR(("write to command register: value(%02xh) not 0x00",
446 (unsigned) value));
447 BX_DMA_THIS s[ma_sl].command_reg = value;
448 return;
449 break;
451 case 0x09: // DMA-1: request register
452 case 0xd2: // DMA-2: request register
453 ma_sl = (address == 0xd2);
454 channel = value & 0x03;
455 BX_ERROR(("DMA-%d: write to request register (%02x)", ma_sl+1, (unsigned) value));
456 // note: write to 0x0d clears this register
457 if (value & 0x04) {
458 // set request bit
459 BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4));
460 BX_DEBUG(("DMA-%d: set request bit for channel %u", ma_sl+1, (unsigned) channel));
461 }
462 else {
463 // clear request bit
464 BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4));
465 BX_DEBUG(("DMA-%d: cleared request bit for channel %u", ma_sl+1, (unsigned) channel));
466 }
467 control_HRQ(ma_sl);
468 return;
469 break;
471 case 0x0a:
472 case 0xd4:
473 ma_sl = (address == 0xd4);
474 set_mask_bit = value & 0x04;
475 channel = value & 0x03;
476 BX_DMA_THIS s[ma_sl].mask[channel] = (set_mask_bit > 0);
477 BX_DEBUG(("DMA-%d: set_mask_bit=%u, channel=%u, mask now=%02xh", ma_sl+1,
478 (unsigned) set_mask_bit, (unsigned) channel, (unsigned) BX_DMA_THIS s[ma_sl].mask[channel]));
479 control_HRQ(ma_sl);
480 return;
481 break;
483 case 0x0b: /* DMA-1 mode register */
484 case 0xd6: /* DMA-2 mode register */
485 ma_sl = (address == 0xd6);
486 channel = value & 0x03;
487 BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type = (value >> 6) & 0x03;
488 BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement = (value >> 5) & 0x01;
489 BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable = (value >> 4) & 0x01;
490 BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type = (value >> 2) & 0x03;
491 BX_DEBUG(("DMA-%d: mode register[%u] = %02x", ma_sl+1,
492 (unsigned) channel, (unsigned) value));
493 return;
494 break;
496 case 0x0c: /* DMA-1 clear byte flip/flop */
497 case 0xd8: /* DMA-2 clear byte flip/flop */
498 ma_sl = (address == 0xd8);
499 BX_DEBUG(("DMA-%d: clear flip/flop", ma_sl+1));
500 BX_DMA_THIS s[ma_sl].flip_flop = 0;
501 return;
502 break;
504 case 0x0d: // DMA-1: master clear
505 case 0xda: // DMA-2: master clear
506 ma_sl = (address == 0xda);
507 BX_DEBUG(("DMA-%d: master clear", ma_sl+1));
508 // writing any value to this port resets DMA controller 1 / 2
509 // same action as a hardware reset
510 // mask register is set (chan 0..3 disabled)
511 // command, status, request, temporary, and byte flip-flop are all cleared
512 reset_controller(ma_sl);
513 return;
514 break;
516 case 0x0e: // DMA-1: clear mask register
517 case 0xdc: // DMA-2: clear mask register
518 ma_sl = (address == 0xdc);
519 BX_DEBUG(("DMA-%d: clear mask register", ma_sl+1));
520 BX_DMA_THIS s[ma_sl].mask[0] = 0;
521 BX_DMA_THIS s[ma_sl].mask[1] = 0;
522 BX_DMA_THIS s[ma_sl].mask[2] = 0;
523 BX_DMA_THIS s[ma_sl].mask[3] = 0;
524 control_HRQ(ma_sl);
525 return;
526 break;
528 case 0x0f: // DMA-1: write all mask bits
529 case 0xde: // DMA-2: write all mask bits
530 ma_sl = (address == 0xde);
531 BX_DEBUG(("DMA-%d: write all mask bits", ma_sl+1));
532 BX_DMA_THIS s[ma_sl].mask[0] = value & 0x01; value >>= 1;
533 BX_DMA_THIS s[ma_sl].mask[1] = value & 0x01; value >>= 1;
534 BX_DMA_THIS s[ma_sl].mask[2] = value & 0x01; value >>= 1;
535 BX_DMA_THIS s[ma_sl].mask[3] = value & 0x01;
536 control_HRQ(ma_sl);
537 return;
538 break;
540 case 0x81: /* DMA-1 page register, channel 2 */
541 case 0x82: /* DMA-1 page register, channel 3 */
542 case 0x83: /* DMA-1 page register, channel 1 */
543 case 0x87: /* DMA-1 page register, channel 0 */
544 /* address bits A16-A23 for DMA channel */
545 channel = channelindex[address - 0x81];
546 BX_DMA_THIS s[0].chan[channel].page_reg = value;
547 BX_DEBUG(("DMA-1: page register %d = %02x", channel, (unsigned) value));
548 return;
549 break;
551 case 0x89: /* DMA-2 page register, channel 2 */
552 case 0x8a: /* DMA-2 page register, channel 3 */
553 case 0x8b: /* DMA-2 page register, channel 1 */
554 case 0x8f: /* DMA-2 page register, channel 0 */
555 /* address bits A16-A23 for DMA channel */
556 channel = channelindex[address - 0x89];
557 BX_DMA_THIS s[1].chan[channel].page_reg = value;
558 BX_DEBUG(("DMA-2: page register %d = %02x", channel + 4, (unsigned) value));
559 return;
560 break;
562 case 0x0084:
563 case 0x0085:
564 case 0x0086:
565 case 0x0088:
566 case 0x008c:
567 case 0x008d:
568 case 0x008e:
569 BX_DEBUG(("write: extra page register 0x%04x unsupported", (unsigned) address));
570 return;
571 break;
573 default:
574 BX_ERROR(("write ignored: %04xh = %02xh",
575 (unsigned) address, (unsigned) value));
576 }
577 }
579 void
580 bx_dma_c::set_DRQ(unsigned channel, bx_bool val)
581 {
582 Bit32u dma_base, dma_roof;
583 bx_bool ma_sl;
585 if (channel > 7) {
586 BX_PANIC(("set_DRQ() channel > 7"));
587 return;
588 }
589 ma_sl = (channel > 3);
590 BX_DMA_THIS s[ma_sl].DRQ[channel & 0x03] = val;
591 if (!BX_DMA_THIS s[ma_sl].chan[channel & 0x03].used) {
592 BX_PANIC(("set_DRQ(): channel %d not connected to device", channel));
593 return;
594 }
595 channel &= 0x03;
596 if (!val) {
597 //BX_DEBUG(("bx_dma_c::DRQ(): val == 0"));
598 // clear bit in status reg
599 BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4));
601 control_HRQ(ma_sl);
602 return;
603 }
605 #if 0
606 BX_INFO(("mask[%d]: %02x", channel, (unsigned) BX_DMA_THIS s[0].mask[channel]));
607 BX_INFO(("flip_flop: %u", (unsigned) BX_DMA_THIS s[0].flip_flop));
608 BX_INFO(("status_reg: %02x", (unsigned) BX_DMA_THIS s[0].status_reg));
609 BX_INFO(("mode_type: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.mode_type));
610 BX_INFO(("address_decrement: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.address_decrement));
611 BX_INFO(("autoinit_enable: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.autoinit_enable));
612 BX_INFO(("transfer_type: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.transfer_type));
613 BX_INFO(("base_address: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].base_address));
614 BX_INFO(("current_address: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].current_address));
615 BX_INFO(("base_count: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].base_count));
616 BX_INFO(("current_count: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].current_count));
617 BX_INFO(("page_reg: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].page_reg));
618 #endif
620 BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4));
622 if ( (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_SINGLE) &&
623 (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_DEMAND) &&
624 (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_CASCADE) )
625 BX_PANIC(("set_DRQ: mode_type(%02x) not handled",
626 (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type));
628 dma_base = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) |
629 (BX_DMA_THIS s[ma_sl].chan[channel].base_address << ma_sl);
630 if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement==0) {
631 dma_roof = dma_base + (BX_DMA_THIS s[ma_sl].chan[channel].base_count << ma_sl);
632 } else {
633 dma_roof = dma_base - (BX_DMA_THIS s[ma_sl].chan[channel].base_count << ma_sl);
634 }
635 if ( (dma_base & (0x7fff0000 << ma_sl)) != (dma_roof & (0x7fff0000 << ma_sl)) ) {
636 BX_INFO(("dma_base = %08x", (unsigned) dma_base));
637 BX_INFO(("dma_base_count = %08x", (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_count));
638 BX_INFO(("dma_roof = %08x", (unsigned) dma_roof));
639 BX_PANIC(("request outside %dk boundary", 64 << ma_sl));
640 }
642 control_HRQ(ma_sl);
643 }
645 void
646 bx_dma_c::control_HRQ(bx_bool ma_sl)
647 {
648 unsigned channel;
650 // deassert HRQ if no DRQ is pending
651 if ((BX_DMA_THIS s[ma_sl].status_reg & 0xf0) == 0) {
652 if (ma_sl) {
653 bx_pc_system.set_HRQ(0);
654 } else {
655 BX_DMA_THIS set_DRQ(4, 0);
656 }
657 return;
658 }
659 // find highest priority channel
660 for (channel=0; channel<4; channel++) {
661 if ( (BX_DMA_THIS s[ma_sl].status_reg & (1 << (channel+4))) &&
662 (BX_DMA_THIS s[ma_sl].mask[channel]==0) ) {
663 if (ma_sl) {
664 // assert Hold ReQuest line to CPU
665 bx_pc_system.set_HRQ(1);
666 } else {
667 // send DRQ to cascade channel of the master
668 BX_DMA_THIS set_DRQ(4, 1);
669 }
670 break;
671 }
672 }
673 }
675 void
676 bx_dma_c::raise_HLDA(void)
677 {
678 unsigned channel;
679 Bit32u phy_addr;
680 bx_bool count_expired = 0;
681 bx_bool ma_sl = 0;
683 BX_DMA_THIS HLDA = 1;
684 // find highest priority channel
685 for (channel=0; channel<4; channel++) {
686 if ( (BX_DMA_THIS s[1].status_reg & (1 << (channel+4))) &&
687 (BX_DMA_THIS s[1].mask[channel]==0) ) {
688 ma_sl = 1;
689 break;
690 }
691 }
692 if (channel == 0) { // master cascade channel
693 BX_DMA_THIS s[1].DACK[0] = 1;
694 for (channel=0; channel<4; channel++) {
695 if ( (BX_DMA_THIS s[0].status_reg & (1 << (channel+4))) &&
696 (BX_DMA_THIS s[0].mask[channel]==0) ) {
697 ma_sl = 0;
698 break;
699 }
700 }
701 }
702 if (channel >= 4) {
703 // wait till they're unmasked
704 return;
705 }
707 //BX_DEBUG(("hlda: OK in response to DRQ(%u)", (unsigned) channel));
708 phy_addr = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) |
709 (BX_DMA_THIS s[ma_sl].chan[channel].current_address << ma_sl);
711 BX_DMA_THIS s[ma_sl].DACK[channel] = 1;
712 // check for expiration of count, so we can signal TC and DACK(n)
713 // at the same time.
714 if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement==0)
715 BX_DMA_THIS s[ma_sl].chan[channel].current_address++;
716 else
717 BX_DMA_THIS s[ma_sl].chan[channel].current_address--;
718 BX_DMA_THIS s[ma_sl].chan[channel].current_count--;
719 if (BX_DMA_THIS s[ma_sl].chan[channel].current_count == 0xffff) {
720 // count expired, done with transfer
721 // assert TC, deassert HRQ & DACK(n) lines
722 BX_DMA_THIS s[ma_sl].status_reg |= (1 << channel); // hold TC in status reg
723 BX_DMA_THIS TC = 1;
724 count_expired = 1;
725 if (BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable == 0) {
726 // set mask bit if not in autoinit mode
727 BX_DMA_THIS s[ma_sl].mask[channel] = 1;
728 }
729 else {
730 // count expired, but in autoinit mode
731 // reload count and base address
732 BX_DMA_THIS s[ma_sl].chan[channel].current_address =
733 BX_DMA_THIS s[ma_sl].chan[channel].base_address;
734 BX_DMA_THIS s[ma_sl].chan[channel].current_count =
735 BX_DMA_THIS s[ma_sl].chan[channel].base_count;
736 }
737 }
739 Bit8u data_byte;
740 Bit16u data_word;
742 if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 1) { // write
743 // DMA controlled xfer of byte from I/O to Memory
745 if (!ma_sl) {
746 if (BX_DMA_THIS h[channel].dmaWrite8)
747 BX_DMA_THIS h[channel].dmaWrite8(&data_byte);
748 else
749 BX_PANIC(("no dmaWrite handler for channel %u.", channel));
751 BX_MEM_WRITE_PHYSICAL(phy_addr, 1, &data_byte);
753 BX_DBG_DMA_REPORT(phy_addr, 1, BX_WRITE, data_byte);
754 }
755 else {
756 if (BX_DMA_THIS h[channel].dmaWrite16)
757 BX_DMA_THIS h[channel].dmaWrite16(&data_word);
758 else
759 BX_PANIC(("no dmaWrite handler for channel %u.", channel));
761 BX_MEM_WRITE_PHYSICAL(phy_addr, 2, &data_word);
763 BX_DBG_DMA_REPORT(phy_addr, 2, BX_WRITE, data_word);
764 }
765 }
766 else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 2) { // read
767 // DMA controlled xfer of byte from Memory to I/O
769 if (!ma_sl) {
770 BX_MEM_READ_PHYSICAL(phy_addr, 1, &data_byte);
772 if (BX_DMA_THIS h[channel].dmaRead8)
773 BX_DMA_THIS h[channel].dmaRead8(&data_byte);
775 BX_DBG_DMA_REPORT(phy_addr, 1, BX_READ, data_byte);
776 }
777 else {
778 BX_MEM_READ_PHYSICAL(phy_addr, 2, &data_word);
780 if (BX_DMA_THIS h[channel].dmaRead16)
781 BX_DMA_THIS h[channel].dmaRead16(&data_word);
783 BX_DBG_DMA_REPORT(phy_addr, 2, BX_READ, data_word);
784 }
785 }
786 else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 0) {
787 // verify
789 if (!ma_sl) {
790 if (BX_DMA_THIS h[channel].dmaWrite8)
791 BX_DMA_THIS h[channel].dmaWrite8(&data_byte);
792 else
793 BX_PANIC(("no dmaWrite handler for channel %u.", channel));
794 }
795 else {
796 if (BX_DMA_THIS h[channel].dmaWrite16)
797 BX_DMA_THIS h[channel].dmaWrite16(&data_word);
798 else
799 BX_PANIC(("no dmaWrite handler for channel %u.", channel));
800 }
801 }
802 else {
803 BX_PANIC(("hlda: transfer_type 3 is undefined"));
804 }
806 if (count_expired) {
807 BX_DMA_THIS TC = 0; // clear TC, adapter card already notified
808 BX_DMA_THIS HLDA = 0;
809 bx_pc_system.set_HRQ(0); // clear HRQ to CPU
810 BX_DMA_THIS s[ma_sl].DACK[channel] = 0; // clear DACK to adapter card
811 if (!ma_sl) {
812 BX_DMA_THIS set_DRQ(4, 0); // clear DRQ to cascade
813 BX_DMA_THIS s[1].DACK[0] = 0; // clear DACK to cascade
814 }
815 }
816 }