mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-29 12:50:28 +00:00
Further flesh out DMA, breaking POST.
This commit is contained in:
parent
0dc44e8efd
commit
9fc0d411fd
@ -16,16 +16,21 @@ namespace PCCompatible {
|
|||||||
class i8237 {
|
class i8237 {
|
||||||
public:
|
public:
|
||||||
void flip_flop_reset() {
|
void flip_flop_reset() {
|
||||||
next_access_low = true;
|
next_access_low_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mask_reset() {
|
void mask_reset() {
|
||||||
// TODO: set all mask bits off.
|
for(auto &channel : channels_) {
|
||||||
|
channel.mask = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void master_reset() {
|
void master_reset() {
|
||||||
flip_flop_reset();
|
flip_flop_reset();
|
||||||
// TODO: clear status, set all mask bits on.
|
for(auto &channel : channels_) {
|
||||||
|
channel.mask = true;
|
||||||
|
channel.transfer_complete = channel.request = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int address>
|
template <int address>
|
||||||
@ -33,8 +38,8 @@ class i8237 {
|
|||||||
constexpr int channel = (address >> 1) & 3;
|
constexpr int channel = (address >> 1) & 3;
|
||||||
constexpr bool is_count = address & 1;
|
constexpr bool is_count = address & 1;
|
||||||
|
|
||||||
next_access_low ^= true;
|
next_access_low_ ^= true;
|
||||||
if(next_access_low) {
|
if(next_access_low_) {
|
||||||
if constexpr (is_count) {
|
if constexpr (is_count) {
|
||||||
channels_[channel].count.halves.high = value;
|
channels_[channel].count.halves.high = value;
|
||||||
} else {
|
} else {
|
||||||
@ -54,8 +59,8 @@ class i8237 {
|
|||||||
constexpr int channel = (address >> 1) & 3;
|
constexpr int channel = (address >> 1) & 3;
|
||||||
constexpr bool is_count = address & 1;
|
constexpr bool is_count = address & 1;
|
||||||
|
|
||||||
next_access_low ^= true;
|
next_access_low_ ^= true;
|
||||||
if(next_access_low) {
|
if(next_access_low_) {
|
||||||
if constexpr (is_count) {
|
if constexpr (is_count) {
|
||||||
return channels_[channel].count.halves.high;
|
return channels_[channel].count.halves.high;
|
||||||
} else {
|
} else {
|
||||||
@ -70,12 +75,89 @@ class i8237 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
void set_reset_mask(uint8_t value) {
|
||||||
bool next_access_low = true;
|
channels_[value & 3].mask = value & 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_reset_request(uint8_t value) {
|
||||||
|
channels_[value & 3].request = value & 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_mask(uint8_t value) {
|
||||||
|
channels_[0].mask = value & 1;
|
||||||
|
channels_[1].mask = value & 2;
|
||||||
|
channels_[2].mask = value & 4;
|
||||||
|
channels_[3].mask = value & 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_mode(uint8_t value) {
|
||||||
|
channels_[value & 3].transfer = Channel::Transfer((value >> 2) & 3);
|
||||||
|
channels_[value & 3].autoinitialise = value & 0x10;
|
||||||
|
channels_[value & 3].address_decrement = value & 0x20;
|
||||||
|
channels_[value & 3].mode = Channel::Mode(value >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_command(uint8_t value) {
|
||||||
|
enable_memory_to_memory_ = value & 0x01;
|
||||||
|
enable_channel0_address_hold_ = value & 0x02;
|
||||||
|
enable_controller_ = value & 0x04;
|
||||||
|
compressed_timing_ = value & 0x08;
|
||||||
|
rotating_priority_ = value & 0x10;
|
||||||
|
extended_write_selection_ = value & 0x20;
|
||||||
|
dreq_active_low_ = value & 0x40;
|
||||||
|
dack_sense_active_high_ = value & 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t status() {
|
||||||
|
const uint8_t result =
|
||||||
|
(channels_[0].transfer_complete ? 0x01 : 0x00) |
|
||||||
|
(channels_[1].transfer_complete ? 0x02 : 0x00) |
|
||||||
|
(channels_[2].transfer_complete ? 0x04 : 0x00) |
|
||||||
|
(channels_[3].transfer_complete ? 0x08 : 0x00) |
|
||||||
|
|
||||||
|
(channels_[0].request ? 0x10 : 0x00) |
|
||||||
|
(channels_[1].request ? 0x20 : 0x00) |
|
||||||
|
(channels_[2].request ? 0x40 : 0x00) |
|
||||||
|
(channels_[3].request ? 0x80 : 0x00);
|
||||||
|
|
||||||
|
for(auto &channel : channels_) {
|
||||||
|
channel.transfer_complete = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Low/high byte latch.
|
||||||
|
bool next_access_low_ = true;
|
||||||
|
|
||||||
|
// Various fields set by the command register.
|
||||||
|
bool enable_memory_to_memory_ = false;
|
||||||
|
bool enable_channel0_address_hold_ = false;
|
||||||
|
bool enable_controller_ = false;
|
||||||
|
bool compressed_timing_ = false;
|
||||||
|
bool rotating_priority_ = false;
|
||||||
|
bool extended_write_selection_ = false;
|
||||||
|
bool dreq_active_low_ = false;
|
||||||
|
bool dack_sense_active_high_ = false;
|
||||||
|
|
||||||
|
// Per-channel state.
|
||||||
struct Channel {
|
struct Channel {
|
||||||
|
bool mask = false;
|
||||||
|
enum class Transfer {
|
||||||
|
Verify, Write, Read, Invalid
|
||||||
|
} transfer = Transfer::Verify;
|
||||||
|
bool autoinitialise = false;
|
||||||
|
bool address_decrement = false;
|
||||||
|
enum class Mode {
|
||||||
|
Demand, Single, Block, Cascade
|
||||||
|
} mode = Mode::Demand;
|
||||||
|
|
||||||
|
bool request = false;
|
||||||
|
bool transfer_complete = false;
|
||||||
|
|
||||||
CPU::RegisterPair16 address, count;
|
CPU::RegisterPair16 address, count;
|
||||||
} channels_[4];
|
};
|
||||||
|
std::array<Channel, 4> channels_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DMAPages {
|
class DMAPages {
|
||||||
|
@ -953,28 +953,22 @@ class IO {
|
|||||||
printf("TODO: NMIs %s\n", (value & 0x80) ? "masked" : "unmasked");
|
printf("TODO: NMIs %s\n", (value & 0x80) ? "masked" : "unmasked");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0000: dma_.i8237.write<0>(value); break;
|
case 0x0000: dma_.i8237.write<0>(value); break;
|
||||||
case 0x0001: dma_.i8237.write<1>(value); break;
|
case 0x0001: dma_.i8237.write<1>(value); break;
|
||||||
case 0x0002: dma_.i8237.write<2>(value); break;
|
case 0x0002: dma_.i8237.write<2>(value); break;
|
||||||
case 0x0003: dma_.i8237.write<3>(value); break;
|
case 0x0003: dma_.i8237.write<3>(value); break;
|
||||||
case 0x0004: dma_.i8237.write<4>(value); break;
|
case 0x0004: dma_.i8237.write<4>(value); break;
|
||||||
case 0x0005: dma_.i8237.write<5>(value); break;
|
case 0x0005: dma_.i8237.write<5>(value); break;
|
||||||
case 0x0006: dma_.i8237.write<6>(value); break;
|
case 0x0006: dma_.i8237.write<6>(value); break;
|
||||||
case 0x0007: dma_.i8237.write<7>(value); break;
|
case 0x0007: dma_.i8237.write<7>(value); break;
|
||||||
|
case 0x0008: dma_.i8237.set_command(uint8_t(value)); break;
|
||||||
// TODO: 0x0008 -> command
|
case 0x0009: dma_.i8237.set_reset_request(uint8_t(value)); break;
|
||||||
// TODO: 0x000a -> mask
|
case 0x000a: dma_.i8237.set_reset_mask(uint8_t(value)); break;
|
||||||
// TODO: 0x000b -> mode
|
case 0x000b: dma_.i8237.set_mode(uint8_t(value)); break;
|
||||||
case 0x000c: dma_.i8237.flip_flop_reset(); break;
|
case 0x000c: dma_.i8237.flip_flop_reset(); break;
|
||||||
|
case 0x000d: dma_.i8237.master_reset(); break;
|
||||||
case 0x0008: case 0x0009:
|
case 0x000e: dma_.i8237.mask_reset(); break;
|
||||||
case 0x000a: case 0x000b:
|
case 0x000f: dma_.i8237.set_mask(uint8_t(value)); break;
|
||||||
case 0x000f:
|
|
||||||
printf("TODO: DMA write of %02x at %04x\n", value, port);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x000d: dma_.i8237.master_reset(); break;
|
|
||||||
case 0x000e: dma_.i8237.mask_reset(); break;
|
|
||||||
|
|
||||||
case 0x0020: pic_.write<0>(value); break;
|
case 0x0020: pic_.write<0>(value); break;
|
||||||
case 0x0021: pic_.write<1>(value); break;
|
case 0x0021: pic_.write<1>(value); break;
|
||||||
@ -1072,7 +1066,9 @@ class IO {
|
|||||||
case 0x0006: return dma_.i8237.read<6>();
|
case 0x0006: return dma_.i8237.read<6>();
|
||||||
case 0x0007: return dma_.i8237.read<7>();
|
case 0x0007: return dma_.i8237.read<7>();
|
||||||
|
|
||||||
case 0x0008: case 0x0009:
|
case 0x0008: return dma_.i8237.status();
|
||||||
|
|
||||||
|
case 0x0009:
|
||||||
case 0x000a: case 0x000b:
|
case 0x000a: case 0x000b:
|
||||||
case 0x000c: case 0x000f:
|
case 0x000c: case 0x000f:
|
||||||
printf("TODO: DMA read from %04x\n", port);
|
printf("TODO: DMA read from %04x\n", port);
|
||||||
|
Loading…
Reference in New Issue
Block a user