diff --git a/bochs/iodev/devices.cc b/bochs/iodev/devices.cc index 03b0a8677..629345c93 100644 --- a/bochs/iodev/devices.cc +++ b/bochs/iodev/devices.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: devices.cc,v 1.18 2001-10-03 13:10:38 bdenney Exp $ +// $Id: devices.cc,v 1.19 2001-12-18 13:12:45 vruppert Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -105,7 +105,7 @@ bx_devices_c::~bx_devices_c(void) void bx_devices_c::init(BX_MEM_C *newmem) { - BX_DEBUG(("Init $Id: devices.cc,v 1.18 2001-10-03 13:10:38 bdenney Exp $")); + BX_DEBUG(("Init $Id: devices.cc,v 1.19 2001-12-18 13:12:45 vruppert Exp $")); mem = newmem; // Start with all IO port address registered to unmapped handler // MUST be called first @@ -338,7 +338,6 @@ bx_devices_c::raise_hlda(void) void bx_devices_c::dma_read8(unsigned channel, Bit8u *data_byte) { - // UNUSED( channel ); if (channel == 2) floppy->dma_read(data_byte); #if BX_SUPPORT_SB16 @@ -350,13 +349,36 @@ bx_devices_c::dma_read8(unsigned channel, Bit8u *data_byte) void bx_devices_c::dma_write8(unsigned channel, Bit8u *data_byte) { - // UNUSED( channel ); if (channel == 2) floppy->dma_write(data_byte); #if BX_SUPPORT_SB16 else if (channel == (unsigned) sb16->currentdma8) sb16->dma_write8(data_byte); #endif +} + + void +bx_devices_c::dma_read16(unsigned channel, Bit16u *data_word) +{ +#if BX_SUPPORT_SB16 + if (channel == (unsigned) sb16->currentdma16) + sb16->dma_read16(data_word); +#else + UNUSED(channel); + UNUSED(data_word); +#endif +} + + void +bx_devices_c::dma_write16(unsigned channel, Bit16u *data_word) +{ +#if BX_SUPPORT_SB16 + if (channel == (unsigned) sb16->currentdma16) + sb16->dma_write16(data_word); +#else + UNUSED(channel); + UNUSED(data_word); +#endif } void diff --git a/bochs/iodev/dma.cc b/bochs/iodev/dma.cc index e1109a093..69cd768a2 100644 --- a/bochs/iodev/dma.cc +++ b/bochs/iodev/dma.cc @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: dma.cc,v 1.11 2001-10-03 13:10:38 bdenney Exp $ +// $Id: dma.cc,v 1.12 2001-12-18 13:12:45 vruppert Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -59,7 +59,7 @@ bx_dma_c::~bx_dma_c(void) bx_dma_c::init(bx_devices_c *d) { unsigned c; - BX_DEBUG(("Init $Id: dma.cc,v 1.11 2001-10-03 13:10:38 bdenney Exp $")); + BX_DEBUG(("Init $Id: dma.cc,v 1.12 2001-12-18 13:12:45 vruppert Exp $")); BX_DMA_THIS devices = d; @@ -74,16 +74,8 @@ bx_dma_c::init(bx_devices_c *d) i, "DMA controller"); } - // 00081..008D - for (i=0x0081; i<=0x008D; i++) { - BX_DMA_THIS devices->register_io_read_handler(this, read_handler, - i, "DMA controller"); - BX_DMA_THIS devices->register_io_write_handler(this, write_handler, - i, "DMA controller"); - } - - // 0008F..008F - for (i=0x008F; i<=0x008F; i++) { + // 00081..008F + for (i=0x0081; i<=0x008F; i++) { BX_DMA_THIS devices->register_io_read_handler(this, read_handler, i, "DMA controller"); BX_DMA_THIS devices->register_io_write_handler(this, write_handler, @@ -91,7 +83,7 @@ bx_dma_c::init(bx_devices_c *d) } // 000C0..00DE - for (i=0x00C0; i<=0x00DE; i++) { + for (i=0x00C0; i<=0x00DE; i+=2) { BX_DMA_THIS devices->register_io_read_handler(this, read_handler, i, "DMA controller"); BX_DMA_THIS devices->register_io_write_handler(this, write_handler, @@ -99,23 +91,25 @@ bx_dma_c::init(bx_devices_c *d) } - BX_DMA_THIS s.mask[0] = 1; // channel 0 masked - BX_DMA_THIS s.mask[1] = 1; // channel 1 masked - BX_DMA_THIS s.mask[2] = 1; // channel 2 masked - BX_DMA_THIS s.mask[3] = 1; // channel 3 masked + for (i=0; i<2; i++) { + BX_DMA_THIS s[i].mask[0] = 1; // channel 0 masked + BX_DMA_THIS s[i].mask[1] = 1; // channel 1 masked + BX_DMA_THIS s[i].mask[2] = 1; // channel 2 masked + BX_DMA_THIS s[i].mask[3] = 1; // channel 3 masked - BX_DMA_THIS s.flip_flop = 0; /* cleared */ - BX_DMA_THIS s.status_reg = 0; // no requests, no terminal counts reached - for (c=0; c<4; c++) { - BX_DMA_THIS s.chan[c].mode.mode_type = 0; // demand mode - BX_DMA_THIS s.chan[c].mode.address_decrement = 0; // address increment - BX_DMA_THIS s.chan[c].mode.autoinit_enable = 0; // autoinit disable - BX_DMA_THIS s.chan[c].mode.transfer_type = 0; // verify - BX_DMA_THIS s.chan[c].base_address = 0; - BX_DMA_THIS s.chan[c].current_address = 0; - BX_DMA_THIS s.chan[c].base_count = 0; - BX_DMA_THIS s.chan[c].current_count = 0; - BX_DMA_THIS s.chan[c].page_reg = 0; + BX_DMA_THIS s[i].flip_flop = 0; /* cleared */ + BX_DMA_THIS s[i].status_reg = 0; // no requests, no terminal counts reached + for (c=0; c<4; c++) { + BX_DMA_THIS s[i].chan[c].mode.mode_type = 0; // demand mode + BX_DMA_THIS s[i].chan[c].mode.address_decrement = 0; // address increment + BX_DMA_THIS s[i].chan[c].mode.autoinit_enable = 0; // autoinit disable + BX_DMA_THIS s[i].chan[c].mode.transfer_type = 0; // verify + BX_DMA_THIS s[i].chan[c].base_address = 0; + BX_DMA_THIS s[i].chan[c].current_address = 0; + BX_DMA_THIS s[i].chan[c].base_count = 0; + BX_DMA_THIS s[i].chan[c].current_count = 0; + BX_DMA_THIS s[i].chan[c].page_reg = 0; + } } } @@ -147,6 +141,7 @@ bx_dma_c::read( Bit32u address, unsigned io_len) Bit8u retval; Bit8u channel; + Boolean ma_sl; if (io_len > 1) { BX_ERROR(("io read from address %08x, len=%u", @@ -166,31 +161,42 @@ bx_dma_c::read( Bit32u address, unsigned io_len) case 0x02: /* DMA-1 current address, channel 1 */ case 0x04: /* DMA-1 current address, channel 2 */ case 0x06: /* DMA-1 current address, channel 3 */ - channel = address >> 1; - if (BX_DMA_THIS s.flip_flop==0) { - BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop; - return(BX_DMA_THIS s.chan[channel].current_address & 0xff); + case 0xc0: /* DMA-2 current address, channel 0 */ + case 0xc4: /* DMA-2 current address, channel 1 */ + case 0xc8: /* DMA-2 current address, channel 2 */ + case 0xcc: /* DMA-2 current address, channel 3 */ + ma_sl = (address >= 0xc0); + channel = (address >> (1 + ma_sl)) & 0x03; + if (BX_DMA_THIS s[ma_sl].flip_flop==0) { + BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; + return(BX_DMA_THIS s[ma_sl].chan[channel].current_address & 0xff); } else { - BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop; - return(BX_DMA_THIS s.chan[channel].current_address >> 8); + BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; + return(BX_DMA_THIS s[ma_sl].chan[channel].current_address >> 8); } case 0x01: /* DMA-1 current count, channel 0 */ case 0x03: /* DMA-1 current count, channel 1 */ case 0x05: /* DMA-1 current count, channel 2 */ case 0x07: /* DMA-1 current count, channel 3 */ - channel = address >> 1; - if (BX_DMA_THIS s.flip_flop==0) { - BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop; - return(BX_DMA_THIS s.chan[channel].current_count & 0xff); + case 0xc2: /* DMA-2 current count, channel 0 */ + case 0xc6: /* DMA-2 current count, channel 1 */ + case 0xca: /* DMA-2 current count, channel 2 */ + case 0xce: /* DMA-2 current count, channel 3 */ + ma_sl = (address >= 0xc2); + channel = (address >> (1 + ma_sl)) & 0x03; + if (BX_DMA_THIS s[ma_sl].flip_flop==0) { + BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; + return(BX_DMA_THIS s[ma_sl].chan[channel].current_count & 0xff); } else { - BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop; - return(BX_DMA_THIS s.chan[channel].current_count >> 8); + BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; + return(BX_DMA_THIS s[ma_sl].chan[channel].current_count >> 8); } case 0x08: // DMA-1 Status Register + case 0xd0: // DMA-2 Status Register // bit 7: 1 = channel 3 request // bit 6: 1 = channel 2 request // bit 5: 1 = channel 1 request @@ -200,12 +206,15 @@ bx_dma_c::read( Bit32u address, unsigned io_len) // bit 1: 1 = channel 1 has reached terminal count // bit 0: 1 = channel 0 has reached terminal count // reading this register clears lower 4 bits (hold flags) - retval = BX_DMA_THIS s.status_reg; - BX_DMA_THIS s.status_reg &= 0xf0; + ma_sl = (address == 0xd0); + retval = BX_DMA_THIS s[ma_sl].status_reg; + BX_DMA_THIS s[ma_sl].status_reg &= 0xf0; return(retval); break; - case 0x0d: // dma-1: temporary register - BX_PANIC(("dma-1: read of temporary register")); + case 0x0d: // DMA-1: temporary register + case 0xda: // DMA-2: temporary register + ma_sl = (address == 0xda); + BX_ERROR(("DMA-%d: read of temporary register", ma_sl+1)); // Note: write to 0x0D clears temporary register return(0); break; @@ -215,38 +224,33 @@ bx_dma_c::read( Bit32u address, unsigned io_len) case 0x0083: // DMA-1 page register, channel 1 case 0x0087: // DMA-1 page register, channel 0 channel = channelindex[address - 0x81]; - return( BX_DMA_THIS s.chan[channel].page_reg ); + return( BX_DMA_THIS s[0].chan[channel].page_reg ); - case 0x0084: // ??? + case 0x0089: // DMA-2 page register, channel 2 + case 0x008a: // DMA-2 page register, channel 3 + case 0x008b: // DMA-2 page register, channel 1 + case 0x008f: // DMA-2 page register, channel 0 + channel = channelindex[address - 0x89]; + return( BX_DMA_THIS s[1].chan[channel].page_reg ); + + case 0x0084: + case 0x0085: + case 0x0086: + case 0x0088: + case 0x008c: + case 0x008d: + case 0x008e: + BX_ERROR(("read: extra page register 0x%04x unsupported", (unsigned) address)); return(0); - case 0x0089: // DMA-2 page register, channel 6 - case 0x008a: // DMA-2 page register, channel 7 - case 0x008b: // DMA-2 page register, channel 5 - case 0x008f: // DMA-2 page register, channel 4 - channel = channelindex[address - 0x89] + 4; - BX_ERROR(("read: unsupported address=%04x (channel %d)", - (unsigned) address, channel)); - return( 0x00 ); - - case 0x00c0: - case 0x00c2: - case 0x00c4: - case 0x00c6: - case 0x00c8: - case 0x00ca: - case 0x00cc: - case 0x00ce: - case 0x00d0: case 0x00d2: case 0x00d4: case 0x00d6: case 0x00d8: - case 0x00da: case 0x00dc: case 0x00de: BX_ERROR(("read: unsupported address=%04x", (unsigned) address)); - return(0x0000); + return(0); break; default: @@ -278,6 +282,7 @@ bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len) #endif // !BX_USE_DMA_SMF Bit8u set_mask_bit; Bit8u channel; + Boolean ma_sl; if (io_len > 1) { if ( (io_len == 2) && (address == 0x0b) ) { @@ -296,7 +301,7 @@ bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len) return; } - BX_DEBUG(("dma: write: address=%04x value=%02x", + BX_DEBUG(("write: address=%04x value=%02x", (unsigned) address, (unsigned) value)); #if BX_DMA_FLOPPY_IO < 1 @@ -309,21 +314,26 @@ bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len) case 0x02: case 0x04: case 0x06: - channel = address >> 1; - BX_DEBUG((" DMA-1 base and current address, channel %d", channel)); - if (BX_DMA_THIS s.flip_flop==0) { /* 1st byte */ - BX_DMA_THIS s.chan[channel].base_address = value; - BX_DMA_THIS s.chan[channel].current_address = value; + case 0xc0: + case 0xc4: + case 0xc8: + case 0xcc: + ma_sl = (address >= 0xc0); + channel = (address >> (1 + ma_sl)) & 0x03; + BX_DEBUG((" DMA-%d base and current address, channel %d", ma_sl+1, channel)); + if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */ + BX_DMA_THIS s[ma_sl].chan[channel].base_address = value; + BX_DMA_THIS s[ma_sl].chan[channel].current_address = value; } else { /* 2nd byte */ - BX_DMA_THIS s.chan[channel].base_address |= (value << 8); - BX_DMA_THIS s.chan[channel].current_address |= (value << 8); + BX_DMA_THIS s[ma_sl].chan[channel].base_address |= (value << 8); + BX_DMA_THIS s[ma_sl].chan[channel].current_address |= (value << 8); BX_DEBUG((" base = %04x", - (unsigned) BX_DMA_THIS s.chan[channel].base_address)); + (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_address)); BX_DEBUG((" curr = %04x", - (unsigned) BX_DMA_THIS s.chan[channel].current_address)); + (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].current_address)); } - BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop; + BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; return; break; @@ -331,34 +341,43 @@ bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len) case 0x03: case 0x05: case 0x07: - channel = address >> 1; - BX_DEBUG((" DMA-1 base and current count, channel %d", channel)); - if (BX_DMA_THIS s.flip_flop==0) { /* 1st byte */ - BX_DMA_THIS s.chan[channel].base_count = value; - BX_DMA_THIS s.chan[channel].current_count = value; + case 0xc2: + case 0xc6: + case 0xca: + case 0xce: + ma_sl = (address >= 0xc2); + channel = (address >> (1 + ma_sl)) & 0x03; + BX_DEBUG((" DMA-%d base and current count, channel %d", ma_sl+1, channel)); + if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */ + BX_DMA_THIS s[ma_sl].chan[channel].base_count = value; + BX_DMA_THIS s[ma_sl].chan[channel].current_count = value; } else { /* 2nd byte */ - BX_DMA_THIS s.chan[channel].base_count |= (value << 8); - BX_DMA_THIS s.chan[channel].current_count |= (value << 8); + BX_DMA_THIS s[ma_sl].chan[channel].base_count |= (value << 8); + BX_DMA_THIS s[ma_sl].chan[channel].current_count |= (value << 8); BX_DEBUG((" base = %04x", - (unsigned) BX_DMA_THIS s.chan[channel].base_count)); + (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_count)); BX_DEBUG((" curr = %04x", - (unsigned) BX_DMA_THIS s.chan[channel].current_count)); + (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].current_count)); } - BX_DMA_THIS s.flip_flop = !BX_DMA_THIS s.flip_flop; + BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; return; break; case 0x08: /* DMA-1: command register */ + case 0xd0: /* DMA-2: command register */ + ma_sl = (address == 0xd0); if (value != 0x04) - BX_ERROR(("DMA: write to 0008: value(%02xh) not 04h", + BX_ERROR(("DMA: write to 0x%02x: value(%02xh) not 04h", address, (unsigned) value)); - BX_DMA_THIS s.command_reg = value; + BX_DMA_THIS s[ma_sl].command_reg = value; return; break; case 0x09: // DMA-1: request register - BX_ERROR(("DMA-1: write to request register (%02x)", (unsigned) value)); + case 0xd2: // DMA-2: request register + ma_sl = (address == 0xd2); + BX_ERROR(("DMA-%d: write to request register (%02x)", ma_sl+1, (unsigned) value)); // note: write to 0x0d clears this register if (value & 0x04) { // set request bit @@ -368,123 +387,122 @@ bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len) // clear request bit channel = value & 0x03; - BX_DMA_THIS s.status_reg &= ~(1 << (channel+4)); - BX_DEBUG(("dma-1: cleared request bit for channel %u", (unsigned) channel)); + BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4)); + BX_DEBUG(("DMA-%d: cleared request bit for channel %u", ma_sl+1, (unsigned) channel)); } return; break; case 0x0a: + case 0xd4: + ma_sl = (address == 0xd4); set_mask_bit = value & 0x04; channel = value & 0x03; - BX_DMA_THIS s.mask[channel] = (set_mask_bit > 0); - BX_DEBUG(("DMA1: set_mask_bit=%u, channel=%u, mask now=%02xh", - (unsigned) set_mask_bit, (unsigned) channel, (unsigned) BX_DMA_THIS s.mask[channel])); + BX_DMA_THIS s[ma_sl].mask[channel] = (set_mask_bit > 0); + BX_DEBUG(("DMA-%d: set_mask_bit=%u, channel=%u, mask now=%02xh", ma_sl+1, + (unsigned) set_mask_bit, (unsigned) channel, (unsigned) BX_DMA_THIS s[0].mask[channel])); return; break; - case 0x0b: /* dma-1 mode register */ + case 0x0b: /* DMA-1 mode register */ + case 0xd6: /* DMA-2 mode register */ + ma_sl = (address == 0xd6); channel = value & 0x03; - BX_DMA_THIS s.chan[channel].mode.mode_type = (value >> 6) & 0x03; - BX_DMA_THIS s.chan[channel].mode.address_decrement = (value >> 5) & 0x01; - BX_DMA_THIS s.chan[channel].mode.autoinit_enable = (value >> 4) & 0x01; - BX_DMA_THIS s.chan[channel].mode.transfer_type = (value >> 2) & 0x03; -//BX_DEBUG(("DMA1: mode register[%u] = %02x", -//(unsigned) channel, (unsigned) value)); - BX_DEBUG(("DMA1: mode register[%u] = %02x", + BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type = (value >> 6) & 0x03; + BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement = (value >> 5) & 0x01; + BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable = (value >> 4) & 0x01; + BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type = (value >> 2) & 0x03; + BX_DEBUG(("DMA-%d: mode register[%u] = %02x", ma_sl+1, (unsigned) channel, (unsigned) value)); return; break; - case 0x0c: /* dma-1 clear byte flip/flop */ - BX_DEBUG(("DMA1: clear flip/flop")); - BX_DMA_THIS s.flip_flop = 0; + case 0x0c: /* DMA-1 clear byte flip/flop */ + case 0xd8: /* DMA-2 clear byte flip/flop */ + ma_sl = (address == 0xd8); + BX_DEBUG(("DMA-%d: clear flip/flop", ma_sl+1)); + BX_DMA_THIS s[ma_sl].flip_flop = 0; return; break; - case 0x0d: // dma-1: master disable + case 0x0d: // DMA-1: master disable + case 0xda: // DMA-2: master disable + ma_sl = (address == 0xda); /* ??? */ - BX_DEBUG(("master disable")); - // writing any value to this port resets DMA controller 1 + BX_DEBUG(("DMA-%d: master disable", ma_sl+1)); + // writing any value to this port resets DMA controller 1 / 2 // same action as a hardware reset // mask register is set (chan 0..3 disabled) // command, status, request, temporary, and byte flip-flop are all cleared - BX_DMA_THIS s.mask[0] = 1; - BX_DMA_THIS s.mask[1] = 1; - BX_DMA_THIS s.mask[2] = 1; - BX_DMA_THIS s.mask[3] = 1; - BX_DMA_THIS s.command_reg = 0; - BX_DMA_THIS s.status_reg = 0; - BX_DMA_THIS s.request_reg = 0; - BX_DMA_THIS s.temporary_reg = 0; - BX_DMA_THIS s.flip_flop = 0; + BX_DMA_THIS s[ma_sl].mask[0] = 1; + BX_DMA_THIS s[ma_sl].mask[1] = 1; + BX_DMA_THIS s[ma_sl].mask[2] = 1; + BX_DMA_THIS s[ma_sl].mask[3] = 1; + BX_DMA_THIS s[ma_sl].command_reg = 0; + BX_DMA_THIS s[ma_sl].status_reg = 0; + BX_DMA_THIS s[ma_sl].request_reg = 0; + BX_DMA_THIS s[ma_sl].temporary_reg = 0; + BX_DMA_THIS s[ma_sl].flip_flop = 0; return; break; - case 0x0e: // dma-1: clear mask register - BX_DEBUG(("dma-1: clear mask register")); - BX_DMA_THIS s.mask[0] = 0; - BX_DMA_THIS s.mask[1] = 0; - BX_DMA_THIS s.mask[2] = 0; - BX_DMA_THIS s.mask[3] = 0; + case 0x0e: // DMA-1: clear mask register + case 0xdc: // DMA-2: clear mask register + ma_sl = (address == 0xdc); + BX_DEBUG(("DMA-%d: clear mask register", ma_sl+1)); + BX_DMA_THIS s[ma_sl].mask[0] = 0; + BX_DMA_THIS s[ma_sl].mask[1] = 0; + BX_DMA_THIS s[ma_sl].mask[2] = 0; + BX_DMA_THIS s[ma_sl].mask[3] = 0; return; break; - case 0x0f: // dma-1: write all mask bits - BX_DEBUG(("dma-1: write all mask bits")); - BX_DMA_THIS s.mask[0] = value & 0x01; value >>= 1; - BX_DMA_THIS s.mask[1] = value & 0x01; value >>= 1; - BX_DMA_THIS s.mask[2] = value & 0x01; value >>= 1; - BX_DMA_THIS s.mask[3] = value & 0x01; + case 0x0f: // DMA-1: write all mask bits + case 0xde: // DMA-2: write all mask bits + ma_sl = (address == 0xde); + BX_DEBUG(("DMA-%d: write all mask bits", ma_sl+1)); + BX_DMA_THIS s[ma_sl].mask[0] = value & 0x01; value >>= 1; + BX_DMA_THIS s[ma_sl].mask[1] = value & 0x01; value >>= 1; + BX_DMA_THIS s[ma_sl].mask[2] = value & 0x01; value >>= 1; + BX_DMA_THIS s[ma_sl].mask[3] = value & 0x01; return; break; - case 0x81: /* dma page register, channel 2 */ - case 0x82: /* dma page register, channel 3 */ - case 0x83: /* dma page register, channel 1 */ - case 0x87: /* dma page register, channel 0 */ + case 0x81: /* DMA-1 page register, channel 2 */ + case 0x82: /* DMA-1 page register, channel 3 */ + case 0x83: /* DMA-1 page register, channel 1 */ + case 0x87: /* DMA-1 page register, channel 0 */ /* address bits A16-A23 for DMA channel */ channel = channelindex[address - 0x81]; - BX_DMA_THIS s.chan[channel].page_reg = value; - BX_DEBUG(("DMA1: page register %d = %02x", channel, (unsigned) value)); + BX_DMA_THIS s[0].chan[channel].page_reg = value; + BX_DEBUG(("DMA-1: page register %d = %02x", channel, (unsigned) value)); return; break; - case 0x0084: // ??? + case 0x89: /* DMA-2 page register, channel 2 */ + case 0x8A: /* DMA-2 page register, channel 3 */ + case 0x8B: /* DMA-2 page register, channel 1 */ + case 0x8F: /* DMA-2 page register, channel 0 */ + /* address bits A16-A23 for DMA channel */ + channel = channelindex[address - 0x89]; + BX_DMA_THIS s[1].chan[channel].page_reg = value; + BX_DEBUG(("DMA-2: page register %d = %02x", channel + 4, (unsigned) value)); return; break; - //case 0xd0: /* DMA-2 command register */ - // if (value != 0x04) - // BX_DEBUG(("DMA2: write command register: value(%02xh)!=04h", - // (unsigned) value)); - // return; - // break; - - case 0x00c0: - case 0x00c2: - case 0x00c4: - case 0x00c6: - case 0x00c8: - case 0x00ca: - case 0x00cc: - case 0x00ce: - case 0x00d0: - case 0x00d2: - case 0x00d4: - case 0x00d6: - case 0x00d8: - case 0x00da: - case 0x00dc: - case 0x00de: - BX_DEBUG(("DMA(ignored): write: %04xh = %04xh", - (unsigned) address, (unsigned) value)); + case 0x0084: + case 0x0085: + case 0x0086: + case 0x0088: + case 0x008C: + case 0x008D: + case 0x008E: + BX_ERROR(("write: extra page register 0x%04x unsupported", (unsigned) address)); return; break; - default: - BX_ERROR(("DMA(ignored): write: %04xh = %02xh", + BX_ERROR(("write ignored: %04xh = %02xh", (unsigned) address, (unsigned) value)); } } @@ -493,22 +511,26 @@ bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len) bx_dma_c::DRQ(unsigned channel, Boolean val) { Bit32u dma_base, dma_roof; + Boolean ma_sl; #if BX_SUPPORT_SB16 - if ( (channel != 2) && (channel != (unsigned) BX_SB16_DMAL) ) - BX_PANIC(("bx_dma_c::DRQ(): channel %d != 2 or %d (SB16) (", - channel, BX_SB16_DMAL)); + if ( (channel != 2) && (channel != (unsigned) BX_SB16_DMAL) && + (channel != (unsigned) BX_SB16_DMAH) ) + BX_PANIC(("DRQ(): channel %d != 2 or %d (SB16) or %d (SB16)", + channel, BX_SB16_DMAL, BX_SB16_DMAH)); #else if ( channel != 2 ) - BX_PANIC(("bx_dma_c::DRQ(): channel %d != 2", + BX_PANIC(("DRQ(): channel %d != 2", channel)); #endif + ma_sl = (channel > 3); + channel &= 0x03; if (!val) { //BX_DEBUG(("bx_dma_c::DRQ(): val == 0")); // clear bit in status reg // deassert HRQ if not pending DRQ's ? // etc. - BX_DMA_THIS s.status_reg &= ~(1 << (channel+4)); + BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4)); return; } @@ -527,27 +549,27 @@ bx_dma_c::DRQ(unsigned channel, Boolean val) BX_INFO((".page_reg: %02x", (unsigned) BX_DMA_THIS s.chan[channel].page_reg)); #endif - BX_DMA_THIS s.status_reg |= (1 << (channel+4)); + BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4)); // if (BX_DMA_THIS s.mask[channel]) // BX_PANIC(("bx_dma_c::DRQ(): BX_DMA_THIS s.mask[] is set")); - if ( (BX_DMA_THIS s.chan[channel].mode.mode_type != DMA_MODE_SINGLE) && - (BX_DMA_THIS s.chan[channel].mode.mode_type != DMA_MODE_DEMAND) ) - BX_PANIC(("bx_dma_c::DRQ: mode_type(%02x) not handled", - (unsigned) BX_DMA_THIS s.chan[channel].mode.mode_type)); - if (BX_DMA_THIS s.chan[channel].mode.address_decrement != 0) - BX_PANIC(("bx_dma_c::DRQ: address_decrement != 0")); + if ( (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_SINGLE) && + (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_DEMAND) ) + BX_PANIC(("DRQ: mode_type(%02x) not handled", + (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type)); + if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement != 0) + BX_PANIC(("DRQ: address_decrement != 0")); //if (BX_DMA_THIS s.chan[channel].mode.autoinit_enable != 0) // BX_PANIC(("bx_dma_c::DRQ: autoinit_enable != 0")); - dma_base = (BX_DMA_THIS s.chan[channel].page_reg << 16) | BX_DMA_THIS s.chan[channel].base_address; - dma_roof = dma_base + BX_DMA_THIS s.chan[channel].base_count; + dma_base = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) | BX_DMA_THIS s[ma_sl].chan[channel].base_address; + dma_roof = dma_base + BX_DMA_THIS s[ma_sl].chan[channel].base_count; if ( (dma_base & 0xffff0000) != (dma_roof & 0xffff0000) ) { - BX_INFO(("dma_base = %08x", (unsigned) dma_base)); - BX_INFO(("dma_base_count = %08x", (unsigned) BX_DMA_THIS s.chan[channel].base_count)); - BX_INFO(("dma_roof = %08x", (unsigned) dma_roof)); + BX_INFO(("dma_base = %08x", (unsigned) dma_base)); + BX_INFO(("dma_base_count = %08x", (unsigned) BX_DMA_THIS s[0].chan[channel].base_count)); + BX_INFO(("dma_roof = %08x", (unsigned) dma_roof)); BX_PANIC(("request outside 64k boundary")); } @@ -563,45 +585,56 @@ bx_dma_c::raise_HLDA(bx_pc_system_c *pc_sys) unsigned channel; Bit32u phy_addr; Boolean count_expired = 0; + Boolean ma_sl; // find highest priority channel for (channel=0; channel<4; channel++) { - if ( (BX_DMA_THIS s.status_reg & (1 << (channel+4))) && - (BX_DMA_THIS s.mask[channel]==0) ) { + if ( (BX_DMA_THIS s[0].status_reg & (1 << (channel+4))) && + (BX_DMA_THIS s[0].mask[channel]==0) ) { + ma_sl = 0; break; } } if (channel >= 4) { - // don't panic, just wait till they're unmasked + for (channel=0; channel<4; channel++) { + if ( (BX_DMA_THIS s[1].status_reg & (1 << (channel+4))) && + (BX_DMA_THIS s[1].mask[channel]==0) ) { + ma_sl = 1; + break; + } + } + } + if (channel >= 4) { + // don't panic, just wait till they're unmasked // BX_PANIC(("hlda: no unmasked requests")); return; } //BX_DEBUG(("hlda: OK in response to DRQ(%u)", (unsigned) channel)); - phy_addr = (BX_DMA_THIS s.chan[channel].page_reg << 16) | - BX_DMA_THIS s.chan[channel].current_address; + phy_addr = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) | + (BX_DMA_THIS s[ma_sl].chan[channel].current_address << ma_sl); - bx_pc_system.set_DACK(channel, 1); + bx_pc_system.set_DACK(channel + (ma_sl << 2), 1); // check for expiration of count, so we can signal TC and DACK(n) // at the same time. - if (BX_DMA_THIS s.chan[channel].mode.address_decrement==0) { + if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement==0) { // address increment - BX_DMA_THIS s.chan[channel].current_address++; - BX_DMA_THIS s.chan[channel].current_count--; - if (BX_DMA_THIS s.chan[channel].current_count == 0xffff) - if (BX_DMA_THIS s.chan[channel].mode.autoinit_enable == 0) { + BX_DMA_THIS s[ma_sl].chan[channel].current_address++; + BX_DMA_THIS s[ma_sl].chan[channel].current_count--; + if (BX_DMA_THIS s[ma_sl].chan[channel].current_count == 0xffff) + if (BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable == 0) { // count expired, done with transfer // assert TC, deassert HRQ & DACK(n) lines - BX_DMA_THIS s.status_reg |= (1 << channel); // hold TC in status reg + BX_DMA_THIS s[ma_sl].status_reg |= (1 << channel); // hold TC in status reg bx_pc_system.set_TC(1); count_expired = 1; } else { // count expired, but in autoinit mode // reload count and base address - BX_DMA_THIS s.chan[channel].current_address = - BX_DMA_THIS s.chan[channel].base_address; - BX_DMA_THIS s.chan[channel].current_count = - BX_DMA_THIS s.chan[channel].base_count; + BX_DMA_THIS s[ma_sl].chan[channel].current_address = + BX_DMA_THIS s[ma_sl].chan[channel].base_address; + BX_DMA_THIS s[ma_sl].chan[channel].current_count = + BX_DMA_THIS s[ma_sl].chan[channel].base_count; } } @@ -610,22 +643,32 @@ bx_dma_c::raise_HLDA(bx_pc_system_c *pc_sys) BX_PANIC(("hlda: decrement not implemented")); } - if (BX_DMA_THIS s.chan[channel].mode.transfer_type == 1) { // write + if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 1) { // write // xfer from I/O to Memory - pc_sys->dma_write8(phy_addr, channel); + if (!ma_sl) { + pc_sys->dma_write8(phy_addr, channel); + } + else { + pc_sys->dma_write16(phy_addr, channel+4); + } } - else if (BX_DMA_THIS s.chan[channel].mode.transfer_type == 2) { // read + else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 2) { // read // xfer from Memory to I/O - pc_sys->dma_read8(phy_addr, channel); + if (!ma_sl) { + pc_sys->dma_read8(phy_addr, channel); + } + else { + pc_sys->dma_read16(phy_addr, channel+4); + } } else { BX_PANIC(("hlda: transfer_type of %u not handled", - (unsigned) BX_DMA_THIS s.chan[channel].mode.transfer_type)); + (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type)); } if (count_expired) { bx_pc_system.set_TC(0); // clear TC, adapter card already notified bx_pc_system.set_HRQ(0); // clear HRQ to CPU - bx_pc_system.set_DACK(channel, 0); // clear DACK to adapter card + bx_pc_system.set_DACK(channel + (ma_sl << 2), 0); // clear DACK to adapter card } } diff --git a/bochs/iodev/dma.h b/bochs/iodev/dma.h index 9a0d38a71..80d0db38e 100644 --- a/bochs/iodev/dma.h +++ b/bochs/iodev/dma.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: dma.h,v 1.4 2001-10-03 13:10:38 bdenney Exp $ +// $Id: dma.h,v 1.5 2001-12-18 13:12:45 vruppert Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -81,7 +81,7 @@ private: Bit16u current_count; Bit8u page_reg; } chan[4]; /* DMA channels 0..3 */ - } s; // state information + } s[2]; // state information DMA-1 / DMA-2 bx_devices_c *devices; }; diff --git a/bochs/iodev/iodev.h b/bochs/iodev/iodev.h index e518b2ee9..ebd673826 100644 --- a/bochs/iodev/iodev.h +++ b/bochs/iodev/iodev.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////// -// $Id: iodev.h,v 1.10 2001-10-03 13:10:38 bdenney Exp $ +// $Id: iodev.h,v 1.11 2001-12-18 13:12:45 vruppert Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. @@ -90,6 +90,8 @@ public: void dma_write8(unsigned channel, Bit8u *data); void dma_read8(unsigned channel, Bit8u *data); + void dma_write16(unsigned channel, Bit16u *data); + void dma_read16(unsigned channel, Bit16u *data); void drq(unsigned channel, Boolean val); void raise_hlda(void); static void timer_handler(void *);