Added arbitration and reselection logic. Seems to work. Also removed some conditional code for non-RASCSI applications

This commit is contained in:
akuker 2020-09-26 21:23:48 -05:00
parent 01b0fb0f35
commit 45426b5fb6
8 changed files with 314 additions and 301 deletions

View File

@ -707,10 +707,7 @@ void FASTCALL SASIDEV::MsgIn()
// Phase change
if (ctrl.phase != BUS::msgin) {
#if defined(DISK_LOG)
Log(Log::Normal, "Message in phase");
#endif // DISK_LOG
LOGTRACE("%s Starting Message in phase", __PRETTY_FUNCTION__);
// Phase Setting
ctrl.phase = BUS::msgin;
@ -724,36 +721,12 @@ void FASTCALL SASIDEV::MsgIn()
ASSERT(ctrl.length > 0);
ASSERT(ctrl.blocks > 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;
}
#ifdef RASCSI
//Send
LOGTRACE("%s Transitioning to Send()", __PRETTY_FUNCTION__);
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;
}
#if defined(DISK_LOG)
Log(Log::Normal, "Data-in Phase");
#endif // DISK_LOG
LOGTRACE("%s Going into Data-in Phase", __PRETTY_FUNCTION__);
// Phase Setting
ctrl.phase = BUS::datain;
@ -809,33 +779,12 @@ void FASTCALL SASIDEV::DataIn()
ASSERT(ctrl.blocks > 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;
}
#ifdef RASCSI
// Send
LOGTRACE("%s Going to Send()",__PRETTY_FUNCTION__);
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->GetIO());
#ifdef RASCSI
// Check that the length isn't 0
if (ctrl.length != 0) {
len = ctrl.bus->SendHandShake(
@ -1411,20 +1359,6 @@ void FASTCALL SASIDEV::Send()
ctrl.length = 0;
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
ctrl.blocks--;
@ -1435,7 +1369,7 @@ void FASTCALL SASIDEV::Send()
if (ctrl.blocks != 0) {
// Set next buffer (set offset, length)
result = XferIn(ctrl.buffer);
//** printf("xfer in: %d \n",result);
LOGTRACE("%s xfer in: %d",__PRETTY_FUNCTION__, result);
#ifndef RASCSI
ctrl.bus->SetDAT(ctrl.buffer[ctrl.offset]);

View File

@ -197,44 +197,56 @@ void FASTCALL SCSIDEV::BusFree()
//---------------------------------------------------------------------------
void FASTCALL SCSIDEV::Arbitration()
{
// TODO: See https://www.staff.uni-mainz.de/tacke/scsi/SCSI2-06.html
// DWORD id;
DWORD id;
DWORD data_lines;
ASSERT(this);
// // Phase change
// if (ctrl.phase != BUS::reselection) {
// // invalid if IDs do not match
// id = 1 << ctrl.id;
// if ((ctrl.bus->GetDAT() & id) == 0) {
// return;
// }
// We need to switch the tranceivers to be inputs....
ctrl.bus->SetBSY(FALSE); // Make sure that we're not asserting the BSY signal
ctrl.bus->SetSEL(FALSE); // Make sure that we're not asserting the SEL signal
// // End if there is no valid unit
// if (!HasUnit()) {
// return;
// }
// If we arent' in the bus-free phase, we can't progress....
// just 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());
}
// Phase change
if (ctrl.phase != BUS::arbitration) {
// LOGDEBUG("Reselection phase ID=%d (with device)", ctrl.id);
ctrl.phase = BUS::arbitration;
// // Phase setting
// ctrl.phase = BUS::selection;
// Assert both the BSY signal and our own SCSI ID
id = 1 << ctrl.id;
ctrl.bus->SetDAT(id);
ctrl.bus->SetBSY(TRUE);
// // Raise BSY and respond
// ctrl.bus->SetBSY(TRUE);
// return;
// }
// Wait for an ARBITRATION DELAY
SysTimer::SleepNsec(SCSI_DELAY_ARBITRATION_DELAY_NS);
// Check if a higher SCSI ID is asserted. If so, we lost arbitration
ctrl.bus->Aquire();
data_lines = ctrl.bus->GetDAT();
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;
}
// // Reselection completed
// if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) {
// // Message out phase if ATN=1, otherwise command phase
// if (ctrl.bus->GetATN()) {
// MsgOut();
// } else {
// Command();
// }
// }
// 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()
{
// DWORD id;
DWORD id;
ASSERT(this);
// // Phase change
// if (ctrl.phase != BUS::reselection) {
// // invalid if IDs do not match
// id = 1 << ctrl.id;
// if ((ctrl.bus->GetDAT() & id) == 0) {
// return;
// }
// Phase change
if (ctrl.phase != BUS::reselection) {
ctrl.phase = BUS::reselection;
// // End if there is no valid unit
// if (!HasUnit()) {
// return;
// }
// Assert the IO signal
ctrl.bus->SetIO(TRUE);
// 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
// ctrl.phase = BUS::selection;
// Wait at least two deskew delays
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
// ctrl.bus->SetBSY(TRUE);
// return;
// }
// Initiater waits for (SEL && IO && ~BSY) with its DAT flag set
// to accept a reselect
SysTimer::SleepNsec(SCSI_DELAY_BUS_SETTLE_DELAY_NS);
// // Reselection completed
// if (!ctrl.bus->GetSEL() && ctrl.bus->GetBSY()) {
// // Message out phase if ATN=1, otherwise command phase
// if (ctrl.bus->GetATN()) {
// MsgOut();
// } else {
// Command();
// }
// }
// Normally, we should wait to ensure that the target asserts BSY, but we
// can't read the BSY signal while the IO line is being asserted. So, we just
// have to assume it worked
// if(ctrl.bus->WaitSignalTimeoutUs(PIN_BSY, TRUE, SCSI_DELAY_SELECTION_ABORT_TIME_US*3))
// {
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()
{
ASSERT(this);
LOGTRACE("%s ID: %d",__PRETTY_FUNCTION__, this->GetID());
// Phase change
if (ctrl.phase != BUS::msgout) {
#if defined(DISK_LOG)
Log(Log::Normal, "Message Out Phase");
#endif // DISK_LOG
LOGTRACE("Message Out Phase");
// Message out phase after selection
// process the IDENTIFY message
@ -576,23 +611,8 @@ void FASTCALL SCSIDEV::MsgOut()
return;
}
#ifdef RASCSI
// 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
#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
//
//---------------------------------------------------------------------------
void FASTCALL SCSIDEV::Receive()
#else
//---------------------------------------------------------------------------
//
// Continue receiving data
//
//---------------------------------------------------------------------------
void FASTCALL SCSIDEV::ReceiveNext()
#endif // RASCSI
{
#ifdef RASCSI
int len;
#endif // RASCSI
BOOL result;
int i;
BYTE data;
ASSERT(this);
LOGTRACE("%s",__PRETTY_FUNCTION__);
// REQ is low
ASSERT(!ctrl.bus->GetREQ());
ASSERT(!ctrl.bus->GetIO());
#ifdef RASCSI
// Length != 0 if received
if (ctrl.length != 0) {
LOGTRACE("%s length was != 0", __PRETTY_FUNCTION__);
// Receive
len = ctrl.bus->ReceiveHandShake(
&ctrl.buffer[ctrl.offset], ctrl.length);
// If not able to receive all, move to status phase
if (len != (int)ctrl.length) {
LOGERROR("%s Not able to receive all data. Going to error",__PRETTY_FUNCTION__);
Error();
return;
}
// Offset and Length
ctrl.offset += ctrl.length;
ctrl.length = 0;;
ctrl.length = 0;
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
ctrl.blocks--;
result = TRUE;
// Processing after receiving data (by phase)
LOGTRACE("ctrl.phase: %d",(int)ctrl.phase);
switch (ctrl.phase) {
// Data out phase
@ -2007,10 +1947,6 @@ void FASTCALL SCSIDEV::ReceiveNext()
if (ctrl.blocks != 0){
ASSERT(ctrl.length > 0);
ASSERT(ctrl.offset == 0);
#ifndef RASCSI
// Signal line operated by the target
ctrl.bus->SetREQ(TRUE);
#endif // RASCSI
return;
}
@ -2018,7 +1954,6 @@ void FASTCALL SCSIDEV::ReceiveNext()
switch (ctrl.phase) {
// Command phase
case BUS::command:
#ifdef RASCSI
// Command data transfer
len = 6;
if (ctrl.buffer[0] >= 0x20 && ctrl.buffer[0] <= 0x7D) {
@ -2027,11 +1962,8 @@ void FASTCALL SCSIDEV::ReceiveNext()
}
for (i = 0; i < len; i++) {
ctrl.cmd[i] = (DWORD)ctrl.buffer[i];
#if defined(DISK_LOG)
Log(Log::Normal, "Command $%02X", ctrl.cmd[i]);
#endif // DISK_LOG
LOGTRACE("%s Command $%02X",__PRETTY_FUNCTION__, (int)ctrl.cmd[i]);
}
#endif // RASCSI
// Execution Phase
Execute();
@ -2045,10 +1977,7 @@ void FASTCALL SCSIDEV::ReceiveNext()
ctrl.offset = 0;
ctrl.length = 1;
ctrl.blocks = 1;
#ifndef RASCSI
// Request message
ctrl.bus->SetREQ(TRUE);
#endif // RASCSI
return;
}
@ -2061,20 +1990,14 @@ void FASTCALL SCSIDEV::ReceiveNext()
// ABORT
if (data == 0x06) {
#if defined(DISK_LOG)
Log(Log::Normal,
"Message code ABORT $%02X", data);
#endif // DISK_LOG
LOGTRACE("Message code ABORT $%02X", (int)data);
BusFree();
return;
}
// BUS DEVICE RESET
if (data == 0x0C) {
#if defined(DISK_LOG)
Log(Log::Normal,
"Message code BUS DEVICE RESET $%02X", data);
#endif // DISK_LOG
LOGTRACE("Message code BUS DEVICE RESET $%02X", (int)data);
scsi.syncoffset = 0;
BusFree();
return;
@ -2082,18 +2005,12 @@ void FASTCALL SCSIDEV::ReceiveNext()
// IDENTIFY
if (data >= 0x80) {
#if defined(DISK_LOG)
Log(Log::Normal,
"Message code IDENTIFY $%02X", data);
#endif // DISK_LOG
LOGTRACE("Message code IDENTIFY $%02X", (int)data);
}
// Extended Message
if (data == 0x01) {
#if defined(DISK_LOG)
Log(Log::Normal,
"Message code EXTENDED MESSAGE $%02X", data);
#endif // DISK_LOG
LOGTRACE("Message code EXTENDED MESSAGE $%02X", (int)data);
// Check only when synchronous transfer is possible
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){
SCSINuvolink *nuvolink;
LOGTRACE("%s", __PRETTY_FUNCTION__);
//*****************************
// BUS FREE PHASE
//*****************************
// We should already be in bus free phase when we enter this function
BusFree();
//*****************************
// ARBITRATION PHASE
//*****************************
// Aquire the bus
// ctrl.bus->Aquire();
// ctrl.bus->SetIO();
Arbitration();
// if (bus->GetBUSY()) {
// #if !defined(BAREMETAL)
// usleep(0);
// #endif // !BAREMETAL
// continue;
// }
// #endif // USE_SEL_EVENT_ENABLE
//*****************************
// Reselection
//*****************************
Reselection();
//*****************************
// 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
// then go to BUS FREE
//*****************************
MsgOut();
LOGTRACE("%s Done with MsgOut", __PRETTY_FUNCTION__);
//*****************************
// DATA IN
// ... 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")
//*****************************
MsgOut();
//*****************************
// If more packets, go back to DATA IN
@ -2229,9 +2163,16 @@ BOOL FASTCALL SCSIDEV::TransferPacketToHost(int packet_len){
// Else
// 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
//*****************************
BusFree();
return TRUE;
}

View File

@ -16,6 +16,16 @@
#pragma once
#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)
@ -38,6 +48,33 @@ public:
BYTE msb[256];
} 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 {
eCmdTestUnitReady = 0x00,
eCmdRezero = 0x01,
@ -79,11 +116,7 @@ public:
public:
// Basic Functions
#ifdef RASCSI
SCSIDEV();
#else
SCSIDEV(Device *dev);
#endif // RASCSI
// Constructor
void FASTCALL Reset();
@ -195,5 +228,9 @@ private:
scsi_t scsi;
// Internal data
// Sequence number for the Nuvolink. This really belongs somewhere else,
// but it goes here for now.
BYTE m_sequence_number = 0;
};

View File

@ -46,7 +46,7 @@ SCSINuvolink::SCSINuvolink() : Disk()
// Nuvolink
disk.id = MAKEID('S', 'C', 'N', 'L');
#if defined(RASCSI) && defined(__linux__) && !defined(BAREMETAL)
#if defined(__linux__) && !defined(BAREMETAL)
// TAP Driver Generation
tap = new CTapDriver();
m_bTapEnable = tap->Init();
@ -77,7 +77,7 @@ SCSINuvolink::SCSINuvolink() : Disk()
SCSINuvolink::~SCSINuvolink()
{
LOGTRACE("SCSINuvolink Destructor");
#if defined(RASCSI) && !defined(BAREMETAL)
#if !defined(BAREMETAL)
// TAP driver release
if (tap) {
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
@ -479,14 +479,47 @@ int FASTCALL SCSINuvolink::ReceivePacket()
if(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 it doesn't match, check to see if this is a broadcast message
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;
return -1;
}else{
packet_is_bcast_or_mcast = TRUE;
}
}else{
packet_is_bcast_or_mcast = FALSE;
}
// Discard if it exceeds the buffer size
@ -496,13 +529,7 @@ int FASTCALL SCSINuvolink::ReceivePacket()
return -1;
}
// TransferPacket(packet_len, packet_buff);
return packet_len;
// // Store in receive buffer
// if (packet_len > 0) {
// packet_enable = TRUE;
// }
}

View File

@ -56,7 +56,14 @@ public:
// Send a packet
int FASTCALL ReceivePacket();
// 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:
enum nuvolink_command_enum : BYTE {
@ -95,10 +102,6 @@ private:
// TAP valid flag
BYTE mac_addr[6];
// MAC Addres
int packet_len;
// Receive packet size
BYTE packet_buf[0x1000];
// Receive packet buffer
BOOL packet_enable;
// Received packet valid
#endif // RASCSI && !BAREMETAL

View File

@ -632,6 +632,29 @@ void FASTCALL GPIOBUS::SetSEL(BOOL ast)
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
SetSignal(PIN_SEL, ast);
}
@ -1532,15 +1555,25 @@ void FASTCALL GPIOBUS::SetSignal(int pin, BOOL ast)
//---------------------------------------------------------------------------
BOOL FASTCALL GPIOBUS::WaitSignal(int pin, BOOL ast)
{
DWORD now;
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
now = SysTimer::GetTimerLow();
// Calculate timeout (3000ms)
timeout = 3000 * 1000;
// end immediately if the signal has changed
do {
// Immediately upon receiving a reset

View File

@ -434,6 +434,30 @@
//
//---------------------------------------------------------------------------
#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
int FASTCALL SendHandShake(BYTE *buf, int count);
// 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
// SEL signal interrupt
@ -536,16 +569,10 @@ private:
// SCSI I/O signal control
void FASTCALL MakeTable();
// Create work data
void FASTCALL SetControl(int pin, BOOL ast);
// Set Control Signal
void FASTCALL SetMode(int pin, int 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);
// Wait for a signal to change
// Wait up to 3s for a signal to change
// Interrupt control
void FASTCALL DisableIRQ();
// IRQ Disabled

View File

@ -54,6 +54,11 @@ public:
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)
{
return phase_table[mci];
@ -122,6 +127,12 @@ public:
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:
static const phase_t phase_table[8];
// フェーズテーブル