1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-16 15:29:34 +00:00

Prepare for additional devices.

This commit is contained in:
Thomas Harte 2024-03-12 21:23:22 -04:00
parent 5d6bb11eb7
commit 2ed031e440

View File

@ -164,11 +164,31 @@ namespace IRQA {
static constexpr uint8_t SetAlways = 0x80;
}
namespace InterruptRequests {
// IRQ B flags
namespace IRQB {
// These are taken from the A3010 documentation.
static constexpr uint8_t PoduleFIQRequest = 0x01;
static constexpr uint8_t SoundBufferPointerUsed = 0x02;
static constexpr uint8_t SerialLine = 0x04;
static constexpr uint8_t IDE = 0x08;
static constexpr uint8_t FloppyDiscInterrupt = 0x10;
static constexpr uint8_t PoduleIRQRequest = 0x20;
static constexpr uint8_t KeyboardTransmitEmpty = 0x40;
static constexpr uint8_t KeyboardReceiveFull = 0x80;
}
// FIQ flags
namespace FIQ {
// These are taken from the A3010 documentation.
static constexpr uint8_t FloppyDiscData = 0x01;
static constexpr uint8_t SerialLine = 0x10;
static constexpr uint8_t PoduleFIQRequest = 0x40;
static constexpr uint8_t SetAlways = 0x80;
}
namespace InterruptRequests {
static constexpr int IRQ = 0x01;
static constexpr int FIQ = 0x02;
};
struct Interrupts {
@ -203,38 +223,82 @@ struct Interrupts {
return did_change_interrupts;
}
bool read(uint32_t address, uint8_t &value) const {
const auto target = address & 0x7f;
logger.error().append("IO controller read from %08x", address);
switch(target) {
default: break;
static constexpr uint32_t AddressMask = 0x1f'ffff;
case 0x00:
bool read(uint32_t address, uint8_t &value) const {
const auto target = address & AddressMask;
switch(target) {
default:
logger.error().append("Unrecognised IOC read from %08x", address);
break;
case 0x3200000 & AddressMask:
logger.error().append("TODO: IOC control read");
value = 0;
return true;
case 0x3200004 & AddressMask:
logger.error().append("TODO: IOC serial receive");
value = 0;
return true;
// IRQ A.
case 0x10: value = irq_a_.status; return true;
case 0x14: value = irq_a_.request(); return true;
case 0x18: value = irq_a_.mask; return true;
case 0x3200010 & AddressMask:
value = irq_a_.status;
logger.error().append("IRQ A status is %02x", value);
return true;
case 0x3200014 & AddressMask:
value = irq_a_.request();
logger.error().append("IRQ A request is %02x", value);
return true;
case 0x3200018 & AddressMask:
value = irq_a_.mask;
logger.error().append("IRQ A mask is %02x", value);
return true;
// IRQ B.
case 0x20: value = irq_b_.status; return true;
case 0x24: value = irq_b_.request(); return true;
case 0x28: value = irq_b_.mask; return true;
case 0x3200020 & AddressMask:
value = irq_b_.status;
logger.error().append("IRQ B status is %02x", value);
return true;
case 0x3200024 & AddressMask:
value = irq_b_.request();
logger.error().append("IRQ B request is %02x", value);
return true;
case 0x3200028 & AddressMask:
value = irq_b_.mask;
logger.error().append("IRQ B mask is %02x", value);
return true;
// FIQ.
case 0x30: value = fiq_.status; return true;
case 0x34: value = fiq_.request(); return true;
case 0x38: value = fiq_.mask; return true;
case 0x3200030 & AddressMask:
value = fiq_.status;
logger.error().append("FIQ status is %02x", value);
return true;
case 0x3200034 & AddressMask:
value = fiq_.request();
logger.error().append("FIQ request is %02x", value);
return true;
case 0x3200038 & AddressMask:
value = fiq_.mask;
logger.error().append("FIQ mask is %02x", value);
return true;
// Counters.
case 0x40: case 0x50: case 0x60: case 0x70:
case 0x3200040 & AddressMask:
case 0x3200050 & AddressMask:
case 0x3200060 & AddressMask:
case 0x3200070 & AddressMask:
value = counters_[(target >> 4) - 0x4].output & 0xff;
logger.error().append("%02x: Counter %d low is %02x", target, (target >> 4) - 0x4, value);
return true;
case 0x44: case 0x54: case 0x64: case 0x74:
case 0x3200044 & AddressMask:
case 0x3200054 & AddressMask:
case 0x3200064 & AddressMask:
case 0x3200074 & AddressMask:
value = counters_[(target >> 4) - 0x4].output >> 8;
logger.error().append("%02x: Counter %d high is %02x", target, (target >> 4) - 0x4, value);
return true;
}
@ -242,16 +306,22 @@ struct Interrupts {
}
bool write(uint32_t address, uint8_t value) {
const auto target = address & 0x7f;
const auto target = address & AddressMask;
logger.error().append("IO controller write of %02x at %08x", value, address);
switch(target) {
default: break;
default:
logger.error().append("Unrecognised IOC write of %02x at %08x", value, address);
break;
case 0x00:
case 0x3200000 & AddressMask:
logger.error().append("TODO: IOC control write %02x", value);
return true;
case 0x14:
case 0x3200004 & AddressMask:
logger.error().append("TODO: IOC serial transmit");
return true;
case 0x3200014 & AddressMask:
// b2: clear IF.
// b3: clear IR.
// b4: clear POR.
@ -261,26 +331,40 @@ struct Interrupts {
return true;
// Interrupts.
case 0x18: irq_a_.mask = value; return true;
case 0x28: irq_b_.mask = value; return true;
case 0x38: fiq_.mask = value; return true;
case 0x3200018 & AddressMask: irq_a_.mask = value; return true;
case 0x3200028 & AddressMask: irq_b_.mask = value; return true;
case 0x3200038 & AddressMask: fiq_.mask = value; return true;
// Counters.
case 0x40: case 0x50: case 0x60: case 0x70:
case 0x3200040 & AddressMask:
case 0x3200050 & AddressMask:
case 0x3200060 & AddressMask:
case 0x3200070 & AddressMask:
counters_[(target >> 4) - 0x4].reload = uint16_t(
(counters_[(target >> 4) - 0x4].reload & 0xff00) | value
);
return true;
case 0x44: case 0x54: case 0x64: case 0x74:
case 0x3200044 & AddressMask:
case 0x3200054 & AddressMask:
case 0x3200064 & AddressMask:
case 0x3200074 & AddressMask:
counters_[(target >> 4) - 0x4].reload = uint16_t(
(counters_[(target >> 4) - 0x4].reload & 0x00ff) | (value << 8)
);
return true;
case 0x48: case 0x58: case 0x68: case 0x78:
case 0x3200048 & AddressMask:
case 0x3200058 & AddressMask:
case 0x3200068 & AddressMask:
case 0x3200078 & AddressMask:
counters_[(target >> 4) - 0x4].value = counters_[(target >> 4) - 0x4].reload;
return true;
case 0x4c: case 0x5c: case 0x6c: case 0x7c:
case 0x320004c & AddressMask:
case 0x320005c & AddressMask:
case 0x320006c & AddressMask:
case 0x320007c & AddressMask:
counters_[(target >> 4) - 0x4].output = counters_[(target >> 4) - 0x4].value;
return true;
}
@ -396,12 +480,13 @@ struct Memory {
return true;
case Zone::AddressTranslator:
// printf("Translator write at %08x\n", address);
pages_[address & 0x7f] = address;
update_mapping();
break;
default:
printf("TODO: write of %08x to %08x [%lu]\n", source, address, sizeof(IntT));
// printf("TODO: write of %08x to %08x [%lu]\n", source, address, sizeof(IntT));
break;
}
@ -457,9 +542,6 @@ struct Memory {
// TODO: generalise this adaptation of an 8-bit device to the 32-bit bus, which probably isn't right anyway.
uint8_t value;
ioc_.read(address, value);
// if(!ioc_.read(address, value)) {
// return false;
// }
source = value;
return true;
}
@ -606,6 +688,12 @@ struct Memory {
}
void update_mapping() {
// static int c = 0;
// ++c;
// if(c == 662) {
// printf("");
// }
// For each physical page, project it into logical space.
switch(page_size_) {
default:
@ -615,7 +703,7 @@ struct Memory {
case PageSize::kb32: update_mapping<PageSize::kb32>(); break;
}
logger.info().append("Updated logical RAM mapping");
// logger.info().append("Updated logical RAM mapping [%d]", c);
}
template <PageSize size>
@ -687,6 +775,8 @@ struct Memory {
break;
}
// printf("%08x => logical %d -> physical %d\n", page, logical, (physical >> 15));
// TODO: consider clashes.
// TODO: what if there's less than 4mb present?
mapping_[logical].target = &ram_[physical];