debuggers.hg

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