1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-22 14:30:29 +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:
Thomas Harte 2019-08-17 23:43:42 -04:00
parent 7e001c1d03
commit 0e0c789b02
7 changed files with 164 additions and 22 deletions

View 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;
}
}

View 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 */

View File

@ -17,19 +17,27 @@ size_t Bus::add_device() {
}
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;
state_is_valid_ = false;
}
BusState Bus::get_state() {
if(!state_is_valid_) return state_;
state_is_valid_ = true;
const auto previous_state = state_;
state_ = DefaultBusState;
for(auto state: device_states_) {
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_;
}
void Bus::add_observer(Observer *observer) {
observers_.push_back(observer);
}

View File

@ -70,10 +70,18 @@ class Bus {
*/
BusState get_state();
struct Observer {
virtual void scsi_bus_did_change(Bus *, BusState new_state) = 0;
};
/*!
Adds an observer.
*/
void add_observer(Observer *);
private:
std::vector<BusState> device_states_;
BusState state_ = DefaultBusState;
bool state_is_valid_ = false;
std::vector<Observer *> observers_;
};
}

View File

@ -12,7 +12,9 @@
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();
}
@ -28,16 +30,17 @@ void NCR5380::write(int address, uint8_t value) {
LOG("[SCSI 1] Initiator command register set: " << PADHEX(2) << int(value));
initiator_command_ = value;
SCSI::BusState mask = SCSI::DefaultBusState;
if(value & 0x80) mask |= Line::Reset;
test_mode_ = value & 0x40;
bus_output_ &= ~(Line::Reset | Line::Acknowledge | Line::Busy | Line::SelectTarget | Line::Attention);
if(value & 0x80) bus_output_ |= Line::Reset;
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 */
if(value & 0x10) mask |= Line::Acknowledge;
if(value & 0x08) mask |= Line::Busy;
if(value & 0x04) mask |= Line::SelectTarget;
if(value & 0x02) mask |= Line::Attention;
test_mode_ = value & 0x40;
assert_data_bus_ = value & 0x01;
bus_output_ = (bus_output_ & ~(Line::Reset | Line::Acknowledge | Line::Busy | Line::SelectTarget | Line::Attention)) | mask;
} break;
case 2:
@ -74,9 +77,14 @@ void NCR5380::write(int address, uint8_t value) {
}
break;
case 3:
case 3: {
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:
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");
return mode_;
case 3:
case 3: {
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: {
LOG("[SCSI 4] Get current bus state");

View File

@ -12,6 +12,7 @@
#include <cstdint>
#include "SCSI.hpp"
#include "DirectAccessDevice.hpp"
#include "../../ClockReceiver/ClockReceiver.hpp"
#include "../../ClockReceiver/ClockingHintSource.hpp"
@ -52,8 +53,12 @@ class NCR5380 final: public ClockingHint::Source {
ClockingHint::Preference preferred_clocking() final;
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::DirectAccessDevice device_;
const int clock_rate_;
size_t device_id_;
SCSI::BusState bus_output_ = SCSI::DefaultBusState;

View File

@ -619,6 +619,7 @@
4BB73EAC1B587A5100552FC2 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BB73EAA1B587A5100552FC2 /* MainMenu.xib */; };
4BB73EB71B587A5100552FC2 /* AllSuiteATests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB73EB61B587A5100552FC2 /* AllSuiteATests.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 */; };
4BBB70A5202011C2002FE009 /* MultiMediaTarget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB70A3202011C2002FE009 /* MultiMediaTarget.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>"; };
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>"; };
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>"; };
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>"; };
@ -3333,6 +3336,8 @@
4BDACBEB22FFA5D20045EF7E /* ncr5380.hpp */,
4B89BCFA23024BB500EA0782 /* SCSI.cpp */,
4B89BCFB23024BB500EA0782 /* SCSI.hpp */,
4BB8F5252308E5A50015C2A6 /* DirectAccessDevice.cpp */,
4BB8F5262308E5A50015C2A6 /* DirectAccessDevice.hpp */,
);
path = 5380;
sourceTree = "<group>";
@ -4143,6 +4148,7 @@
4BCE0060227D39AB000CA200 /* Video.cpp in Sources */,
4B4518A51F75FD1C00926311 /* SSD.cpp in Sources */,
4B55CE5F1C3B7D960093A61B /* MachineDocument.swift in Sources */,
4BB8F5272308E5A50015C2A6 /* DirectAccessDevice.cpp in Sources */,
4B2B3A4C1F9B8FA70062DABF /* MemoryFuzzer.cpp in Sources */,
4B7913CC1DFCD80E00175A82 /* Video.cpp in Sources */,
4BDA00E622E699B000AC3CD0 /* CSMachine.mm in Sources */,