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:
@@ -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;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user