mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Attempts to nudge the command phase further towards functioning.
This commit is contained in:
parent
8339e2044c
commit
955e909e61
@ -25,19 +25,36 @@ void DirectAccessDevice::scsi_bus_did_change(Bus *, BusState new_state) {
|
||||
time."
|
||||
*/
|
||||
|
||||
// A reset always takes precedence over anything else ongoing.
|
||||
if(new_state & Line::Reset) {
|
||||
phase_ = Phase::AwaitingSelection;
|
||||
bus_state_ = DefaultBusState;
|
||||
bus_.set_device_output(scsi_bus_device_id_, bus_state_);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(phase_) {
|
||||
case Phase::AwaitingSelection:
|
||||
if(
|
||||
(new_state & scsi_id_mask_) &&
|
||||
((new_state & (Line::SelectTarget | Line::Busy | Line::Input)) == Line::SelectTarget)
|
||||
) {
|
||||
printf("Selected\n");
|
||||
phase_ = Phase::Command;
|
||||
bus_state_ |= Line::Busy | Line::Request | Line::Control; // Initiate the command phase: request a command byte.
|
||||
bus_state_ |= Line::Busy; // Initiate the command phase: request a command byte.
|
||||
bus_.set_device_output(scsi_bus_device_id_, bus_state_);
|
||||
} else {
|
||||
if(!(new_state & scsi_id_mask_)) printf("No ID mask\n");
|
||||
else printf("Not SEL|~BSY|~IO");
|
||||
}
|
||||
break;
|
||||
|
||||
case Phase::Command:
|
||||
// Wait for select to be disabled before beginning the control phase proper.
|
||||
if((new_state & Line::SelectTarget)) return;
|
||||
|
||||
bus_state_ |= Line::Control;
|
||||
|
||||
switch(new_state & (Line::Request | Line::Acknowledge)) {
|
||||
// If request and acknowledge are both enabled, grab a byte and cancel the request.
|
||||
case Line::Request | Line::Acknowledge:
|
||||
|
@ -56,23 +56,15 @@ void NCR5380::write(int address, uint8_t value) {
|
||||
// bit 1: 1 = use DMA mode
|
||||
// bit 0: 1 = begin arbitration mode (device ID should be in register 0)
|
||||
|
||||
/*
|
||||
Arbitration is accomplished using a bus-free filter to continuously monitor BSY.
|
||||
If BSY remains inactive for at least 400 nsec then the SCSI bus is considered free
|
||||
and arbitration may begin. Arbitration will begin if the bus is free, SEL is inactive
|
||||
and the ARBITRATION bit (port 2, bit 0) is active. Once arbitration has begun
|
||||
(BSY asserted), an arbitration delay of 2.2 /Lsec must elapse before the data bus
|
||||
can be examined to deter- mine if arbitration has been won. This delay must be
|
||||
implemented in the controlling software driver.
|
||||
*/
|
||||
|
||||
if(mode_ & 1) {
|
||||
arbitration_in_progress_ = true;
|
||||
if(state_ == ExecutionState::None) {
|
||||
set_execution_state(ExecutionState::WatchingBusy);
|
||||
arbitration_in_progress_ = true;
|
||||
lost_arbitration_ = false;
|
||||
}
|
||||
} else {
|
||||
arbitration_in_progress_ = false;
|
||||
bus_output_ &= ~SCSI::Line::Busy;
|
||||
set_execution_state(ExecutionState::None);
|
||||
}
|
||||
break;
|
||||
@ -152,9 +144,8 @@ uint8_t NCR5380::read(int address) {
|
||||
}
|
||||
|
||||
case 4: {
|
||||
LOG("[SCSI 4] Get current bus state");
|
||||
const auto bus_state = bus_.get_state();
|
||||
return
|
||||
const uint8_t result =
|
||||
((bus_state & SCSI::Line::Reset) ? 0x80 : 0x00) |
|
||||
((bus_state & SCSI::Line::Busy) ? 0x40 : 0x00) |
|
||||
((bus_state & SCSI::Line::Request) ? 0x20 : 0x00) |
|
||||
@ -163,14 +154,17 @@ uint8_t NCR5380::read(int address) {
|
||||
((bus_state & SCSI::Line::Input) ? 0x04 : 0x00) |
|
||||
((bus_state & SCSI::Line::SelectTarget) ? 0x02 : 0x00) |
|
||||
((bus_state & SCSI::Line::Parity) ? 0x01 : 0x00);
|
||||
LOG("[SCSI 4] Get current bus state: " << PADHEX(2) << int(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
case 5: {
|
||||
LOG("[SCSI 5] Get bus and status");
|
||||
const auto bus_state = bus_.get_state();
|
||||
return
|
||||
const uint8_t result =
|
||||
((bus_state & SCSI::Line::Attention) ? 0x02 : 0x00) |
|
||||
((bus_state & SCSI::Line::Acknowledge) ? 0x01 : 0x00);
|
||||
LOG("[SCSI 5] Get bus and status: " << PADHEX(2) << int(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
case 6:
|
||||
@ -191,27 +185,48 @@ void NCR5380::run_for(Cycles cycles) {
|
||||
switch(state_) {
|
||||
default: break;
|
||||
|
||||
case ExecutionState::WatchingBusy:
|
||||
/*
|
||||
/*
|
||||
Official documentation:
|
||||
|
||||
Arbitration is accomplished using a bus-free filter to continuously monitor BSY.
|
||||
If BSY remains inactive for at least 400 nsec then the SCSI bus is considered free
|
||||
and arbitration may begin. Arbitration will begin if the bus is free, SEL is inactive
|
||||
and the ARBITRATION bit (port 2, bit 0) is active. Once arbitration has begun
|
||||
(BSY asserted)...
|
||||
*/
|
||||
if(bus_.get_state() & SCSI::Line::Busy) {
|
||||
lost_arbitration_ = true;
|
||||
set_execution_state(ExecutionState::None);
|
||||
}
|
||||
(BSY asserted), an arbitration delay of 2.2 /Lsec must elapse before the data bus
|
||||
can be examined to deter- mine if arbitration has been won. This delay must be
|
||||
implemented in the controlling software driver.
|
||||
|
||||
// Check for having hit the 400ns state.
|
||||
if(time_in_state_ == 400 * clock_rate_ / 1000000000) {
|
||||
arbitration_in_progress_ = false;
|
||||
Personal notes:
|
||||
|
||||
I'm discounting that "arbitratation is accomplished" opening, and assuming that what needs
|
||||
to happen is:
|
||||
|
||||
(i) wait for BSY to be inactive;
|
||||
(ii) count 400 nsec;
|
||||
(iii) check that BSY and SEL are inactive.
|
||||
*/
|
||||
|
||||
case ExecutionState::WatchingBusy:
|
||||
if(bus_.get_state() & SCSI::Line::Busy) {
|
||||
// Arbitration is lost only if a non-busy state had previously been observed.
|
||||
if(time_in_state_ > 1) {
|
||||
lost_arbitration_ = true;
|
||||
set_execution_state(ExecutionState::None);
|
||||
} else {
|
||||
time_in_state_ = 0;
|
||||
}
|
||||
} /* else {
|
||||
arbitration_in_progress_ = true;
|
||||
}*/
|
||||
|
||||
// Check for having hit 400ns (more or less) since BSY was inactive.
|
||||
if(!lost_arbitration_ && time_in_state_ == int(int64_t(400) * int64_t(clock_rate_) / int64_t(1000000000))) {
|
||||
// arbitration_in_progress_ = false;
|
||||
if(bus_.get_state() & SCSI::Line::SelectTarget) {
|
||||
lost_arbitration_ = true;
|
||||
set_execution_state(ExecutionState::None);
|
||||
} else {
|
||||
bus_output_ |= SCSI::Line::Busy;
|
||||
bus_output_ &= ~SCSI::Line::Busy;
|
||||
set_execution_state(ExecutionState::None);
|
||||
}
|
||||
}
|
||||
@ -221,6 +236,7 @@ void NCR5380::run_for(Cycles cycles) {
|
||||
|
||||
void NCR5380::set_execution_state(ExecutionState state) {
|
||||
time_in_state_ = 0;
|
||||
state_ = state;
|
||||
update_clocking_observer();
|
||||
}
|
||||
|
||||
@ -228,5 +244,5 @@ ClockingHint::Preference NCR5380::preferred_clocking() {
|
||||
// Request real-time clocking if any sort of timed bus watching is ongoing,
|
||||
// given that there's no knowledge in here as to what clocking other devices
|
||||
// on the SCSI bus might be enjoying.
|
||||
return (state_ == ExecutionState::None) ? ClockingHint::Preference::RealTime : ClockingHint::Preference::None;
|
||||
return (state_ == ExecutionState::None) ? ClockingHint::Preference::None : ClockingHint::Preference::RealTime;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user