mirror of
https://github.com/thewesker/RASCSI.git
synced 2025-12-22 05:11:15 -05:00
Added arbitration and reselection logic. Seems to work. Also removed some conditional code for non-RASCSI applications
This commit is contained in:
@@ -707,10 +707,7 @@ void FASTCALL SASIDEV::MsgIn()
|
|||||||
|
|
||||||
// Phase change
|
// Phase change
|
||||||
if (ctrl.phase != BUS::msgin) {
|
if (ctrl.phase != BUS::msgin) {
|
||||||
|
LOGTRACE("%s Starting Message in phase", __PRETTY_FUNCTION__);
|
||||||
#if defined(DISK_LOG)
|
|
||||||
Log(Log::Normal, "Message in phase");
|
|
||||||
#endif // DISK_LOG
|
|
||||||
|
|
||||||
// Phase Setting
|
// Phase Setting
|
||||||
ctrl.phase = BUS::msgin;
|
ctrl.phase = BUS::msgin;
|
||||||
@@ -724,36 +721,12 @@ void FASTCALL SASIDEV::MsgIn()
|
|||||||
ASSERT(ctrl.length > 0);
|
ASSERT(ctrl.length > 0);
|
||||||
ASSERT(ctrl.blocks > 0);
|
ASSERT(ctrl.blocks > 0);
|
||||||
ctrl.offset = 0;
|
ctrl.offset = 0;
|
||||||
|
|
||||||
#ifndef RASCSI
|
|
||||||
// Request message
|
|
||||||
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
|
|
||||||
ctrl.bus->SetREQ(TRUE);
|
|
||||||
|
|
||||||
#if defined(DISK_LOG)
|
|
||||||
Log(Log::Normal, "Message in phase $%02X", ctrl.buffer[ctrl.offset]);
|
|
||||||
#endif // DISK_LOG
|
|
||||||
#endif // RASCSI
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RASCSI
|
|
||||||
//Send
|
//Send
|
||||||
|
LOGTRACE("%s Transitioning to Send()", __PRETTY_FUNCTION__);
|
||||||
Send();
|
Send();
|
||||||
#else
|
|
||||||
// Requesting
|
|
||||||
if (ctrl.bus->GetREQ()) {
|
|
||||||
// Initator received
|
|
||||||
if (ctrl.bus->GetACK()) {
|
|
||||||
SendNext();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Initiator requests next
|
|
||||||
if (!ctrl.bus->GetACK()) {
|
|
||||||
Send();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // RASCSI
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -792,10 +765,7 @@ void FASTCALL SASIDEV::DataIn()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DISK_LOG)
|
LOGTRACE("%s Going into Data-in Phase", __PRETTY_FUNCTION__);
|
||||||
Log(Log::Normal, "Data-in Phase");
|
|
||||||
#endif // DISK_LOG
|
|
||||||
|
|
||||||
// Phase Setting
|
// Phase Setting
|
||||||
ctrl.phase = BUS::datain;
|
ctrl.phase = BUS::datain;
|
||||||
|
|
||||||
@@ -809,33 +779,12 @@ void FASTCALL SASIDEV::DataIn()
|
|||||||
ASSERT(ctrl.blocks > 0);
|
ASSERT(ctrl.blocks > 0);
|
||||||
ctrl.offset = 0;
|
ctrl.offset = 0;
|
||||||
|
|
||||||
#ifndef RASCSI
|
|
||||||
// Assert the DAT signal
|
|
||||||
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
|
|
||||||
|
|
||||||
// Request data
|
|
||||||
ctrl.bus->SetREQ(TRUE);
|
|
||||||
#endif // RASCSI
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RASCSI
|
|
||||||
// Send
|
// Send
|
||||||
|
LOGTRACE("%s Going to Send()",__PRETTY_FUNCTION__);
|
||||||
Send();
|
Send();
|
||||||
#else
|
|
||||||
// Requesting
|
|
||||||
if (ctrl.bus->GetREQ()) {
|
|
||||||
// Initator received
|
|
||||||
if (ctrl.bus->GetACK()) {
|
|
||||||
SendNext();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Initiator requests next
|
|
||||||
if (!ctrl.bus->GetACK()) {
|
|
||||||
Send();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // RASCSI
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -1394,7 +1343,6 @@ void FASTCALL SASIDEV::Send()
|
|||||||
ASSERT(!ctrl.bus->GetREQ());
|
ASSERT(!ctrl.bus->GetREQ());
|
||||||
ASSERT(ctrl.bus->GetIO());
|
ASSERT(ctrl.bus->GetIO());
|
||||||
|
|
||||||
#ifdef RASCSI
|
|
||||||
// Check that the length isn't 0
|
// Check that the length isn't 0
|
||||||
if (ctrl.length != 0) {
|
if (ctrl.length != 0) {
|
||||||
len = ctrl.bus->SendHandShake(
|
len = ctrl.bus->SendHandShake(
|
||||||
@@ -1411,20 +1359,6 @@ void FASTCALL SASIDEV::Send()
|
|||||||
ctrl.length = 0;
|
ctrl.length = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
// Offset and Length
|
|
||||||
ASSERT(ctrl.length >= 1);
|
|
||||||
ctrl.offset++;
|
|
||||||
ctrl.length--;
|
|
||||||
|
|
||||||
// Immediately after ACK is asserted, if the data
|
|
||||||
// has been set by SendNext, raise the request
|
|
||||||
if (ctrl.length != 0) {
|
|
||||||
// Signal line operated by the target
|
|
||||||
ctrl.bus->SetREQ(TRUE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif // RASCSI
|
|
||||||
|
|
||||||
// Remove block and initialize the result
|
// Remove block and initialize the result
|
||||||
ctrl.blocks--;
|
ctrl.blocks--;
|
||||||
@@ -1435,7 +1369,7 @@ void FASTCALL SASIDEV::Send()
|
|||||||
if (ctrl.blocks != 0) {
|
if (ctrl.blocks != 0) {
|
||||||
// Set next buffer (set offset, length)
|
// Set next buffer (set offset, length)
|
||||||
result = XferIn(ctrl.buffer);
|
result = XferIn(ctrl.buffer);
|
||||||
//** printf("xfer in: %d \n",result);
|
LOGTRACE("%s xfer in: %d",__PRETTY_FUNCTION__, result);
|
||||||
|
|
||||||
#ifndef RASCSI
|
#ifndef RASCSI
|
||||||
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
|
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);
|
||||||
|
|||||||
@@ -197,44 +197,56 @@ void FASTCALL SCSIDEV::BusFree()
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void FASTCALL SCSIDEV::Arbitration()
|
void FASTCALL SCSIDEV::Arbitration()
|
||||||
{
|
{
|
||||||
|
|
||||||
// TODO: See https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-06.html
|
// TODO: See https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-06.html
|
||||||
// DWORD id;
|
DWORD id;
|
||||||
|
DWORD data_lines;
|
||||||
|
|
||||||
ASSERT(this);
|
ASSERT(this);
|
||||||
|
|
||||||
// // Phase change
|
// We need to switch the tranceivers to be inputs....
|
||||||
// if (ctrl.phase != BUS::reselection) {
|
ctrl.bus->SetBSY(FALSE); // Make sure that we're not asserting the BSY signal
|
||||||
// // invalid if IDs do not match
|
ctrl.bus->SetSEL(FALSE); // Make sure that we're not asserting the SEL signal
|
||||||
// id = 1 << ctrl.id;
|
|
||||||
// if ((ctrl.bus->GetDAT() & id) == 0) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // End if there is no valid unit
|
// If we arent' in the bus-free phase, we can't progress....
|
||||||
// if (!HasUnit()) {
|
// just return.
|
||||||
// return;
|
ctrl.bus->Aquire();
|
||||||
// }
|
if(ctrl.bus->GetBSY() || ctrl.bus->GetSEL())
|
||||||
|
{
|
||||||
|
LOGWARN("Unable to start arbitration. BSY:%d SEL:%d",(int)ctrl.bus->GetBSY(), (int)ctrl.bus->GetSEL());
|
||||||
|
}
|
||||||
|
|
||||||
// LOGDEBUG("Reselection phase ID=%d (with device)", ctrl.id);
|
// Phase change
|
||||||
|
if (ctrl.phase != BUS::arbitration) {
|
||||||
|
|
||||||
// // Phase setting
|
ctrl.phase = BUS::arbitration;
|
||||||
// ctrl.phase = BUS::selection;
|
|
||||||
|
|
||||||
// // Raise BSY and respond
|
// Assert both the BSY signal and our own SCSI ID
|
||||||
// ctrl.bus->SetBSY(TRUE);
|
id = 1 << ctrl.id;
|
||||||
// return;
|
ctrl.bus->SetDAT(id);
|
||||||
// }
|
ctrl.bus->SetBSY(TRUE);
|
||||||
|
|
||||||
// // Reselection completed
|
// Wait for an ARBITRATION DELAY
|
||||||
// if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) {
|
SysTimer::SleepNsec(SCSI_DELAY_ARBITRATION_DELAY_NS);
|
||||||
// // Message out phase if ATN=1, otherwise command phase
|
|
||||||
// if (ctrl.bus->GetATN()) {
|
// Check if a higher SCSI ID is asserted. If so, we lost arbitration
|
||||||
// MsgOut();
|
ctrl.bus->Aquire();
|
||||||
// } else {
|
data_lines = ctrl.bus->GetDAT();
|
||||||
// Command();
|
LOGDEBUG("After Arbitration, data lines are %04X", (int)data_lines);
|
||||||
// }
|
data_lines >>= (ctrl.id + 1);
|
||||||
// }
|
if(data_lines != 0)
|
||||||
|
{
|
||||||
|
LOGINFO("We LOST arbitration for ID %d", ctrl.id);
|
||||||
|
BusFree();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we won the arbitration, assert the SEL signal
|
||||||
|
ctrl.bus->SetSEL(TRUE);
|
||||||
|
|
||||||
|
// Wait for BUS CLEAR delay + BUS SETTLE delay before changing any signals
|
||||||
|
SysTimer::SleepNsec(SCSI_DELAY_BUS_CLEAR_DELAY_NS + SCSI_DELAY_BUS_SETTLE_DELAY_NS);
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -292,42 +304,66 @@ void FASTCALL SCSIDEV::Selection()
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void FASTCALL SCSIDEV::Reselection()
|
void FASTCALL SCSIDEV::Reselection()
|
||||||
{
|
{
|
||||||
// DWORD id;
|
DWORD id;
|
||||||
|
|
||||||
ASSERT(this);
|
ASSERT(this);
|
||||||
|
|
||||||
// // Phase change
|
// Phase change
|
||||||
// if (ctrl.phase != BUS::reselection) {
|
if (ctrl.phase != BUS::reselection) {
|
||||||
// // invalid if IDs do not match
|
ctrl.phase = BUS::reselection;
|
||||||
// id = 1 << ctrl.id;
|
|
||||||
// if ((ctrl.bus->GetDAT() & id) == 0) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // End if there is no valid unit
|
// Assert the IO signal
|
||||||
// if (!HasUnit()) {
|
ctrl.bus->SetIO(TRUE);
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// LOGDEBUG("Reselection phase ID=%d (with device)", ctrl.id);
|
// Set the data bus to my SCSI ID or-ed with the Initiator's SCSI ID
|
||||||
|
// Assume this is 7, since that is what all Macintoshes use
|
||||||
|
id = (1 << ctrl.id) | (1 << 7);
|
||||||
|
LOGDEBUG("Reslection DAT set to %02X",(int)id);
|
||||||
|
ctrl.bus->SetDAT((BYTE)id);
|
||||||
|
|
||||||
// // Phase setting
|
// Wait at least two deskew delays
|
||||||
// ctrl.phase = BUS::selection;
|
SysTimer::SleepNsec(SCSI_DELAY_DESKEW_DELAY_NS);
|
||||||
|
// Release the BSY signal
|
||||||
|
////////////////ctrl.bus->SetBSY(FALSE);
|
||||||
|
// We can't use the SetBSY() funciton, because that also reverses the direction of IC3
|
||||||
|
ctrl.bus->SetSignal(PIN_BSY, FALSE);
|
||||||
|
|
||||||
// // Raise BSY and respond
|
// Initiater waits for (SEL && IO && ~BSY) with its DAT flag set
|
||||||
// ctrl.bus->SetBSY(TRUE);
|
// to accept a reselect
|
||||||
// return;
|
SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS);
|
||||||
// }
|
|
||||||
|
|
||||||
// // Reselection completed
|
// Normally, we should wait to ensure that the target asserts BSY, but we
|
||||||
// if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) {
|
// can't read the BSY signal while the IO line is being asserted. So, we just
|
||||||
// // Message out phase if ATN=1, otherwise command phase
|
// have to assume it worked
|
||||||
// if (ctrl.bus->GetATN()) {
|
|
||||||
// MsgOut();
|
// if(ctrl.bus->WaitSignalTimeoutUs(PIN_BSY, TRUE, SCSI_DELAY_SELECTION_ABORT_TIME_US*3))
|
||||||
// } else {
|
// {
|
||||||
// Command();
|
LOGDEBUG("Initiator correctly asserted BSY");
|
||||||
// }
|
// After the Initiator asserts BSY, we need to take it over and also assert it
|
||||||
// }
|
////////////////////ctrl.bus->SetBSY(TRUE);
|
||||||
|
ctrl.bus->SetSignal(PIN_BSY, TRUE);
|
||||||
|
SysTimer::SleepNsec(SCSI_DELAY_DESKEW_DELAY_NS * 2);
|
||||||
|
|
||||||
|
// Release the SEL signal
|
||||||
|
ctrl.bus->SetSEL(FALSE);
|
||||||
|
|
||||||
|
// Transition to the Msg Out phase
|
||||||
|
MsgOut();
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// ctrl.phase = BUS::busfree;
|
||||||
|
// BusFree();
|
||||||
|
// // Timeout waiting for Intiaitor to reselect
|
||||||
|
// LOGERROR("Initiator did not assert PIN_BSY within the specified timeout. Aborting the Reselection");
|
||||||
|
// // Reset the controller
|
||||||
|
// Reset();
|
||||||
|
|
||||||
|
// // Reset the bus
|
||||||
|
// ctrl.bus->Reset();
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -540,13 +576,12 @@ void FASTCALL SCSIDEV::Execute()
|
|||||||
void FASTCALL SCSIDEV::MsgOut()
|
void FASTCALL SCSIDEV::MsgOut()
|
||||||
{
|
{
|
||||||
ASSERT(this);
|
ASSERT(this);
|
||||||
|
LOGTRACE("%s ID: %d",__PRETTY_FUNCTION__, this->GetID());
|
||||||
|
|
||||||
// Phase change
|
// Phase change
|
||||||
if (ctrl.phase != BUS::msgout) {
|
if (ctrl.phase != BUS::msgout) {
|
||||||
|
|
||||||
#if defined(DISK_LOG)
|
LOGTRACE("Message Out Phase");
|
||||||
Log(Log::Normal, "Message Out Phase");
|
|
||||||
#endif // DISK_LOG
|
|
||||||
|
|
||||||
// Message out phase after selection
|
// Message out phase after selection
|
||||||
// process the IDENTIFY message
|
// process the IDENTIFY message
|
||||||
@@ -576,23 +611,8 @@ void FASTCALL SCSIDEV::MsgOut()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RASCSI
|
|
||||||
// Receive
|
// Receive
|
||||||
Receive();
|
Receive();
|
||||||
#else
|
|
||||||
// Requesting
|
|
||||||
if (ctrl.bus->GetREQ()) {
|
|
||||||
// Sent by the initiator
|
|
||||||
if (ctrl.bus->GetACK()) {
|
|
||||||
Receive();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Request the initator to
|
|
||||||
if (!ctrl.bus->GetACK()) {
|
|
||||||
ReceiveNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // RASCSI
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -1841,132 +1861,52 @@ void FASTCALL SCSIDEV::SendNext()
|
|||||||
}
|
}
|
||||||
#endif // RASCSI
|
#endif // RASCSI
|
||||||
|
|
||||||
#ifndef RASCSI
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Receive data
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void FASTCALL SCSIDEV::Receive()
|
|
||||||
{
|
|
||||||
DWORD data;
|
|
||||||
|
|
||||||
ASSERT(this);
|
|
||||||
|
|
||||||
// Req is up
|
|
||||||
ASSERT(ctrl.bus->GetREQ());
|
|
||||||
ASSERT(!ctrl.bus->GetIO());
|
|
||||||
|
|
||||||
// Get data
|
|
||||||
data = (DWORD)ctrl.bus->GetDAT();
|
|
||||||
|
|
||||||
// Signal line operated by the target
|
|
||||||
ctrl.bus->SetREQ(FALSE);
|
|
||||||
|
|
||||||
switch (ctrl.phase) {
|
|
||||||
// Command phase
|
|
||||||
case BUS::command:
|
|
||||||
ctrl.cmd[ctrl.offset] = data;
|
|
||||||
#if defined(DISK_LOG)
|
|
||||||
Log(Log::Normal, "Command phase $%02X", data);
|
|
||||||
#endif // DISK_LOG
|
|
||||||
|
|
||||||
// Set the length again with the first data (offset 0)
|
|
||||||
if (ctrl.offset == 0) {
|
|
||||||
if (ctrl.cmd[0] >= 0x20) {
|
|
||||||
// 10バイトCDB
|
|
||||||
ctrl.length = 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Message out phase
|
|
||||||
case BUS::msgout:
|
|
||||||
ctrl.message = data;
|
|
||||||
#if defined(DISK_LOG)
|
|
||||||
Log(Log::Normal, "Message out phase $%02X", data);
|
|
||||||
#endif // DISK_LOG
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Data out phase
|
|
||||||
case BUS::dataout:
|
|
||||||
ctrl.buffer[ctrl.offset] = (BYTE)data;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Other (impossible)
|
|
||||||
default:
|
|
||||||
ASSERT(FALSE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // RASCSI
|
|
||||||
|
|
||||||
#ifdef RASCSI
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Receive Data
|
// Receive Data
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void FASTCALL SCSIDEV::Receive()
|
void FASTCALL SCSIDEV::Receive()
|
||||||
#else
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Continue receiving data
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
void FASTCALL SCSIDEV::ReceiveNext()
|
|
||||||
#endif // RASCSI
|
|
||||||
{
|
{
|
||||||
#ifdef RASCSI
|
|
||||||
int len;
|
int len;
|
||||||
#endif // RASCSI
|
|
||||||
BOOL result;
|
BOOL result;
|
||||||
int i;
|
int i;
|
||||||
BYTE data;
|
BYTE data;
|
||||||
|
|
||||||
ASSERT(this);
|
ASSERT(this);
|
||||||
|
|
||||||
|
LOGTRACE("%s",__PRETTY_FUNCTION__);
|
||||||
|
|
||||||
// REQ is low
|
// REQ is low
|
||||||
ASSERT(!ctrl.bus->GetREQ());
|
ASSERT(!ctrl.bus->GetREQ());
|
||||||
ASSERT(!ctrl.bus->GetIO());
|
ASSERT(!ctrl.bus->GetIO());
|
||||||
|
|
||||||
#ifdef RASCSI
|
|
||||||
// Length != 0 if received
|
// Length != 0 if received
|
||||||
if (ctrl.length != 0) {
|
if (ctrl.length != 0) {
|
||||||
|
LOGTRACE("%s length was != 0", __PRETTY_FUNCTION__);
|
||||||
// Receive
|
// Receive
|
||||||
len = ctrl.bus->ReceiveHandShake(
|
len = ctrl.bus->ReceiveHandShake(
|
||||||
&ctrl.buffer[ctrl.offset], ctrl.length);
|
&ctrl.buffer[ctrl.offset], ctrl.length);
|
||||||
|
|
||||||
// If not able to receive all, move to status phase
|
// If not able to receive all, move to status phase
|
||||||
if (len != (int)ctrl.length) {
|
if (len != (int)ctrl.length) {
|
||||||
|
LOGERROR("%s Not able to receive all data. Going to error",__PRETTY_FUNCTION__);
|
||||||
Error();
|
Error();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset and Length
|
// Offset and Length
|
||||||
ctrl.offset += ctrl.length;
|
ctrl.offset += ctrl.length;
|
||||||
ctrl.length = 0;;
|
ctrl.length = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
// Offset and Length
|
|
||||||
ASSERT(ctrl.length >= 1);
|
|
||||||
ctrl.offset++;
|
|
||||||
ctrl.length--;
|
|
||||||
|
|
||||||
// If length!=0, set req again
|
|
||||||
if (ctrl.length != 0) {
|
|
||||||
// Signal line operated by the target
|
|
||||||
ctrl.bus->SetREQ(TRUE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif // RASCSI
|
|
||||||
|
|
||||||
// Block subtraction, result initialization
|
// Block subtraction, result initialization
|
||||||
ctrl.blocks--;
|
ctrl.blocks--;
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
|
|
||||||
// Processing after receiving data (by phase)
|
// Processing after receiving data (by phase)
|
||||||
|
LOGTRACE("ctrl.phase: %d",(int)ctrl.phase);
|
||||||
switch (ctrl.phase) {
|
switch (ctrl.phase) {
|
||||||
|
|
||||||
// Data out phase
|
// Data out phase
|
||||||
@@ -2007,10 +1947,6 @@ void FASTCALL SCSIDEV::ReceiveNext()
|
|||||||
if (ctrl.blocks != 0){
|
if (ctrl.blocks != 0){
|
||||||
ASSERT(ctrl.length > 0);
|
ASSERT(ctrl.length > 0);
|
||||||
ASSERT(ctrl.offset == 0);
|
ASSERT(ctrl.offset == 0);
|
||||||
#ifndef RASCSI
|
|
||||||
// Signal line operated by the target
|
|
||||||
ctrl.bus->SetREQ(TRUE);
|
|
||||||
#endif // RASCSI
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2018,7 +1954,6 @@ void FASTCALL SCSIDEV::ReceiveNext()
|
|||||||
switch (ctrl.phase) {
|
switch (ctrl.phase) {
|
||||||
// Command phase
|
// Command phase
|
||||||
case BUS::command:
|
case BUS::command:
|
||||||
#ifdef RASCSI
|
|
||||||
// Command data transfer
|
// Command data transfer
|
||||||
len = 6;
|
len = 6;
|
||||||
if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) {
|
if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) {
|
||||||
@@ -2027,11 +1962,8 @@ void FASTCALL SCSIDEV::ReceiveNext()
|
|||||||
}
|
}
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
ctrl.cmd[i] = (DWORD)ctrl.buffer[i];
|
ctrl.cmd[i] = (DWORD)ctrl.buffer[i];
|
||||||
#if defined(DISK_LOG)
|
LOGTRACE("%s Command $%02X",__PRETTY_FUNCTION__, (int)ctrl.cmd[i]);
|
||||||
Log(Log::Normal, "Command $%02X", ctrl.cmd[i]);
|
|
||||||
#endif // DISK_LOG
|
|
||||||
}
|
}
|
||||||
#endif // RASCSI
|
|
||||||
|
|
||||||
// Execution Phase
|
// Execution Phase
|
||||||
Execute();
|
Execute();
|
||||||
@@ -2045,10 +1977,7 @@ void FASTCALL SCSIDEV::ReceiveNext()
|
|||||||
ctrl.offset = 0;
|
ctrl.offset = 0;
|
||||||
ctrl.length = 1;
|
ctrl.length = 1;
|
||||||
ctrl.blocks = 1;
|
ctrl.blocks = 1;
|
||||||
#ifndef RASCSI
|
|
||||||
// Request message
|
|
||||||
ctrl.bus->SetREQ(TRUE);
|
|
||||||
#endif // RASCSI
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2061,20 +1990,14 @@ void FASTCALL SCSIDEV::ReceiveNext()
|
|||||||
|
|
||||||
// ABORT
|
// ABORT
|
||||||
if (data == 0x06) {
|
if (data == 0x06) {
|
||||||
#if defined(DISK_LOG)
|
LOGTRACE("Message code ABORT $%02X", (int)data);
|
||||||
Log(Log::Normal,
|
|
||||||
"Message code ABORT $%02X", data);
|
|
||||||
#endif // DISK_LOG
|
|
||||||
BusFree();
|
BusFree();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BUS DEVICE RESET
|
// BUS DEVICE RESET
|
||||||
if (data == 0x0C) {
|
if (data == 0x0C) {
|
||||||
#if defined(DISK_LOG)
|
LOGTRACE("Message code BUS DEVICE RESET $%02X", (int)data);
|
||||||
Log(Log::Normal,
|
|
||||||
"Message code BUS DEVICE RESET $%02X", data);
|
|
||||||
#endif // DISK_LOG
|
|
||||||
scsi.syncoffset = 0;
|
scsi.syncoffset = 0;
|
||||||
BusFree();
|
BusFree();
|
||||||
return;
|
return;
|
||||||
@@ -2082,18 +2005,12 @@ void FASTCALL SCSIDEV::ReceiveNext()
|
|||||||
|
|
||||||
// IDENTIFY
|
// IDENTIFY
|
||||||
if (data >= 0x80) {
|
if (data >= 0x80) {
|
||||||
#if defined(DISK_LOG)
|
LOGTRACE("Message code IDENTIFY $%02X", (int)data);
|
||||||
Log(Log::Normal,
|
|
||||||
"Message code IDENTIFY $%02X", data);
|
|
||||||
#endif // DISK_LOG
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extended Message
|
// Extended Message
|
||||||
if (data == 0x01) {
|
if (data == 0x01) {
|
||||||
#if defined(DISK_LOG)
|
LOGTRACE("Message code EXTENDED MESSAGE $%02X", (int)data);
|
||||||
Log(Log::Normal,
|
|
||||||
"Message code EXTENDED MESSAGE $%02X", data);
|
|
||||||
#endif // DISK_LOG
|
|
||||||
|
|
||||||
// Check only when synchronous transfer is possible
|
// Check only when synchronous transfer is possible
|
||||||
if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) {
|
if (!scsi.syncenable || scsi.msb[i + 2] != 0x01) {
|
||||||
@@ -2182,28 +2099,26 @@ BOOL FASTCALL SCSIDEV::XferMsg(DWORD msg)
|
|||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
BOOL FASTCALL SCSIDEV::TransferPacketToHost(int packet_len){
|
BOOL FASTCALL SCSIDEV::TransferPacketToHost(int packet_len){
|
||||||
|
|
||||||
|
SCSINuvolink *nuvolink;
|
||||||
|
|
||||||
|
LOGTRACE("%s", __PRETTY_FUNCTION__);
|
||||||
//*****************************
|
//*****************************
|
||||||
// BUS FREE PHASE
|
// BUS FREE PHASE
|
||||||
//*****************************
|
//*****************************
|
||||||
// We should already be in bus free phase when we enter this function
|
// We should already be in bus free phase when we enter this function
|
||||||
|
BusFree();
|
||||||
|
|
||||||
//*****************************
|
//*****************************
|
||||||
// ARBITRATION PHASE
|
// ARBITRATION PHASE
|
||||||
//*****************************
|
//*****************************
|
||||||
// Aquire the bus
|
Arbitration();
|
||||||
// ctrl.bus->Aquire();
|
|
||||||
// ctrl.bus->SetIO();
|
|
||||||
|
|
||||||
// if (bus->GetBUSY()) {
|
|
||||||
// #if !defined(BAREMETAL)
|
|
||||||
// usleep(0);
|
|
||||||
// #endif // !BAREMETAL
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// #endif // USE_SEL_EVENT_ENABLE
|
|
||||||
//*****************************
|
//*****************************
|
||||||
// Reselection
|
// Reselection
|
||||||
//*****************************
|
//*****************************
|
||||||
|
Reselection();
|
||||||
|
|
||||||
//*****************************
|
//*****************************
|
||||||
// Message OUT (expect a "NO OPERATION")
|
// Message OUT (expect a "NO OPERATION")
|
||||||
@@ -2211,15 +2126,34 @@ BOOL FASTCALL SCSIDEV::TransferPacketToHost(int packet_len){
|
|||||||
// Transition to MESSAGE IN and send a DISCONNECT
|
// Transition to MESSAGE IN and send a DISCONNECT
|
||||||
// then go to BUS FREE
|
// then go to BUS FREE
|
||||||
//*****************************
|
//*****************************
|
||||||
|
MsgOut();
|
||||||
|
|
||||||
|
LOGTRACE("%s Done with MsgOut", __PRETTY_FUNCTION__);
|
||||||
//*****************************
|
//*****************************
|
||||||
// DATA IN
|
// DATA IN
|
||||||
// ... send the packet
|
// ... send the packet
|
||||||
//*****************************
|
//*****************************
|
||||||
|
// The Nuvolink should always be unit 0. Unit 1 is only applicable
|
||||||
|
// to SASI devices
|
||||||
|
if(ctrl.unit[0]->GetID() == MAKEID('S','C','N','L')){
|
||||||
|
ctrl.length = packet_len;
|
||||||
|
ctrl.buffer[0] = NUVOLINK_RSR_REG_PACKET_INTACT;
|
||||||
|
ctrl.buffer[1] = m_sequence_number++;
|
||||||
|
ctrl.buffer[2] = (packet_len & 0xFF);
|
||||||
|
ctrl.buffer[3] = (packet_len >> 8) & 0xFF;
|
||||||
|
nuvolink = (SCSINuvolink*)ctrl.unit[0];
|
||||||
|
memcpy(&(ctrl.buffer[4]), nuvolink->packet_buf, packet_len);
|
||||||
|
}else{
|
||||||
|
ctrl.buffer[2] = 0;
|
||||||
|
ctrl.buffer[3] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataIn();
|
||||||
|
|
||||||
//*****************************
|
//*****************************
|
||||||
// MESSAGE OUT (expect a "NO OPERATION")
|
// MESSAGE OUT (expect a "NO OPERATION")
|
||||||
//*****************************
|
//*****************************
|
||||||
|
MsgOut();
|
||||||
|
|
||||||
//*****************************
|
//*****************************
|
||||||
// If more packets, go back to DATA IN
|
// If more packets, go back to DATA IN
|
||||||
@@ -2229,9 +2163,16 @@ BOOL FASTCALL SCSIDEV::TransferPacketToHost(int packet_len){
|
|||||||
// Else
|
// Else
|
||||||
// MESSAGE IN (sends DISCONNECT)
|
// MESSAGE IN (sends DISCONNECT)
|
||||||
//*****************************
|
//*****************************
|
||||||
|
ctrl.blocks = 1;
|
||||||
|
ctrl.length = sizeof(scsi_message_code);
|
||||||
|
ctrl.buffer[0] = eMsgCodeDisconnect;
|
||||||
|
ctrl.message = (DWORD)eMsgCodeDisconnect; // (This is probably redundant and unnecessary?)
|
||||||
|
MsgIn();
|
||||||
|
|
||||||
//*****************************
|
//*****************************
|
||||||
// BUS FREE
|
// BUS FREE
|
||||||
//*****************************
|
//*****************************
|
||||||
BusFree();
|
BusFree();
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "controllers/sasidev_ctrl.h"
|
#include "controllers/sasidev_ctrl.h"
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Nuvolink Register constants
|
||||||
|
// Bit 0: set when packet received intact, thus always set.
|
||||||
|
// Bit 5: set when the packet was a multicast/broadcast packet.
|
||||||
|
//===========================================================================
|
||||||
|
#define NUVOLINK_RSR_REG_PACKET_INTACT (1 << 0)
|
||||||
|
#define NUVOLINK_RSR_REG_MCAST_OR_BCAST (1 << 5)
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// SCSI Device (Interits SASI device)
|
// SCSI Device (Interits SASI device)
|
||||||
@@ -38,6 +48,33 @@ public:
|
|||||||
BYTE msb[256];
|
BYTE msb[256];
|
||||||
} scsi_t;
|
} scsi_t;
|
||||||
|
|
||||||
|
|
||||||
|
enum scsi_message_code : BYTE {
|
||||||
|
eMsgCodeAbort = 0x06,
|
||||||
|
eMsgCodeAbortTag = 0x0D,
|
||||||
|
eMsgCodeBusDeviceReset = 0x0C,
|
||||||
|
eMsgCodeClearQueue = 0x0E,
|
||||||
|
eMsgCodeCommandComplete = 0x00,
|
||||||
|
eMsgCodeDisconnect = 0x04,
|
||||||
|
eMsgCodeIdentify = 0x80,
|
||||||
|
eMsgCodeIgnoreWideResidue = 0x23, // (Two Bytes)
|
||||||
|
eMsgCodeInitiateRecovery = 0x0F,
|
||||||
|
eMsgCodeInitiatorDetectedError = 0x05,
|
||||||
|
eMsgCodeLinkedCommandComplete = 0x0A,
|
||||||
|
eMsgCodeLinkedCommandCompleteWithFlag = 0x0B,
|
||||||
|
eMsgCodeMessageParityError = 0x09,
|
||||||
|
eMsgCodeMessageReject = 0x07,
|
||||||
|
eMsgCodeNoOperation = 0x08,
|
||||||
|
eMsgCodeHeadOfQueueTag = 0x21,
|
||||||
|
eMsgCodeOrderedQueueTag = 0x22,
|
||||||
|
eMsgCodeSimpleQueueTag = 0x20,
|
||||||
|
eMsgCodeReleaseRecovery = 0x10,
|
||||||
|
eMsgCodeRestorePointers = 0x03,
|
||||||
|
eMsgCodeSaveDataPointer = 0x02,
|
||||||
|
eMsgCodeTerminateIOProcess = 0x11,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
enum scsi_command : BYTE {
|
enum scsi_command : BYTE {
|
||||||
eCmdTestUnitReady = 0x00,
|
eCmdTestUnitReady = 0x00,
|
||||||
eCmdRezero = 0x01,
|
eCmdRezero = 0x01,
|
||||||
@@ -79,11 +116,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Basic Functions
|
// Basic Functions
|
||||||
#ifdef RASCSI
|
|
||||||
SCSIDEV();
|
SCSIDEV();
|
||||||
#else
|
|
||||||
SCSIDEV(Device *dev);
|
|
||||||
#endif // RASCSI
|
|
||||||
// Constructor
|
// Constructor
|
||||||
|
|
||||||
void FASTCALL Reset();
|
void FASTCALL Reset();
|
||||||
@@ -195,5 +228,9 @@ private:
|
|||||||
|
|
||||||
scsi_t scsi;
|
scsi_t scsi;
|
||||||
// Internal data
|
// Internal data
|
||||||
|
|
||||||
|
// Sequence number for the Nuvolink. This really belongs somewhere else,
|
||||||
|
// but it goes here for now.
|
||||||
|
BYTE m_sequence_number = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ SCSINuvolink::SCSINuvolink() : Disk()
|
|||||||
// Nuvolink
|
// Nuvolink
|
||||||
disk.id = MAKEID('S', 'C', 'N', 'L');
|
disk.id = MAKEID('S', 'C', 'N', 'L');
|
||||||
|
|
||||||
#if defined(RASCSI) && defined(__linux__) && !defined(BAREMETAL)
|
#if defined(__linux__) && !defined(BAREMETAL)
|
||||||
// TAP Driver Generation
|
// TAP Driver Generation
|
||||||
tap = new CTapDriver();
|
tap = new CTapDriver();
|
||||||
m_bTapEnable = tap->Init();
|
m_bTapEnable = tap->Init();
|
||||||
@@ -77,7 +77,7 @@ SCSINuvolink::SCSINuvolink() : Disk()
|
|||||||
SCSINuvolink::~SCSINuvolink()
|
SCSINuvolink::~SCSINuvolink()
|
||||||
{
|
{
|
||||||
LOGTRACE("SCSINuvolink Destructor");
|
LOGTRACE("SCSINuvolink Destructor");
|
||||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
#if !defined(BAREMETAL)
|
||||||
// TAP driver release
|
// TAP driver release
|
||||||
if (tap) {
|
if (tap) {
|
||||||
tap->Cleanup();
|
tap->Cleanup();
|
||||||
@@ -420,7 +420,7 @@ void FASTCALL SCSINuvolink::SetMulticastRegisters(BYTE *buffer, int len){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(RASCSI) && !defined(BAREMETAL)
|
#if !defined(BAREMETAL)
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Get MAC Address
|
// Get MAC Address
|
||||||
@@ -479,14 +479,47 @@ int FASTCALL SCSINuvolink::ReceivePacket()
|
|||||||
|
|
||||||
if(packet_len){
|
if(packet_len){
|
||||||
LOGINFO("Received a packet of size %d",packet_len);
|
LOGINFO("Received a packet of size %d",packet_len);
|
||||||
|
|
||||||
|
for(int i=0; i< 48; i+=8)
|
||||||
|
{
|
||||||
|
LOGTRACE("%s %02X: %02X %02X %02X %02X %02X %02X %02X %02X", \
|
||||||
|
__PRETTY_FUNCTION__,i,
|
||||||
|
(int)packet_buf[i+0],
|
||||||
|
(int)packet_buf[i+1],
|
||||||
|
(int)packet_buf[i+2],
|
||||||
|
(int)packet_buf[i+3],
|
||||||
|
(int)packet_buf[i+4],
|
||||||
|
(int)packet_buf[i+5],
|
||||||
|
(int)packet_buf[i+6],
|
||||||
|
(int)packet_buf[i+7]);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if received packet
|
// This is a very basic filter to prevent unnecessary packets from
|
||||||
|
// being sent to the SCSI initiator.
|
||||||
|
|
||||||
|
// Check if received packet destination MAC address matches the
|
||||||
|
// Nuvolink MAC
|
||||||
if (memcmp(packet_buf, mac_addr, 6) != 0) {
|
if (memcmp(packet_buf, mac_addr, 6) != 0) {
|
||||||
|
// If it doesn't match, check to see if this is a broadcast message
|
||||||
if (memcmp(packet_buf, bcast_addr, 6) != 0) {
|
if (memcmp(packet_buf, bcast_addr, 6) != 0) {
|
||||||
|
LOGINFO("%s Received a packet that's not for me: %02X %02X %02X %02X %02X %02X", \
|
||||||
|
__PRETTY_FUNCTION__,
|
||||||
|
(int)packet_buf[0],
|
||||||
|
(int)packet_buf[1],
|
||||||
|
(int)packet_buf[2],
|
||||||
|
(int)packet_buf[3],
|
||||||
|
(int)packet_buf[4],
|
||||||
|
(int)packet_buf[5]);
|
||||||
packet_len = 0;
|
packet_len = 0;
|
||||||
return -1;
|
return -1;
|
||||||
|
}else{
|
||||||
|
packet_is_bcast_or_mcast = TRUE;
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
packet_is_bcast_or_mcast = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard if it exceeds the buffer size
|
// Discard if it exceeds the buffer size
|
||||||
@@ -496,13 +529,7 @@ int FASTCALL SCSINuvolink::ReceivePacket()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransferPacket(packet_len, packet_buff);
|
|
||||||
return packet_len;
|
return packet_len;
|
||||||
|
|
||||||
// // Store in receive buffer
|
|
||||||
// if (packet_len > 0) {
|
|
||||||
// packet_enable = TRUE;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,14 @@ public:
|
|||||||
// Send a packet
|
// Send a packet
|
||||||
int FASTCALL ReceivePacket();
|
int FASTCALL ReceivePacket();
|
||||||
// Receive a packet
|
// Receive a packet
|
||||||
|
int packet_len;
|
||||||
|
// Receive packet size
|
||||||
|
BYTE packet_buf[0x1000];
|
||||||
|
// Receive packet buffer
|
||||||
|
BOOL packet_is_bcast_or_mcast;
|
||||||
|
// Flag intidcating if the last packet is multicast/broadcast
|
||||||
|
// TRUE if multicast or broadcast
|
||||||
|
// FALSE if unicast
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum nuvolink_command_enum : BYTE {
|
enum nuvolink_command_enum : BYTE {
|
||||||
@@ -95,10 +102,6 @@ private:
|
|||||||
// TAP valid flag
|
// TAP valid flag
|
||||||
BYTE mac_addr[6];
|
BYTE mac_addr[6];
|
||||||
// MAC Addres
|
// MAC Addres
|
||||||
int packet_len;
|
|
||||||
// Receive packet size
|
|
||||||
BYTE packet_buf[0x1000];
|
|
||||||
// Receive packet buffer
|
|
||||||
BOOL packet_enable;
|
BOOL packet_enable;
|
||||||
// Received packet valid
|
// Received packet valid
|
||||||
#endif // RASCSI && !BAREMETAL
|
#endif // RASCSI && !BAREMETAL
|
||||||
|
|||||||
@@ -632,6 +632,29 @@ void FASTCALL GPIOBUS::SetSEL(BOOL ast)
|
|||||||
SetControl(PIN_ACT, ACT_ON);
|
SetControl(PIN_ACT, ACT_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If we're trying to SET the SEL signal, we need to
|
||||||
|
// reverse directions on IC4
|
||||||
|
if (actmode == TARGET) {
|
||||||
|
if (ast) {
|
||||||
|
// Set Target signal to output
|
||||||
|
SetControl(PIN_IND, IND_OUT);
|
||||||
|
|
||||||
|
SetMode(PIN_SEL, OUT);
|
||||||
|
SetMode(PIN_RST, OUT);
|
||||||
|
SetMode(PIN_ACK, OUT);
|
||||||
|
SetMode(PIN_ATN, OUT);
|
||||||
|
} else {
|
||||||
|
// Set the target signal to input
|
||||||
|
SetControl(PIN_IND, IND_IN);
|
||||||
|
|
||||||
|
SetMode(PIN_SEL, IN);
|
||||||
|
SetMode(PIN_RST, IN);
|
||||||
|
SetMode(PIN_ACK, IN);
|
||||||
|
SetMode(PIN_ATN, IN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set SEL signal
|
// Set SEL signal
|
||||||
SetSignal(PIN_SEL, ast);
|
SetSignal(PIN_SEL, ast);
|
||||||
}
|
}
|
||||||
@@ -1532,15 +1555,25 @@ void FASTCALL GPIOBUS::SetSignal(int pin, BOOL ast)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
BOOL FASTCALL GPIOBUS::WaitSignal(int pin, BOOL ast)
|
BOOL FASTCALL GPIOBUS::WaitSignal(int pin, BOOL ast)
|
||||||
{
|
{
|
||||||
DWORD now;
|
|
||||||
DWORD timeout;
|
DWORD timeout;
|
||||||
|
|
||||||
|
// Calculate default timeout (3000ms)
|
||||||
|
timeout = 3000 * 1000;
|
||||||
|
return WaitSignalTimeoutUs(pin, ast, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Wait for signal change
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
BOOL FASTCALL GPIOBUS::WaitSignalTimeoutUs(int pin, BOOL ast, DWORD timeout)
|
||||||
|
{
|
||||||
|
DWORD now;
|
||||||
|
|
||||||
// Get current time
|
// Get current time
|
||||||
now = SysTimer::GetTimerLow();
|
now = SysTimer::GetTimerLow();
|
||||||
|
|
||||||
// Calculate timeout (3000ms)
|
|
||||||
timeout = 3000 * 1000;
|
|
||||||
|
|
||||||
// end immediately if the signal has changed
|
// end immediately if the signal has changed
|
||||||
do {
|
do {
|
||||||
// Immediately upon receiving a reset
|
// Immediately upon receiving a reset
|
||||||
|
|||||||
@@ -434,6 +434,30 @@
|
|||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#define GPIO_DATA_SETTLING 100 // Data bus stabilization time (ns)
|
#define GPIO_DATA_SETTLING 100 // Data bus stabilization time (ns)
|
||||||
|
// SCSI Bus timings taken from:
|
||||||
|
// https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-05.html
|
||||||
|
#define SCSI_DELAY_ARBITRATION_DELAY_NS 2400
|
||||||
|
#define SCSI_DELAY_ASSERTION_PERIOD_NS 90
|
||||||
|
#define SCSI_DELAY_BUS_CLEAR_DELAY_NS 800
|
||||||
|
#define SCSI_DELAY_BUS_FREE_DELAY_NS 800
|
||||||
|
#define SCSI_DELAY_BUS_SET_DELAY_NS 1800
|
||||||
|
#define SCSI_DELAY_BUS_SETTLE_DELAY_NS 400
|
||||||
|
#define SCSI_DELAY_CABLE_SKEW_DELAY_NS 10
|
||||||
|
#define SCSI_DELAY_DATA_RELEASE_DELAY_NS 400
|
||||||
|
#define SCSI_DELAY_DESKEW_DELAY_NS 45
|
||||||
|
#define SCSI_DELAY_DISCONNECTION_DELAY_US 200
|
||||||
|
#define SCSI_DELAY_HOLD_TIME_NS 45
|
||||||
|
#define SCSI_DELAY_NEGATION_PERIOD_NS 90
|
||||||
|
#define SCSI_DELAY_POWER_ON_TO_SELECTION_TIME_S 10 // (recommended)
|
||||||
|
#define SCSI_DELAY_RESET_TO_SELECTION_TIME_US (250*1000) // (recommended)
|
||||||
|
#define SCSI_DELAY_RESET_HOLD_TIME_US 25
|
||||||
|
#define SCSI_DELAY_SELECTION_ABORT_TIME_US 200
|
||||||
|
#define SCSI_DELAY_SELECTION_TIMEOUT_DELAY_NS (250*1000) // (recommended)
|
||||||
|
#define SCSI_DELAY_FAST_ASSERTION_PERIOD_NS 30
|
||||||
|
#define SCSI_DELAY_FAST_CABLE_SKEW_DELAY_NS 5
|
||||||
|
#define SCSI_DELAY_FAST_DESKEW_DELAY_NS 20
|
||||||
|
#define SCSI_DELAY_FAST_HOLD_TIME_NS 10
|
||||||
|
#define SCSI_DELAY_FAST_NEGATION_PERIOD_NS 30
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@@ -523,6 +547,15 @@ public:
|
|||||||
// Data receive handshake
|
// Data receive handshake
|
||||||
int FASTCALL SendHandShake(BYTE *buf, int count);
|
int FASTCALL SendHandShake(BYTE *buf, int count);
|
||||||
// Data transmission handshake
|
// Data transmission handshake
|
||||||
|
BOOL FASTCALL WaitSignalTimeoutUs(int pin, BOOL ast, DWORD timeout);
|
||||||
|
// Wait for a specified number of
|
||||||
|
// microseconds for a signal to change
|
||||||
|
void FASTCALL SetControl(int pin, BOOL ast);
|
||||||
|
// Set Control Signal
|
||||||
|
BOOL FASTCALL GetSignal(int pin);
|
||||||
|
// Get SCSI input signal value
|
||||||
|
void FASTCALL SetSignal(int pin, BOOL ast);
|
||||||
|
// Set SCSI output signal value
|
||||||
|
|
||||||
#ifdef USE_SEL_EVENT_ENABLE
|
#ifdef USE_SEL_EVENT_ENABLE
|
||||||
// SEL signal interrupt
|
// SEL signal interrupt
|
||||||
@@ -536,16 +569,10 @@ private:
|
|||||||
// SCSI I/O signal control
|
// SCSI I/O signal control
|
||||||
void FASTCALL MakeTable();
|
void FASTCALL MakeTable();
|
||||||
// Create work data
|
// Create work data
|
||||||
void FASTCALL SetControl(int pin, BOOL ast);
|
|
||||||
// Set Control Signal
|
|
||||||
void FASTCALL SetMode(int pin, int mode);
|
void FASTCALL SetMode(int pin, int mode);
|
||||||
// Set SCSI I/O mode
|
// Set SCSI I/O mode
|
||||||
BOOL FASTCALL GetSignal(int pin);
|
|
||||||
// Get SCSI input signal value
|
|
||||||
void FASTCALL SetSignal(int pin, BOOL ast);
|
|
||||||
// Set SCSI output signal value
|
|
||||||
BOOL FASTCALL WaitSignal(int pin, BOOL ast);
|
BOOL FASTCALL WaitSignal(int pin, BOOL ast);
|
||||||
// Wait for a signal to change
|
// Wait up to 3s for a signal to change
|
||||||
// Interrupt control
|
// Interrupt control
|
||||||
void FASTCALL DisableIRQ();
|
void FASTCALL DisableIRQ();
|
||||||
// IRQ Disabled
|
// IRQ Disabled
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ public:
|
|||||||
phase_t FASTCALL GetPhase();
|
phase_t FASTCALL GetPhase();
|
||||||
// フェーズ取得
|
// フェーズ取得
|
||||||
|
|
||||||
|
virtual BOOL FASTCALL WaitSignalTimeoutUs(int pin, BOOL ast, DWORD timeout) = 0;
|
||||||
|
// Wait for a specified number of
|
||||||
|
// microseconds for a signal to change
|
||||||
|
|
||||||
|
|
||||||
static phase_t FASTCALL GetPhase(DWORD mci)
|
static phase_t FASTCALL GetPhase(DWORD mci)
|
||||||
{
|
{
|
||||||
return phase_table[mci];
|
return phase_table[mci];
|
||||||
@@ -122,6 +127,12 @@ public:
|
|||||||
virtual int FASTCALL SendHandShake(BYTE *buf, int count) = 0;
|
virtual int FASTCALL SendHandShake(BYTE *buf, int count) = 0;
|
||||||
// データ送信ハンドシェイク
|
// データ送信ハンドシェイク
|
||||||
|
|
||||||
|
|
||||||
|
virtual BOOL FASTCALL GetSignal(int pin) = 0;
|
||||||
|
// Get SCSI input signal value
|
||||||
|
virtual void FASTCALL SetSignal(int pin, BOOL ast) = 0;
|
||||||
|
// Set SCSI output signal value
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const phase_t phase_table[8];
|
static const phase_t phase_table[8];
|
||||||
// フェーズテーブル
|
// フェーズテーブル
|
||||||
|
|||||||
Reference in New Issue
Block a user