2019-08-18 03:43:42 +00:00
|
|
|
//
|
|
|
|
// 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."
|
|
|
|
*/
|
|
|
|
|
2019-08-19 02:39:27 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2019-08-18 19:10:07 +00:00
|
|
|
switch(phase_) {
|
|
|
|
case Phase::AwaitingSelection:
|
2019-08-18 03:43:42 +00:00
|
|
|
if(
|
|
|
|
(new_state & scsi_id_mask_) &&
|
|
|
|
((new_state & (Line::SelectTarget | Line::Busy | Line::Input)) == Line::SelectTarget)
|
|
|
|
) {
|
2019-08-19 02:39:27 +00:00
|
|
|
printf("Selected\n");
|
2019-08-18 19:10:07 +00:00
|
|
|
phase_ = Phase::Command;
|
2019-08-19 02:39:27 +00:00
|
|
|
bus_state_ |= Line::Busy; // Initiate the command phase: request a command byte.
|
2019-08-18 03:43:42 +00:00
|
|
|
bus_.set_device_output(scsi_bus_device_id_, bus_state_);
|
2019-08-19 02:39:27 +00:00
|
|
|
} else {
|
|
|
|
if(!(new_state & scsi_id_mask_)) printf("No ID mask\n");
|
|
|
|
else printf("Not SEL|~BSY|~IO");
|
2019-08-18 03:43:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2019-08-18 19:10:07 +00:00
|
|
|
case Phase::Command:
|
2019-08-19 02:39:27 +00:00
|
|
|
// Wait for select to be disabled before beginning the control phase proper.
|
|
|
|
if((new_state & Line::SelectTarget)) return;
|
|
|
|
|
|
|
|
bus_state_ |= Line::Control;
|
|
|
|
|
2019-08-18 03:43:42 +00:00
|
|
|
switch(new_state & (Line::Request | Line::Acknowledge)) {
|
2019-08-18 19:10:07 +00:00
|
|
|
// If request and acknowledge are both enabled, grab a byte and cancel the request.
|
2019-08-18 03:43:42 +00:00
|
|
|
case Line::Request | Line::Acknowledge:
|
|
|
|
bus_state_ &= ~Line::Request;
|
2019-08-19 03:15:54 +00:00
|
|
|
printf("Got %02x maybe?\n", new_state & 0xff);
|
2019-08-18 19:10:07 +00:00
|
|
|
|
|
|
|
// TODO: is the command phase over?
|
2019-08-18 03:43:42 +00:00
|
|
|
break;
|
|
|
|
|
2019-08-18 19:10:07 +00:00
|
|
|
// The reset of request has caused the initiator to reset acknowledge, so it is now
|
|
|
|
// safe to request the next byte.
|
2019-08-18 03:43:42 +00:00
|
|
|
case 0:
|
|
|
|
bus_state_ |= Line::Request;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
bus_.set_device_output(scsi_bus_device_id_, bus_state_);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|