mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-26 15:32:04 +00:00
Improve logging, factor out phase_matches per TODO comment.
This commit is contained in:
parent
5ed60f9153
commit
04f5d29ed9
@ -8,12 +8,18 @@
|
||||
|
||||
#include "ncr5380.hpp"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define NDEBUG
|
||||
#endif
|
||||
//#ifndef NDEBUG
|
||||
//#define NDEBUG
|
||||
//#endif
|
||||
#define LOG_PREFIX "[5380] "
|
||||
|
||||
#include "../../Outputs/Log.hpp"
|
||||
|
||||
// TODO:
|
||||
//
|
||||
// end_of_dma_ should be set if: /EOP && /DACK && (/RD || /WR); for at least 100ns.
|
||||
|
||||
|
||||
using namespace NCR::NCR5380;
|
||||
using SCSI::Line;
|
||||
|
||||
@ -32,7 +38,7 @@ NCR5380::NCR5380(SCSI::Bus &bus, int clock_rate) :
|
||||
void NCR5380::write(int address, uint8_t value, bool) {
|
||||
switch(address & 7) {
|
||||
case 0:
|
||||
LOG("[SCSI 0] Set current SCSI bus state to " << PADHEX(2) << int(value));
|
||||
LOG("[0] Set current SCSI bus state to " << PADHEX(2) << int(value));
|
||||
|
||||
data_bus_ = value;
|
||||
if(dma_request_ && dma_operation_ == DMAOperation::Send) {
|
||||
@ -41,7 +47,7 @@ void NCR5380::write(int address, uint8_t value, bool) {
|
||||
break;
|
||||
|
||||
case 1: {
|
||||
LOG("[SCSI 1] Initiator command register set: " << PADHEX(2) << int(value));
|
||||
LOG("[1] Initiator command register set: " << PADHEX(2) << int(value));
|
||||
initiator_command_ = value;
|
||||
|
||||
bus_output_ &= ~(Line::Reset | Line::Acknowledge | Line::Busy | Line::SelectTarget | Line::Attention);
|
||||
@ -57,7 +63,7 @@ void NCR5380::write(int address, uint8_t value, bool) {
|
||||
} break;
|
||||
|
||||
case 2:
|
||||
LOG("[SCSI 2] Set mode: " << PADHEX(2) << int(value));
|
||||
LOG("[2] Set mode: " << PADHEX(2) << int(value));
|
||||
mode_ = value;
|
||||
|
||||
// bit 7: 1 = use block mode DMA mode (if DMA mode is also enabled)
|
||||
@ -88,31 +94,36 @@ void NCR5380::write(int address, uint8_t value, bool) {
|
||||
bus_.update_observers();
|
||||
break;
|
||||
}
|
||||
|
||||
// "[The End of DMA Transfer] bit is reset when the DMA MODE bit
|
||||
// is reset (0) in the Mode Register".
|
||||
end_of_dma_ &= bool(value & 0x2);
|
||||
|
||||
update_control_output();
|
||||
break;
|
||||
|
||||
case 3: {
|
||||
LOG("[SCSI 3] Set target command: " << PADHEX(2) << int(value));
|
||||
LOG("[3] Set target command: " << PADHEX(2) << int(value));
|
||||
target_command_ = value;
|
||||
update_control_output();
|
||||
} break;
|
||||
|
||||
case 4:
|
||||
LOG("[SCSI 4] Set select enabled: " << PADHEX(2) << int(value));
|
||||
LOG("[4] Set select enabled: " << PADHEX(2) << int(value));
|
||||
break;
|
||||
|
||||
case 5:
|
||||
LOG("[SCSI 5] Start DMA send: " << PADHEX(2) << int(value));
|
||||
LOG("[5] Start DMA send: " << PADHEX(2) << int(value));
|
||||
dma_operation_ = DMAOperation::Send;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
LOG("[SCSI 6] Start DMA target receive: " << PADHEX(2) << int(value));
|
||||
LOG("[6] Start DMA target receive: " << PADHEX(2) << int(value));
|
||||
dma_operation_ = DMAOperation::TargetReceive;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
LOG("[SCSI 7] Start DMA initiator receive: " << PADHEX(2) << int(value));
|
||||
LOG("[7] Start DMA initiator receive: " << PADHEX(2) << int(value));
|
||||
dma_operation_ = DMAOperation::InitiatorReceive;
|
||||
break;
|
||||
}
|
||||
@ -136,7 +147,7 @@ void NCR5380::write(int address, uint8_t value, bool) {
|
||||
uint8_t NCR5380::read(int address, bool) {
|
||||
switch(address & 7) {
|
||||
case 0:
|
||||
LOG("[SCSI 0] Get current SCSI bus state: " << PADHEX(2) << (bus_.get_state() & 0xff));
|
||||
LOG("[0] Get current SCSI bus state: " << PADHEX(2) << (bus_.get_state() & 0xff));
|
||||
|
||||
if(dma_request_ && dma_operation_ == DMAOperation::InitiatorReceive) {
|
||||
return dma_acknowledge();
|
||||
@ -144,7 +155,7 @@ uint8_t NCR5380::read(int address, bool) {
|
||||
return uint8_t(bus_.get_state());
|
||||
|
||||
case 1:
|
||||
LOG("[SCSI 1] Initiator command register get: " << (arbitration_in_progress_ ? 'p' : '-') << (lost_arbitration_ ? 'l' : '-'));
|
||||
LOG("[1] Initiator command register get: " << (arbitration_in_progress_ ? 'p' : '-') << (lost_arbitration_ ? 'l' : '-'));
|
||||
return
|
||||
// Bits repeated as they were set.
|
||||
(initiator_command_ & ~0x60) |
|
||||
@ -156,11 +167,11 @@ uint8_t NCR5380::read(int address, bool) {
|
||||
(lost_arbitration_ ? 0x20 : 0x00);
|
||||
|
||||
case 2:
|
||||
LOG("[SCSI 2] Get mode");
|
||||
LOG("[2] Get mode");
|
||||
return mode_;
|
||||
|
||||
case 3:
|
||||
LOG("[SCSI 3] Get target command");
|
||||
LOG("[3] Get target command");
|
||||
return target_command_;
|
||||
|
||||
case 4: {
|
||||
@ -174,41 +185,37 @@ uint8_t NCR5380::read(int address, bool) {
|
||||
((bus_state & Line::Input) ? 0x04 : 0x00) |
|
||||
((bus_state & Line::SelectTarget) ? 0x02 : 0x00) |
|
||||
((bus_state & Line::Parity) ? 0x01 : 0x00);
|
||||
LOG("[SCSI 4] Get current bus state: " << PADHEX(2) << int(result));
|
||||
LOG("[4] Get current bus state: " << PADHEX(2) << int(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
case 5: {
|
||||
const auto bus_state = bus_.get_state();
|
||||
const bool phase_matches =
|
||||
(target_output() & (Line::Message | Line::Control | Line::Input)) ==
|
||||
(bus_state & (Line::Message | Line::Control | Line::Input));
|
||||
|
||||
const uint8_t result =
|
||||
/* b7 = end of DMA */
|
||||
(end_of_dma_ ? 0x80 : 0x00) |
|
||||
((dma_request_ && state_ == ExecutionState::PerformingDMA) ? 0x40 : 0x00) |
|
||||
/* b5 = parity error */
|
||||
/* b4 = IRQ active */
|
||||
(phase_matches ? 0x08 : 0x00) |
|
||||
(phase_matches() ? 0x08 : 0x00) |
|
||||
/* b2 = busy error */
|
||||
((bus_state & Line::Attention) ? 0x02 : 0x00) |
|
||||
((bus_state & Line::Acknowledge) ? 0x01 : 0x00);
|
||||
LOG("[SCSI 5] Get bus and status: " << PADHEX(2) << int(result));
|
||||
LOG("[5] Get bus and status: " << PADHEX(2) << int(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
case 6:
|
||||
LOG("[SCSI 6] Get input data");
|
||||
LOG("[6] Get input data");
|
||||
return 0xff;
|
||||
|
||||
case 7:
|
||||
LOG("[SCSI 7] Reset parity/interrupt");
|
||||
LOG("[7] Reset parity/interrupt");
|
||||
return 0xff;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SCSI::BusState NCR5380::target_output() {
|
||||
SCSI::BusState NCR5380::target_output() const {
|
||||
SCSI::BusState output = SCSI::DefaultBusState;
|
||||
if(target_command_ & 0x08) output |= Line::Request;
|
||||
if(target_command_ & 0x04) output |= Line::Message;
|
||||
@ -233,6 +240,14 @@ void NCR5380::update_control_output() {
|
||||
}
|
||||
|
||||
void NCR5380::scsi_bus_did_change(SCSI::Bus *, SCSI::BusState new_state, double time_since_change) {
|
||||
|
||||
/*
|
||||
When connected as an Initiator with DMA Mode True,
|
||||
if the phase lines I//O, C//D, and /MSG do not match the
|
||||
phase bits in the Target Command Register, a phase mismatch
|
||||
interrupt is generated when /REQ goes active.
|
||||
*/
|
||||
|
||||
switch(state_) {
|
||||
default: break;
|
||||
|
||||
@ -341,3 +356,10 @@ void NCR5380::dma_acknowledge(uint8_t value) {
|
||||
update_control_output();
|
||||
bus_.set_device_output(device_id_, bus_output_);
|
||||
}
|
||||
|
||||
bool NCR5380::phase_matches() const {
|
||||
const auto bus_state = bus_.get_state();
|
||||
return
|
||||
(target_output() & (Line::Message | Line::Control | Line::Input)) ==
|
||||
(bus_state & (Line::Message | Line::Control | Line::Input));
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ class NCR5380 final: public SCSI::Bus::Observer {
|
||||
bool assert_data_bus_ = false;
|
||||
bool dma_request_ = false;
|
||||
bool dma_acknowledge_ = false;
|
||||
bool end_of_dma_ = false;
|
||||
|
||||
enum class ExecutionState {
|
||||
None,
|
||||
@ -75,10 +76,11 @@ class NCR5380 final: public SCSI::Bus::Observer {
|
||||
|
||||
void set_execution_state(ExecutionState state);
|
||||
|
||||
SCSI::BusState target_output();
|
||||
SCSI::BusState target_output() const;
|
||||
void update_control_output();
|
||||
|
||||
void scsi_bus_did_change(SCSI::Bus *, SCSI::BusState new_state, double time_since_change) final;
|
||||
bool phase_matches() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user