diff --git a/Analyser/Static/Macintosh/Target.hpp b/Analyser/Static/Macintosh/Target.hpp index fd2434ca9..5d70748f0 100644 --- a/Analyser/Static/Macintosh/Target.hpp +++ b/Analyser/Static/Macintosh/Target.hpp @@ -21,7 +21,7 @@ struct Target: public ::Analyser::Static::Target { MacPlus }; - Model model = Model::Mac512ke; + Model model = Model::MacPlus; }; } diff --git a/Components/5380/ncr5380.hpp b/Components/5380/ncr5380.hpp index e01901d5a..a1630e7eb 100644 --- a/Components/5380/ncr5380.hpp +++ b/Components/5380/ncr5380.hpp @@ -12,7 +12,7 @@ #include #include "../../Storage/MassStorage/SCSI/SCSI.hpp" -#include "../../Storage/MassStorage/SCSI/Target.hpp" +#include "../../Storage/MassStorage/SCSI/DirectAccessDevice.hpp" #include "../../ClockReceiver/ClockReceiver.hpp" #include "../../ClockReceiver/ClockingHintSource.hpp" @@ -56,7 +56,7 @@ class NCR5380 final: public ClockingHint::Source { // TEMPORARY. For development expediency, the 5380 owns its own // SCSI bus and target. These will be moved out. SCSI::Bus bus_; - SCSI::Target::Target device_; + SCSI::Target::Target device_; const int clock_rate_; size_t device_id_; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 1f7d83ee1..2e815c126 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -636,6 +636,8 @@ 4BC751B21D157E61006C31D9 /* 6522Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BC751B11D157E61006C31D9 /* 6522Tests.swift */; }; 4BC76E691C98E31700E6EF73 /* FIRFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC76E671C98E31700E6EF73 /* FIRFilter.cpp */; }; 4BC76E6B1C98F43700E6EF73 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */; }; + 4BC890D3230F86020025A55A /* DirectAccessDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC890D1230F86020025A55A /* DirectAccessDevice.cpp */; }; + 4BC890D4230F86020025A55A /* DirectAccessDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC890D1230F86020025A55A /* DirectAccessDevice.cpp */; }; 4BC91B831D1F160E00884B76 /* CommodoreTAP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC91B811D1F160E00884B76 /* CommodoreTAP.cpp */; }; 4BC9DF4F1D04691600F44158 /* 6560.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC9DF4D1D04691600F44158 /* 6560.cpp */; }; 4BC9E1EE1D23449A003FCEE4 /* 6502InterruptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BC9E1ED1D23449A003FCEE4 /* 6502InterruptTests.swift */; }; @@ -1436,6 +1438,8 @@ 4BC76E671C98E31700E6EF73 /* FIRFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FIRFilter.cpp; sourceTree = ""; }; 4BC76E681C98E31700E6EF73 /* FIRFilter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FIRFilter.hpp; sourceTree = ""; }; 4BC76E6A1C98F43700E6EF73 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; + 4BC890D1230F86020025A55A /* DirectAccessDevice.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DirectAccessDevice.cpp; sourceTree = ""; }; + 4BC890D2230F86020025A55A /* DirectAccessDevice.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = DirectAccessDevice.hpp; sourceTree = ""; }; 4BC91B811D1F160E00884B76 /* CommodoreTAP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommodoreTAP.cpp; sourceTree = ""; }; 4BC91B821D1F160E00884B76 /* CommodoreTAP.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CommodoreTAP.hpp; sourceTree = ""; }; 4BC9DF441D044FCA00F44158 /* ROMImages */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ROMImages; path = ../../../../ROMImages; sourceTree = ""; }; @@ -2264,10 +2268,12 @@ 4B6AAEA5230E40250078E864 /* SCSI */ = { isa = PBXGroup; children = ( - 4B6AAEA8230E40250078E864 /* Target.cpp */, + 4BC890D1230F86020025A55A /* DirectAccessDevice.cpp */, 4B6AAEA7230E40250078E864 /* SCSI.cpp */, - 4B6AAEA6230E40250078E864 /* Target.hpp */, + 4B6AAEA8230E40250078E864 /* Target.cpp */, + 4BC890D2230F86020025A55A /* DirectAccessDevice.hpp */, 4B6AAEA9230E40250078E864 /* SCSI.hpp */, + 4B6AAEA6230E40250078E864 /* Target.hpp */, 4B6AAEAA230E40250078E864 /* TargetImplementation.hpp */, ); path = SCSI; @@ -4005,6 +4011,7 @@ 4B055AEE1FAE9BBF0060FFFF /* Keyboard.cpp in Sources */, 4B055AED1FAE9BA20060FFFF /* Z80Storage.cpp in Sources */, 4B1B88BC202E2EC100B67DFF /* MultiKeyboardMachine.cpp in Sources */, + 4BC890D4230F86020025A55A /* DirectAccessDevice.cpp in Sources */, 4B6AAEAE230E40250078E864 /* Target.cpp in Sources */, 4BF437EF209D0F7E008CBD6B /* SegmentParser.cpp in Sources */, 4B055AD11FAE9B030060FFFF /* Video.cpp in Sources */, @@ -4161,6 +4168,7 @@ 4B6AAEA4230E3E1D0078E864 /* MassStorageDevice.cpp in Sources */, 4B89452E201967B4007DE474 /* StaticAnalyser.cpp in Sources */, 4BD5D2682199148100DDF17D /* ScanTargetGLSLFragments.cpp in Sources */, + 4BC890D3230F86020025A55A /* DirectAccessDevice.cpp in Sources */, 4B38F3481F2EC11D00D9235D /* AmstradCPC.cpp in Sources */, 4B8FE2221DA19FB20090D3CE /* MachinePanel.swift in Sources */, 4B4518A41F75FD1C00926311 /* OricMFMDSK.cpp in Sources */, diff --git a/Storage/MassStorage/SCSI/DirectAccessDevice.cpp b/Storage/MassStorage/SCSI/DirectAccessDevice.cpp new file mode 100644 index 000000000..88b0f9456 --- /dev/null +++ b/Storage/MassStorage/SCSI/DirectAccessDevice.cpp @@ -0,0 +1,21 @@ +// +// DirectAccessDevice.cpp +// Clock Signal +// +// Created by Thomas Harte on 22/08/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#include "DirectAccessDevice.hpp" + +using namespace SCSI; + +bool DirectAccessDevice::read(const Target::CommandState &state, Target::Responder &responder) { + std::vector data(512); + + responder.send_data(std::move(data), [] (const Target::CommandState &state, Target::Responder &responder) { + responder.end_command(); + }); + + return true; +} diff --git a/Storage/MassStorage/SCSI/DirectAccessDevice.hpp b/Storage/MassStorage/SCSI/DirectAccessDevice.hpp new file mode 100644 index 000000000..72915acb9 --- /dev/null +++ b/Storage/MassStorage/SCSI/DirectAccessDevice.hpp @@ -0,0 +1,23 @@ +// +// DirectAccessDevice.hpp +// Clock Signal +// +// Created by Thomas Harte on 22/08/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#ifndef SCSI_DirectAccessDevice_hpp +#define SCSI_DirectAccessDevice_hpp + +#include "Target.hpp" + +namespace SCSI { + +class DirectAccessDevice: public Target::Executor { + public: + bool read(const Target::CommandState &, Target::Responder &); +}; + +} + +#endif /* SCSI_DirectAccessDevice_hpp */ diff --git a/Storage/MassStorage/SCSI/Target.hpp b/Storage/MassStorage/SCSI/Target.hpp index b88ebc592..150b8d162 100644 --- a/Storage/MassStorage/SCSI/Target.hpp +++ b/Storage/MassStorage/SCSI/Target.hpp @@ -1,13 +1,13 @@ // -// DirectAccessDevice.hpp +// Target.hpp // Clock Signal // // Created by Thomas Harte on 17/08/2019. // Copyright © 2019 Thomas Harte. All rights reserved. // -#ifndef DirectAccessDevice_hpp -#define DirectAccessDevice_hpp +#ifndef SCSI_Target_hpp +#define SCSI_Target_hpp #include "SCSI.hpp" @@ -154,7 +154,11 @@ template class Target: public Bus::Observer, public Responde enum class Phase { AwaitingSelection, - Command + Command, + ReceivingData, + SendingData, + SendingStatus, + SendingMessage } phase_ = Phase::AwaitingSelection; BusState bus_state_ = DefaultBusState; @@ -162,6 +166,11 @@ template class Target: public Bus::Observer, public Responde std::vector command_; size_t command_pointer_ = 0; bool dispatch_command(); + + std::vector data_; + size_t data_pointer_ = 0; + + continuation next_function_; }; #import "TargetImplementation.hpp" @@ -169,4 +178,4 @@ template class Target: public Bus::Observer, public Responde } } -#endif /* DirectAccessDevice_hpp */ +#endif /* SCSI_Target_hpp */ diff --git a/Storage/MassStorage/SCSI/TargetImplementation.hpp b/Storage/MassStorage/SCSI/TargetImplementation.hpp index ca8ac0717..50024ec68 100644 --- a/Storage/MassStorage/SCSI/TargetImplementation.hpp +++ b/Storage/MassStorage/SCSI/TargetImplementation.hpp @@ -35,13 +35,9 @@ template void Target::scsi_bus_did_change(Bus *, B (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; // 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; @@ -81,6 +77,42 @@ template void Target::scsi_bus_did_change(Bus *, B } bus_.set_device_output(scsi_bus_device_id_, bus_state_); break; + + case Phase::ReceivingData: + switch(new_state & (Line::Request | Line::Acknowledge)) { + case Line::Request | Line::Acknowledge: + bus_state_ &= ~Line::Request; + + data_[data_pointer_] = uint8_t(new_state); + ++data_pointer_; + if(data_pointer_ == data_.size()) { + next_function_(CommandState(command_), *this); + } + break; + + case 0: + bus_state_ |= Line::Request; + break; + } + break; + + case Phase::SendingData: + switch(new_state & (Line::Request | Line::Acknowledge)) { + case Line::Request | Line::Acknowledge: + bus_state_ &= ~(Line::Request | 0xff); + + ++data_pointer_; + if(data_pointer_ == data_.size()) { + next_function_(CommandState(command_), *this); + } + break; + + case 0: + bus_state_ |= Line::Request; + bus_state_ = (bus_state_ & ~0xff) | data_[data_pointer_]; + break; + } + break; } } @@ -143,8 +175,46 @@ template bool Target::dispatch_command() { return false; } -template void Target::send_data(std::vector &&data, continuation next) {} -template void Target::receive_data(size_t length, continuation next) {} -template void Target::send_status(Status, continuation next) {} -template void Target::send_message(Message, continuation next) {} -template void Target::end_command() {} +template void Target::send_data(std::vector &&data, continuation next) { + // Data out phase: control and message all reset, input set. + bus_state_ &= ~(Line::Control | Line::Input | Line::Message); + bus_state_ |= Line::Input; + phase_ = Phase::SendingData; + data_ = std::move(data); + data_pointer_ = 0; + bus_.set_device_output(scsi_bus_device_id_, bus_state_); +} + +template void Target::receive_data(size_t length, continuation next) { + // Data out phase: control, input and message all reset. + bus_state_ &= ~(Line::Control | Line::Input | Line::Message); + phase_ = Phase::ReceivingData; + data_.resize(length); + data_pointer_ = 0; + bus_.set_device_output(scsi_bus_device_id_, bus_state_); +} + +template void Target::send_status(Status, continuation next) { + // Status phase: message reset, control and input set. + bus_state_ &= ~(Line::Control | Line::Input | Line::Message); + bus_state_ |= Line::Input | Line::Control; + phase_ = Phase::SendingStatus; + bus_.set_device_output(scsi_bus_device_id_, bus_state_); +} + +template void Target::send_message(Message, continuation next) { + // Message out phase: message and control set, input reset. + bus_state_ &= ~(Line::Control | Line::Input | Line::Message); + bus_state_ |= Line::Message | Line::Control; + phase_ = Phase::SendingMessage; + bus_.set_device_output(scsi_bus_device_id_, bus_state_); +} + +template void Target::end_command() { + // TODO: was this a linked command? + + // Release all bus lines and return to awaiting selection. + phase_ = Phase::AwaitingSelection; + bus_state_ = DefaultBusState; + bus_.set_device_output(scsi_bus_device_id_, bus_state_); +}