1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-01-23 16:16:16 +00:00

Finally crack case of controller failure.

This commit is contained in:
Thomas Harte
2025-09-04 15:16:48 -04:00
parent d5650da8c0
commit 4e822347a5
4 changed files with 59 additions and 28 deletions

View File

@@ -17,6 +17,8 @@
#include <array>
//extern bool should_log;
namespace PCCompatible {
enum class AccessResult {
@@ -245,12 +247,19 @@ private:
template <bool is_pair>
class DMAPages {
public:
int count = 0;
template <int index>
void set_page(const uint8_t value) {
pages_[page_for_index(index)] = value;
if(index == 0x00) {
log_.info().append("%02x", value);
// if(value == 0x3c) {
// ++count;
// should_log |= count == 2;
// }
}
}

View File

@@ -198,15 +198,12 @@ public:
);
drive.raised_interrupt = true;
drive.status =
decoder_.target().drive | uint8_t(Intel::i8272::Status0::SeekEnded);
drive.status = decoder_.target().drive | uint8_t(Intel::i8272::Status0::SeekEnded);
drive.ready = drive.has_disk();
pics_.pic[0].template apply_edge<6>(true);
} break;
case Command::SenseInterruptStatus: {
log_.info().append("Sense interrupt status");
const auto interruptor = std::find_if(
std::begin(drives_),
std::end(drives_),
@@ -216,12 +213,22 @@ public:
);
if(interruptor != std::end(drives_)) {
last_seeking_drive_ = interruptor - std::begin(drives_);
interruptor->raised_interrupt = false;
interruptor->status &= ~ 0xc0;
}
status_.set_status0(drives_[last_seeking_drive_].status);
results_.serialise(status_, drives_[last_seeking_drive_].track);
auto &drive = drives_[last_seeking_drive_];
log_.info().append(
"Sense interrupt status; picked drive %d with interrupt status %d",
last_seeking_drive_,
drive.raised_interrupt
);
status_.set_status0(drive.status);
results_.serialise(status_, drive.track);
// Clear cause-of-interrupt flags on that drive.
drive.raised_interrupt = false;
drive.status &= ~0xc0;
// Possibly lower interrupt flag.
const bool any_remaining_interrupts = std::accumulate(
std::begin(drives_),
std::end(drives_),
@@ -312,18 +319,18 @@ private:
mutable Log::Logger<Log::Source::Floppy> log_;
void reset() {
// printf("FDC reset\n");
log_.info().append("{Reset}");
decoder_.clear();
status_.reset();
// Necessary to pass GlaBIOS' POST test, but: why?
//
// Cf. INT_13_0_2 and the CMP AL, 11000000B following a CALL FDC_WAIT_SENSE.
// for(int c = 0; c < 4; c++) {
// drives_[c].raised_interrupt = true;
// drives_[c].status = uint8_t(Intel::i8272::Status0::BecameNotReady);
// }
// pics_.pic[0].template apply_edge<6>(true);
for(int c = 0; c < 4; c++) {
drives_[c].raised_interrupt = true;
drives_[c].status = uint8_t(Intel::i8272::Status0::BecameNotReady) | uint8_t(c);
}
pics_.pic[0].template apply_edge<6>(true);
using MainStatus = Intel::i8272::MainStatus;
status_.set(MainStatus::DataReady, true);

View File

@@ -24,6 +24,27 @@ namespace PCCompatible {
// TODO: send writes to the ROM area off to nowhere.
// TODO: support banked sections for EGA/VGA and possibly EMS purposes.
struct DummyValue {
public:
template <typename IntT>
IntT &value() {
if constexpr (std::is_same_v<IntT, uint32_t>) {
return dummies_.dummy32;
} else if constexpr (std::is_same_v<IntT, uint16_t>) {
return dummies_.dummy16;
} else if constexpr (std::is_same_v<IntT, uint8_t>) {
return dummies_.dummy8;
}
}
private:
union {
uint32_t dummy32;
uint16_t dummy16;
uint8_t dummy8;
} dummies_;
};
template <size_t MaxAddressV>
struct LinearPool {
static constexpr size_t MaxAddress = MaxAddressV;
@@ -255,7 +276,7 @@ struct LinearMemory<InstructionSet::x86::Model::i80286>: public LinearPool<1 <<
uint32_t address, uint32_t
) {
if(MaxAddress != (1 << 24) && (address & address_mask_) >= MaxAddress) {
return dummy<IntT>();
return dummy_.value<IntT>();
}
return *reinterpret_cast<IntT *>(&memory[address & address_mask_]);
}
@@ -266,14 +287,14 @@ struct LinearMemory<InstructionSet::x86::Model::i80286>: public LinearPool<1 <<
) const {
static_assert(!is_writeable(type));
if(MaxAddress != (1 << 24) && (address & address_mask_) >= MaxAddress) {
return dummy<IntT>();
return dummy_.value<IntT>();
}
return *reinterpret_cast<const IntT *>(&memory[address & address_mask_]);
}
template <typename IntT>
void write_back() {
dummy<IntT>() = IntT(~0);
dummy_.value<IntT>() = IntT(~0);
}
template <typename IntT>
@@ -291,16 +312,7 @@ struct LinearMemory<InstructionSet::x86::Model::i80286>: public LinearPool<1 <<
private:
uint32_t address_mask_;
union {
uint32_t dummy32;
uint16_t dummy16;
uint8_t dummy8;
} dummies_;
template <typename IntT> IntT &dummy();
template<> uint32_t &dummy<uint32_t>() { return dummies_.dummy32; }
template<> uint16_t &dummy<uint16_t>() { return dummies_.dummy16; }
template<> uint8_t &dummy<uint8_t>() { return dummies_.dummy8; }
static DummyValue dummy_;
};
}

View File

@@ -943,10 +943,13 @@ public:
}
// if(decoded_ip_ >= 0x7c00 && decoded_ip_ < 0x7c00 + 1024) {
// if(decoded_ip_ == 0x12d8) {
// if(decoded_ip_ == 0x21d0) {
// should_log = true;
// }
// Covers DISK_RESET.
// should_log = (decoded_ip_ >= 0x21d0 && decoded_ip_ < 0x221c);
if(should_log) {
const auto next = to_string(decoded_, InstructionSet::x86::Model::i8086);
static std::string previous;