From 968f3336af2d1dc9d6eed63c901086113c4a9786 Mon Sep 17 00:00:00 2001 From: David Kuder Date: Sat, 11 Jun 2022 10:59:23 -0400 Subject: [PATCH] Control channel framework Building the framework for communicating with the GreenSCSI command line over the SCSI bus. --- src/cmd.ino | 9 ++++ src/config.h | 2 + src/control.ino | 111 +++++++++++++++++++++++++++++++++++++++++++++++ src/defaults.ino | 20 ++++++++- src/scsi_defs.h | 7 +++ 5 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/control.ino diff --git a/src/cmd.ino b/src/cmd.ino index 8e096c2..9bb75e6 100755 --- a/src/cmd.ino +++ b/src/cmd.ino @@ -1506,6 +1506,12 @@ void createcmd(int argc, char **argv) { goto success; } #endif /* SUPPORT_TAPE */ +#if SUPPORT_CONTROL + if(!strcasecmp(argv[1], "control")) { + ConfigureControl(h, NULL); + goto success; + } +#endif /* SUPPORT_CONTROL */ //failure: errorlevel = -1; @@ -1711,6 +1717,9 @@ void saveconfig(int argc, char **argv) { if(h->m_enabled) { // The create command automatically changes directory to the created object switch(h->m_type) { + case DEV_PROCESSOR: + config_file.print("create control\r\n"); + break; case DEV_DISK: config_file.print("create disk\r\n"); break; diff --git a/src/config.h b/src/config.h index e260b4a..c1814e4 100755 --- a/src/config.h +++ b/src/config.h @@ -22,6 +22,7 @@ #define MAX_BLOCKSIZE (1 << 15) // Maximum BLOCK size (2048 to 8192 tested, 16384 had issues) #define SCSI_INQUIRY_RESPONSE_SIZE 96 +extern uint8_t SCSI_INQUIRY_RESPONSE[][SCSI_INQUIRY_RESPONSE_SIZE]; // Supported Device Types #define SUPPORT_DISK true @@ -29,6 +30,7 @@ #define SUPPORT_TAPE false #define SUPPORT_MO false #define SUPPORT_INITIATOR true +#define SUPPORT_CONTROL true // Compatibility Settings #define SUPPORT_SASI false // Enable SASI compatiblity for Sharp X68000 diff --git a/src/control.ino b/src/control.ino new file mode 100644 index 0000000..12230c1 --- /dev/null +++ b/src/control.ino @@ -0,0 +1,111 @@ +#include "config.h" +#include "scsi_defs.h" + +#if SUPPORT_CONTROL +/* + * RECEIVE Command processing. + */ +void onControlReceiveCommand(uint32_t adds, uint32_t len) +{ + LOG("-R "); + LOGHEX4N(len); + + if(!m_sel) { + m_sts |= STATUS_CHECK; + m_phase = PHASE_STATUSIN; + return; + } + + switch(m_cmd[1] & 0x3) { + case 0: + if(len == 0) return; + break; + case 1: // Fixed + break; + case 2: // SILI + break; + case 3: // Illegal Request + m_sts = 0x02; + m_sel->m_sense.m_key = ILLEGAL_REQUEST; + m_sel->m_sense.m_code = INVALID_FIELD_IN_CDB; /* "Invalid field in CDB" */ + m_sel->m_sense.m_key_specific[0] = ERROR_IN_OPCODE; /* "Error in Byte 1" */ + m_sel->m_sense.m_key_specific[1] = 0x00; + m_sel->m_sense.m_key_specific[2] = 0x01; + m_phase = PHASE_STATUSIN; + return; + } + + LED_ON(); + writeDataPhase(len, m_responsebuffer); + LED_OFF(); + + m_phase = PHASE_STATUSIN; +} + +/* + * SEND Command processing. + */ +void onControlSendCommand(uint32_t adds, uint32_t len) +{ + LOG("-W "); + LOGHEX4N(len); + + if(!m_sel) { + m_sts |= STATUS_CHECK; + m_phase = PHASE_STATUSIN; + return; + } + if(len > MAX_BLOCKSIZE) { + m_sel->m_sense.m_key = ILLEGAL_REQUEST; + m_sel->m_sense.m_code = INVALID_FIELD_IN_CDB; /* "Invalid field in CDB" */ + m_sel->m_sense.m_key_specific[0] = ERROR_IN_OPCODE; /* "Error in Byte 4" */ + m_sel->m_sense.m_key_specific[1] = 0x00; + m_sel->m_sense.m_key_specific[2] = 0x04; + m_sts |= STATUS_CHECK; + m_phase = PHASE_STATUSIN; + return; + } + + LED_ON(); + readDataPhase(len, m_responsebuffer); + LED_OFF(); + + m_phase = PHASE_STATUSIN; +} + +void ControlReceive6CommandHandler() { + LOG("[Receive6]"); + onControlReceiveCommand((((uint32_t)m_cmd[1] & 0x1F) << 16) | ((uint32_t)m_cmd[2] << 8) | m_cmd[3], (m_cmd[4] == 0) ? 0x100 : m_cmd[4]); +} + +void ControlSend6CommandHandler() { + LOG("[Send6]"); + onControlSendCommand((((uint32_t)m_cmd[1] & 0x1F) << 16) | ((uint32_t)m_cmd[2] << 8) | m_cmd[3], (m_cmd[4] == 0) ? 0x100 : m_cmd[4]); +} + +void ConfigureControlHandlers(VirtualDevice_t *vdev) { + for(int c = 0; c < 256; c++) + vdev->m_handler[c] = &UnknownCommandHandler; + + vdev->m_handler[CMD_TEST_UNIT_READY] = &TestUnitCommandHandler; + vdev->m_handler[CMD_REQUEST_SENSE] = &RequestSenseCommandHandler; + vdev->m_handler[CMD_READ6] = &ControlReceive6CommandHandler; + vdev->m_handler[CMD_WRITE6] = &ControlSend6CommandHandler; + vdev->m_handler[CMD_INQUIRY] = &InquiryCommandHandler; + vdev->m_handler[CMD_SEND_DIAGNOSTIC] = &SendDiagnosticCommandHandler; +} + +// If config file exists, read the first three lines and copy the contents. +// File must be well formed or you will get junk in the SCSI Vendor fields. +void ConfigureControl(VirtualDevice_t *vdev, const char *image_name) { + for(int i = 0; SCSI_INQUIRY_RESPONSE[i][0] != 0xff; i++) { + if(SCSI_INQUIRY_RESPONSE[i][0] == DEV_PROCESSOR) { + memcpy(vdev->m_inquiryresponse, SCSI_INQUIRY_RESPONSE[i], SCSI_INQUIRY_RESPONSE_SIZE); + break; + } + } + + vdev->m_type = DEV_PROCESSOR; + ConfigureControlHandlers(vdev); +} +#endif diff --git a/src/defaults.ino b/src/defaults.ino index 8e81d30..1ad0248 100755 --- a/src/defaults.ino +++ b/src/defaults.ino @@ -2,7 +2,7 @@ // SCSI Drive Vendor information -static uint8_t SCSI_INQUIRY_RESPONSE[][SCSI_INQUIRY_RESPONSE_SIZE] = { +uint8_t SCSI_INQUIRY_RESPONSE[][SCSI_INQUIRY_RESPONSE_SIZE] = { #if SUPPORT_SASI { 0x00, //Device type @@ -163,6 +163,24 @@ static uint8_t SCSI_INQUIRY_RESPONSE[][SCSI_INQUIRY_RESPONSE_SIZE] = { }, #endif /* SUPPORT_TAPE */ + +#if SUPPORT_CONTROL +{ + DEV_PROCESSOR, //device type + 0x80, //RMB = 0 + 0x03, //ISO, ECMA, ANSI version + 0x02, //Response data format + 37 - 4, //Additional data length + 0, //Reserve + 0x00, // Support function + 0x00, // Support function + 'G', 'R', 'N', 'S', 'C', 'S', 'I', ' ', // vendor 8 + 'G', 'R', 'E', 'E', 'N', 'S', 'C', 'S', 'I', 'C', 'T','R', 'L', ' ', ' ', ' ', // product 16 + 'G', 'S', 'C', '0', // version 4 + 0 +}, +#endif /* SUPPORT_CONTROL */ + // Invalid entry to mark end of data { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, diff --git a/src/scsi_defs.h b/src/scsi_defs.h index 2faf31a..0614d55 100755 --- a/src/scsi_defs.h +++ b/src/scsi_defs.h @@ -93,7 +93,14 @@ */ #define DEV_DISK 0x00 #define DEV_TAPE 0x01 +#define DEV_PRINTER 0x02 +#define DEV_PROCESSOR 0x03 +#define DEV_WORM 0x04 #define DEV_OPTICAL 0x05 +#define DEV_SCANNER 0x06 +#define DEV_OMS 0x07 +#define DEV_CHANGER 0x08 +#define DEV_COMM 0x09 /* * SCSI MESSAGE CODES