1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-08-07 08:26:28 +00:00

Do some interrupt work.

This commit is contained in:
Thomas Harte
2023-11-21 15:46:31 -05:00
parent 83ca9b3af5
commit a1e118a1ff

View File

@@ -61,6 +61,10 @@ class PIC {
} }
} else { } else {
if(value & 0x10) { if(value & 0x10) {
//
// Initialisation Command Word 1.
//
config_.word = 0; config_.word = 0;
config_.has_fourth_word = value & 1; config_.has_fourth_word = value & 1;
@@ -71,14 +75,33 @@ class PIC {
single_pic_ = value & 2; single_pic_ = value & 2;
four_byte_vectors_ = value & 4; four_byte_vectors_ = value & 4;
level_triggered_ = value & 8; level_triggered_ = value & 8;
} else if(value & 0x08) {
//
// Operation Control Word 3.
//
// b6: 1 => use b5; 0 => ignore.
// b5: 1 => set special mask; 0 => clear.
// b2: 1 => poll command issued; 0 => not.
// b1: 1 => use b0; 0 => ignore.
// b0: 1 => read IRR on next read; 0 => read ISR.
} else {
//
// Operation Control Word 2.
//
// b7, b6, b5: EOI type.
// b2, b1, b0: interrupt level to acknowledge.
if((value >> 5) == 0b001) {
// Non-specific EOI.
awaiting_eoi_ = false;
}
} }
} }
printf("PIC: %02x to %d\n", value, address);
} }
template <int address> template <int address>
uint8_t read() { uint8_t read() {
printf("PIC: read from %d\n", address);
if(address) { if(address) {
return mask_; return mask_;
} }
@@ -101,7 +124,28 @@ class PIC {
bool pending() { bool pending() {
// Per the OSDev Wiki, masking is applied after the fact. // Per the OSDev Wiki, masking is applied after the fact.
return requests_ & ~mask_; return !awaiting_eoi_ && (requests_ & ~mask_);
}
int acknowledge() {
awaiting_eoi_ = true;
// TODO: there's bound to be a better solution than this search?
// TODO: is this the right priority order?
in_service_ = 0x80;
int id = 7;
while(!(in_service_ & requests_)) {
in_service_ >>= 1;
--id;
}
if(in_service_) {
requests_ &= ~in_service_;
return vector_base_ + id;
}
// Spurious interrupt.
return vector_base_ + 7;
} }
private: private:
@@ -112,6 +156,7 @@ class PIC {
uint8_t vector_base_ = 0; uint8_t vector_base_ = 0;
uint8_t mask_ = 0; uint8_t mask_ = 0;
bool awaiting_eoi_ = false;
uint8_t requests_ = 0; uint8_t requests_ = 0;
uint8_t in_service_ = 0; uint8_t in_service_ = 0;
@@ -389,20 +434,20 @@ struct Memory {
} }
// Accesses an address based on physical location. // Accesses an address based on physical location.
int mda_delay = -1; // HACK. // int mda_delay = -1; // HACK.
template <typename IntT, AccessType type> template <typename IntT, AccessType type>
typename InstructionSet::x86::Accessor<IntT, type>::type access(uint32_t address) { typename InstructionSet::x86::Accessor<IntT, type>::type access(uint32_t address) {
// TEMPORARY HACK. // TEMPORARY HACK.
if(mda_delay > 0) { // if(mda_delay > 0) {
--mda_delay; // --mda_delay;
if(!mda_delay) { // if(!mda_delay) {
print_mda(); // print_mda();
} // }
} // }
if(address >= 0xb'0000 && is_writeable(type)) { // if(address >= 0xb'0000 && is_writeable(type)) {
mda_delay = 100; // mda_delay = 100;
} // }
// Dispense with the single-byte case trivially. // Dispense with the single-byte case trivially.
if constexpr (std::is_same_v<IntT, uint8_t>) { if constexpr (std::is_same_v<IntT, uint8_t>) {
@@ -477,16 +522,16 @@ struct Memory {
// TEMPORARY HACK. // TEMPORARY HACK.
void print_mda() { // void print_mda() {
uint32_t pointer = 0xb'0000; // uint32_t pointer = 0xb'0000;
for(int y = 0; y < 25; y++) { // for(int y = 0; y < 25; y++) {
for(int x = 0; x < 80; x++) { // for(int x = 0; x < 80; x++) {
printf("%c", memory[pointer]); // printf("%c", memory[pointer]);
pointer += 2; // MDA goes [character, attributes]...; skip the attributes. // pointer += 2; // MDA goes [character, attributes]...; skip the attributes.
} // }
printf("\n"); // printf("\n");
} // }
} // }
private: private:
std::array<uint8_t, 1024*1024> memory{0xff}; std::array<uint8_t, 1024*1024> memory{0xff};
@@ -729,8 +774,11 @@ class ConcreteMachine:
context.flow_controller.begin_instruction(); context.flow_controller.begin_instruction();
} }
// TODO: signal interrupt. // Signal interrupt.
// printf("TODO: should interrupt\n"); InstructionSet::x86::interrupt(
pic_.acknowledge(),
context
);
} }
// Get the next thing to execute. // Get the next thing to execute.