mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 05:29:23 +00:00
Starts attempting to introduce a direct access device.
Without having access to the SCSI-1 standard, a lot of this is guesswork.
This commit is contained in:
parent
7e001c1d03
commit
0e0c789b02
57
Components/5380/DirectAccessDevice.cpp
Normal file
57
Components/5380/DirectAccessDevice.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// DirectAccessDevice.cpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 17/08/2019.
|
||||||
|
// Copyright © 2019 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "DirectAccessDevice.hpp"
|
||||||
|
|
||||||
|
using namespace SCSI;
|
||||||
|
|
||||||
|
DirectAccessDevice::DirectAccessDevice(Bus &bus, int scsi_id) :
|
||||||
|
bus_(bus),
|
||||||
|
scsi_id_mask_(BusState(1 << scsi_id)),
|
||||||
|
scsi_bus_device_id_(bus.add_device()) {
|
||||||
|
bus.add_observer(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectAccessDevice::scsi_bus_did_change(Bus *, BusState new_state) {
|
||||||
|
/*
|
||||||
|
"The target determines that it is selected when the SEL# signal
|
||||||
|
and its SCSI ID bit are active and the BSY# and I#/O signals
|
||||||
|
are false. It then asserts the signal within a selection abort
|
||||||
|
time."
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch(state_) {
|
||||||
|
case State::Inactive:
|
||||||
|
if(
|
||||||
|
(new_state & scsi_id_mask_) &&
|
||||||
|
((new_state & (Line::SelectTarget | Line::Busy | Line::Input)) == Line::SelectTarget)
|
||||||
|
) {
|
||||||
|
state_ = State::Selected;
|
||||||
|
bus_state_ |= Line::Busy | Line::Request;
|
||||||
|
bus_.set_device_output(scsi_bus_device_id_, bus_state_);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case State::Selected:
|
||||||
|
switch(new_state & (Line::Request | Line::Acknowledge)) {
|
||||||
|
case Line::Request | Line::Acknowledge:
|
||||||
|
bus_state_ &= ~Line::Request;
|
||||||
|
printf("Got %02x maybe?\n", bus_state_ & 0xff);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Line::Acknowledge:
|
||||||
|
case 0:
|
||||||
|
bus_state_ |= Line::Request;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
bus_.set_device_output(scsi_bus_device_id_, bus_state_);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
44
Components/5380/DirectAccessDevice.hpp
Normal file
44
Components/5380/DirectAccessDevice.hpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// DirectAccessDevice.hpp
|
||||||
|
// Clock Signal
|
||||||
|
//
|
||||||
|
// Created by Thomas Harte on 17/08/2019.
|
||||||
|
// Copyright © 2019 Thomas Harte. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef DirectAccessDevice_hpp
|
||||||
|
#define DirectAccessDevice_hpp
|
||||||
|
|
||||||
|
#include "SCSI.hpp"
|
||||||
|
|
||||||
|
namespace SCSI {
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Models a SCSI direct access device, ordinarily some sort of
|
||||||
|
hard drive.
|
||||||
|
*/
|
||||||
|
class DirectAccessDevice: public Bus::Observer {
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
Instantiates a direct access device attached to @c bus,
|
||||||
|
with SCSI ID @c scsi_id — a number in the range 0 to 7.
|
||||||
|
*/
|
||||||
|
DirectAccessDevice(Bus &bus, int scsi_id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void scsi_bus_did_change(Bus *, BusState new_state) final;
|
||||||
|
|
||||||
|
Bus &bus_;
|
||||||
|
const BusState scsi_id_mask_;
|
||||||
|
const size_t scsi_bus_device_id_;
|
||||||
|
|
||||||
|
enum class State {
|
||||||
|
Inactive,
|
||||||
|
Selected
|
||||||
|
} state_ = State::Inactive;
|
||||||
|
BusState bus_state_ = DefaultBusState;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DirectAccessDevice_hpp */
|
@ -17,19 +17,27 @@ size_t Bus::add_device() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Bus::set_device_output(size_t device, BusState output) {
|
void Bus::set_device_output(size_t device, BusState output) {
|
||||||
printf("%08x output\n", output);
|
if(device_states_[device] == output) return;
|
||||||
device_states_[device] = output;
|
device_states_[device] = output;
|
||||||
state_is_valid_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BusState Bus::get_state() {
|
const auto previous_state = state_;
|
||||||
if(!state_is_valid_) return state_;
|
|
||||||
|
|
||||||
state_is_valid_ = true;
|
|
||||||
state_ = DefaultBusState;
|
state_ = DefaultBusState;
|
||||||
for(auto state: device_states_) {
|
for(auto state: device_states_) {
|
||||||
state_ |= state;
|
state_ |= state;
|
||||||
}
|
}
|
||||||
|
if(state_ == previous_state) return;
|
||||||
|
|
||||||
|
printf("SCSI bus: %08x\n", state_);
|
||||||
|
|
||||||
|
for(auto &observer: observers_) {
|
||||||
|
observer->scsi_bus_did_change(this, state_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BusState Bus::get_state() {
|
||||||
return state_;
|
return state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bus::add_observer(Observer *observer) {
|
||||||
|
observers_.push_back(observer);
|
||||||
|
}
|
||||||
|
@ -70,10 +70,18 @@ class Bus {
|
|||||||
*/
|
*/
|
||||||
BusState get_state();
|
BusState get_state();
|
||||||
|
|
||||||
|
struct Observer {
|
||||||
|
virtual void scsi_bus_did_change(Bus *, BusState new_state) = 0;
|
||||||
|
};
|
||||||
|
/*!
|
||||||
|
Adds an observer.
|
||||||
|
*/
|
||||||
|
void add_observer(Observer *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<BusState> device_states_;
|
std::vector<BusState> device_states_;
|
||||||
BusState state_ = DefaultBusState;
|
BusState state_ = DefaultBusState;
|
||||||
bool state_is_valid_ = false;
|
std::vector<Observer *> observers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,9 @@
|
|||||||
|
|
||||||
using namespace NCR::NCR5380;
|
using namespace NCR::NCR5380;
|
||||||
|
|
||||||
NCR5380::NCR5380(int clock_rate) : clock_rate_(clock_rate) {
|
NCR5380::NCR5380(int clock_rate) :
|
||||||
|
device_(bus_, 6),
|
||||||
|
clock_rate_(clock_rate) {
|
||||||
device_id_ = bus_.add_device();
|
device_id_ = bus_.add_device();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,16 +30,17 @@ void NCR5380::write(int address, uint8_t value) {
|
|||||||
LOG("[SCSI 1] Initiator command register set: " << PADHEX(2) << int(value));
|
LOG("[SCSI 1] Initiator command register set: " << PADHEX(2) << int(value));
|
||||||
initiator_command_ = value;
|
initiator_command_ = value;
|
||||||
|
|
||||||
SCSI::BusState mask = SCSI::DefaultBusState;
|
bus_output_ &= ~(Line::Reset | Line::Acknowledge | Line::Busy | Line::SelectTarget | Line::Attention);
|
||||||
if(value & 0x80) mask |= Line::Reset;
|
if(value & 0x80) bus_output_ |= Line::Reset;
|
||||||
test_mode_ = value & 0x40;
|
if(value & 0x10) bus_output_ |= Line::Acknowledge;
|
||||||
|
if(value & 0x08) bus_output_ |= Line::Busy;
|
||||||
|
if(value & 0x04) bus_output_ |= Line::SelectTarget;
|
||||||
|
if(value & 0x02) bus_output_ |= Line::Attention;
|
||||||
|
|
||||||
/* bit 5 = differential enable if this were a 5381 */
|
/* bit 5 = differential enable if this were a 5381 */
|
||||||
if(value & 0x10) mask |= Line::Acknowledge;
|
|
||||||
if(value & 0x08) mask |= Line::Busy;
|
test_mode_ = value & 0x40;
|
||||||
if(value & 0x04) mask |= Line::SelectTarget;
|
|
||||||
if(value & 0x02) mask |= Line::Attention;
|
|
||||||
assert_data_bus_ = value & 0x01;
|
assert_data_bus_ = value & 0x01;
|
||||||
bus_output_ = (bus_output_ & ~(Line::Reset | Line::Acknowledge | Line::Busy | Line::SelectTarget | Line::Attention)) | mask;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
@ -74,9 +77,14 @@ void NCR5380::write(int address, uint8_t value) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3: {
|
||||||
LOG("[SCSI 3] Set target command: " << PADHEX(2) << int(value));
|
LOG("[SCSI 3] Set target command: " << PADHEX(2) << int(value));
|
||||||
break;
|
bus_output_ &= ~(Line::Request | Line::Message | Line::Control | Line::Input);
|
||||||
|
if(value & 0x08) bus_output_ |= Line::Request;
|
||||||
|
if(value & 0x04) bus_output_ |= Line::Message;
|
||||||
|
if(value & 0x02) bus_output_ |= Line::Control;
|
||||||
|
if(value & 0x01) bus_output_ |= Line::Input;
|
||||||
|
} break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
LOG("[SCSI 4] Set select enabled: " << PADHEX(2) << int(value));
|
LOG("[SCSI 4] Set select enabled: " << PADHEX(2) << int(value));
|
||||||
@ -133,9 +141,15 @@ uint8_t NCR5380::read(int address) {
|
|||||||
LOG("[SCSI 2] Get mode");
|
LOG("[SCSI 2] Get mode");
|
||||||
return mode_;
|
return mode_;
|
||||||
|
|
||||||
case 3:
|
case 3: {
|
||||||
LOG("[SCSI 3] Get target command");
|
LOG("[SCSI 3] Get target command");
|
||||||
return 0xff;
|
const auto bus_state = bus_.get_state();
|
||||||
|
return
|
||||||
|
((bus_state & SCSI::Line::Request) ? 0x08 : 0x00) |
|
||||||
|
((bus_state & SCSI::Line::Message) ? 0x04 : 0x00) |
|
||||||
|
((bus_state & SCSI::Line::Control) ? 0x02 : 0x00) |
|
||||||
|
((bus_state & SCSI::Line::Input) ? 0x01 : 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
case 4: {
|
case 4: {
|
||||||
LOG("[SCSI 4] Get current bus state");
|
LOG("[SCSI 4] Get current bus state");
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "SCSI.hpp"
|
#include "SCSI.hpp"
|
||||||
|
#include "DirectAccessDevice.hpp"
|
||||||
#include "../../ClockReceiver/ClockReceiver.hpp"
|
#include "../../ClockReceiver/ClockReceiver.hpp"
|
||||||
#include "../../ClockReceiver/ClockingHintSource.hpp"
|
#include "../../ClockReceiver/ClockingHintSource.hpp"
|
||||||
|
|
||||||
@ -52,8 +53,12 @@ class NCR5380 final: public ClockingHint::Source {
|
|||||||
ClockingHint::Preference preferred_clocking() final;
|
ClockingHint::Preference preferred_clocking() final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const int clock_rate_;
|
// TEMPORARY. For development expediency, the 5380 owns its own
|
||||||
|
// SCSI bus and direct access device. These will be moved out.
|
||||||
SCSI::Bus bus_;
|
SCSI::Bus bus_;
|
||||||
|
SCSI::DirectAccessDevice device_;
|
||||||
|
|
||||||
|
const int clock_rate_;
|
||||||
size_t device_id_;
|
size_t device_id_;
|
||||||
|
|
||||||
SCSI::BusState bus_output_ = SCSI::DefaultBusState;
|
SCSI::BusState bus_output_ = SCSI::DefaultBusState;
|
||||||
|
@ -619,6 +619,7 @@
|
|||||||
4BB73EAC1B587A5100552FC2 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BB73EAA1B587A5100552FC2 /* MainMenu.xib */; };
|
4BB73EAC1B587A5100552FC2 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BB73EAA1B587A5100552FC2 /* MainMenu.xib */; };
|
||||||
4BB73EB71B587A5100552FC2 /* AllSuiteATests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EB61B587A5100552FC2 /* AllSuiteATests.swift */; };
|
4BB73EB71B587A5100552FC2 /* AllSuiteATests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EB61B587A5100552FC2 /* AllSuiteATests.swift */; };
|
||||||
4BB73EC21B587A5100552FC2 /* Clock_SignalUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EC11B587A5100552FC2 /* Clock_SignalUITests.swift */; };
|
4BB73EC21B587A5100552FC2 /* Clock_SignalUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EC11B587A5100552FC2 /* Clock_SignalUITests.swift */; };
|
||||||
|
4BB8F5272308E5A50015C2A6 /* DirectAccessDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB8F5252308E5A50015C2A6 /* DirectAccessDevice.cpp */; };
|
||||||
4BBB70A4202011C2002FE009 /* MultiMediaTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A3202011C2002FE009 /* MultiMediaTarget.cpp */; };
|
4BBB70A4202011C2002FE009 /* MultiMediaTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A3202011C2002FE009 /* MultiMediaTarget.cpp */; };
|
||||||
4BBB70A5202011C2002FE009 /* MultiMediaTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A3202011C2002FE009 /* MultiMediaTarget.cpp */; };
|
4BBB70A5202011C2002FE009 /* MultiMediaTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A3202011C2002FE009 /* MultiMediaTarget.cpp */; };
|
||||||
4BBB70A8202014E2002FE009 /* MultiCRTMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A6202014E2002FE009 /* MultiCRTMachine.cpp */; };
|
4BBB70A8202014E2002FE009 /* MultiCRTMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A6202014E2002FE009 /* MultiCRTMachine.cpp */; };
|
||||||
@ -1407,6 +1408,8 @@
|
|||||||
4BB73EC11B587A5100552FC2 /* Clock_SignalUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clock_SignalUITests.swift; sourceTree = "<group>"; };
|
4BB73EC11B587A5100552FC2 /* Clock_SignalUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clock_SignalUITests.swift; sourceTree = "<group>"; };
|
||||||
4BB73EC31B587A5100552FC2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
4BB73EC31B587A5100552FC2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
4BB73ECF1B587A6700552FC2 /* Clock Signal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Clock Signal.entitlements"; sourceTree = "<group>"; };
|
4BB73ECF1B587A6700552FC2 /* Clock Signal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Clock Signal.entitlements"; sourceTree = "<group>"; };
|
||||||
|
4BB8F5252308E5A50015C2A6 /* DirectAccessDevice.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DirectAccessDevice.cpp; sourceTree = "<group>"; };
|
||||||
|
4BB8F5262308E5A50015C2A6 /* DirectAccessDevice.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DirectAccessDevice.hpp; sourceTree = "<group>"; };
|
||||||
4BBB709C2020109C002FE009 /* DynamicMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DynamicMachine.hpp; sourceTree = "<group>"; };
|
4BBB709C2020109C002FE009 /* DynamicMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DynamicMachine.hpp; sourceTree = "<group>"; };
|
||||||
4BBB70A2202011C2002FE009 /* MultiMediaTarget.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MultiMediaTarget.hpp; sourceTree = "<group>"; };
|
4BBB70A2202011C2002FE009 /* MultiMediaTarget.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MultiMediaTarget.hpp; sourceTree = "<group>"; };
|
||||||
4BBB70A3202011C2002FE009 /* MultiMediaTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MultiMediaTarget.cpp; sourceTree = "<group>"; };
|
4BBB70A3202011C2002FE009 /* MultiMediaTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MultiMediaTarget.cpp; sourceTree = "<group>"; };
|
||||||
@ -3333,6 +3336,8 @@
|
|||||||
4BDACBEB22FFA5D20045EF7E /* ncr5380.hpp */,
|
4BDACBEB22FFA5D20045EF7E /* ncr5380.hpp */,
|
||||||
4B89BCFA23024BB500EA0782 /* SCSI.cpp */,
|
4B89BCFA23024BB500EA0782 /* SCSI.cpp */,
|
||||||
4B89BCFB23024BB500EA0782 /* SCSI.hpp */,
|
4B89BCFB23024BB500EA0782 /* SCSI.hpp */,
|
||||||
|
4BB8F5252308E5A50015C2A6 /* DirectAccessDevice.cpp */,
|
||||||
|
4BB8F5262308E5A50015C2A6 /* DirectAccessDevice.hpp */,
|
||||||
);
|
);
|
||||||
path = 5380;
|
path = 5380;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -4143,6 +4148,7 @@
|
|||||||
4BCE0060227D39AB000CA200 /* Video.cpp in Sources */,
|
4BCE0060227D39AB000CA200 /* Video.cpp in Sources */,
|
||||||
4B4518A51F75FD1C00926311 /* SSD.cpp in Sources */,
|
4B4518A51F75FD1C00926311 /* SSD.cpp in Sources */,
|
||||||
4B55CE5F1C3B7D960093A61B /* MachineDocument.swift in Sources */,
|
4B55CE5F1C3B7D960093A61B /* MachineDocument.swift in Sources */,
|
||||||
|
4BB8F5272308E5A50015C2A6 /* DirectAccessDevice.cpp in Sources */,
|
||||||
4B2B3A4C1F9B8FA70062DABF /* MemoryFuzzer.cpp in Sources */,
|
4B2B3A4C1F9B8FA70062DABF /* MemoryFuzzer.cpp in Sources */,
|
||||||
4B7913CC1DFCD80E00175A82 /* Video.cpp in Sources */,
|
4B7913CC1DFCD80E00175A82 /* Video.cpp in Sources */,
|
||||||
4BDA00E622E699B000AC3CD0 /* CSMachine.mm in Sources */,
|
4BDA00E622E699B000AC3CD0 /* CSMachine.mm in Sources */,
|
||||||
|
Loading…
Reference in New Issue
Block a user