Kaynağa Gözat

Merge pull request #114 from erichelgeson/eric/newCmds

Four new commands & some Sense
Eric Helgeson 3 yıl önce
ebeveyn
işleme
c2c3397b72
4 değiştirilmiş dosya ile 241 ekleme ve 57 silme
  1. 42 27
      platformio.ini
  2. 176 30
      src/BlueSCSI.cpp
  3. 9 0
      src/scsi_mode.h
  4. 14 0
      src/scsi_sense.h

+ 42 - 27
platformio.ini

@@ -32,50 +32,65 @@ board_build.core = maple
 
 [env:STM32F1-XCVR]
 extends = env:STM32F1
-build_flags = ${env.build_flags} 
+build_flags = ${env.build_flags}
     -DXCVR
     -D BUILD_TAGS="\"-XCVR\""
 
-[env:STM32F1-USB]
-extends = env:STM32F1
-build_flags = ${env.build_flags} 
-    -D BUILD_TAGS="\"-USB\""
+[env:STM32F1-USB-128MHz]
+# Max overclock for STM32
+# Can use for APM32F1 as well.
+extends = env:STM32F1-USB
+board_build.f_cpu = 128000000L
+build_flags = ${env.build_flags}
+    -D BUILD_TAGS="\"-USB-128MHz\""
+
+[env:STM32F1-USB-96MHz]
+# Slight overclock for STM32
+# Use for APM32F1's - it's default clock is 96MHz and runs unstable at 72MHz(STM32F1's default)
+extends = env:STM32F1-USB
+# Explicilty define the multiplier as maple only handles a few cases.
+build_flags = ${env.build_flags}
+    -D BUILD_TAGS="\"-USB-96MHz\""
     -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
     -D USBCON
     -D USBD_VID=0x0483
     -D USB_MANUFACTURER="Unknown"
     -D USB_PRODUCT="\"BLUEPILL_F103C8\""
     -D HAL_PCD_MODULE_ENABLED
-
-[env:STM32F1-USB-128MHZ]
-extends = env:STM32F1
-board_build.f_cpu = 128000000L
-build_flags = ${env.build_flags} 
-    -D BUILD_TAGS="\"-USB-128MHZ\""
-
-[env:APM32F1]
-# The APM32F1's default clock is 96MHz and runs unstable at 72MHz(STM32F1's default)
-extends = env:STM32F1
-# Explicilty define the multiplier as maple only handles a few cases.
-build_flags = ${env.build_flags} 
-    -D BUILD_TAGS="\"-APM32\""
     -DBOARD_RCC_PLLMUL=RCC_PLLMUL_12 #96000000L
 
-[env:APM32F1-USB]
-# The APM32F1's default clock is 96MHz and runs unstable at 72MHz(STM32F1's default)
-extends = env:APM32F1
-# Explicilty define the multiplier as maple only handles a few cases.
-build_flags = ${env.build_flags} 
-    -D BUILD_TAGS="\"-APM32-USB\""
+# TODO: Find out why USB build flags get trampled when extending an extended env.
+[env:STM32F1-USB]
+platform = ststm32
+board = genericSTM32F103C8
+board_build.mcu = stm32f103c8t6
+board_build.core = maple
+board_build.f_cpu = 128000000L
+framework = arduino
+lib_deps =
+    greiman/SdFat @ ^2.0.6
+upload_protocol = dfu
+; Different gcc versions produce much different binaries in terms of speed.
+platform_packages = platformio/toolchain-gccarmnoneeabi@1.90301.200702
+build_flags =
+    -D BUILD_TAGS="\"-USB\""
     -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
     -D USBCON
     -D USBD_VID=0x0483
     -D USB_MANUFACTURER="Unknown"
     -D USB_PRODUCT="\"BLUEPILL_F103C8\""
     -D HAL_PCD_MODULE_ENABLED
-    -DBOARD_RCC_PLLMUL=RCC_PLLMUL_12 #96000000L
-# Or go all out at 128Mhz, your call :)
-#board_build.f_cpu = 128000000L
+    -w
+    -DARDUINO_GENERIC_STM32F103C
+    -DARDUINO_LIB_DISCOVERY_PHASE
+    -DARDUINO=10813
+    -DARDUINO_ARCH_STM32
+    -DDEBUG_LEVEL=DEBUG_NONE
+    -O2
+build_unflags =
+    -Os
+    -DARDUINO_ARCH_STM32F1
+upload_flags = -c set CPUTAPID 0
 
 ; [env:debug]
 ; build_type = debug

+ 176 - 30
src/BlueSCSI.cpp

@@ -41,6 +41,7 @@
 #include "scsi_cmds.h"
 #include "scsi_sense.h"
 #include "scsi_status.h"
+#include "scsi_mode.h"
 
 #ifdef USE_STM32_DMA
 #warning "warning USE_STM32_DMA"
@@ -54,7 +55,7 @@
 #define NUM_SCSIID  7          // Maximum number of supported SCSI-IDs (The minimum is 0)
 #define NUM_SCSILUN 2          // Maximum number of LUNs supported     (The minimum is 0)
 #define READ_PARITY_CHECK 0    // Perform read parity check (unverified)
-
+#define SCSI_BUF_SIZE 512      // Size of the SCSI Buffer
 // HDD format
 #define MAX_BLOCKSIZE 2048     // Maximum BLOCK size
 
@@ -238,14 +239,15 @@ volatile bool m_isBusReset = false;   // Bus reset
 volatile bool m_resetJmp = false;     // Call longjmp on reset
 jmp_buf       m_resetJmpBuf;
 
-byte          scsi_id_mask;           // Mask list of responding SCSI IDs
-byte          m_id;                   // Currently responding SCSI-ID
-byte          m_lun;                  // Logical unit number currently responding
-byte          m_sts;                  // Status byte
-byte          m_msg;                  // Message bytes
-HDDIMG       *m_img;                  // HDD image for current SCSI-ID, LUN
-byte          m_buf[MAX_BLOCKSIZE];   // General purpose buffer
-byte          m_msb[256];             // Command storage bytes
+byte          scsi_id_mask;              // Mask list of responding SCSI IDs
+byte          m_id;                      // Currently responding SCSI-ID
+byte          m_lun;                     // Logical unit number currently responding
+byte          m_sts;                     // Status byte
+byte          m_msg;                     // Message bytes
+HDDIMG       *m_img;                     // HDD image for current SCSI-ID, LUN
+byte          m_buf[MAX_BLOCKSIZE];      // General purpose buffer
+byte          m_scsi_buf[SCSI_BUF_SIZE]; // Buffer for SCSI READ/WRITE Buffer
+byte          m_msb[256];                // Command storage bytes
 
 /*
  *  Data byte to BSRR register setting value and parity table
@@ -276,7 +278,7 @@ uint32_t db_bsrr[256];
 //#undef PTY
 
 // Log File
-#define VERSION "1.1-SNAPSHOT-20220407"
+#define VERSION "1.1-SNAPSHOT-20220522"
 #define LOG_FILENAME "LOG.txt"
 FsFile LOG_FILE;
 
@@ -679,7 +681,7 @@ void initFileLog(int success_mhz) {
   LOG_FILE.println(SDFAT_FILE_TYPE);
   LOG_FILE.print("SdFat version: ");
   LOG_FILE.println(SD_FAT_VERSION_STR);
-  LOG_FILE.print("SD Format: ");
+  LOG_FILE.print("Sd Format: ");
   switch(SD.vol()->fatType()) {
     case FAT_TYPE_EXFAT:
     LOG_FILE.println("exFAT");
@@ -1239,7 +1241,7 @@ byte onModeSenseCommand(byte scsi_cmd, byte dbd, byte cmd2, uint32_t len)
   int pageCode = cmd2 & 0x3F;
   int pageControl = cmd2 >> 6;
   int a = 4;
-  if(scsi_cmd == 0x5A) a = 8;
+  if(scsi_cmd == SCSI_MODE_SENSE10) a = 8;
 
   if(dbd == 0) {
     byte c[8] = {
@@ -1252,21 +1254,21 @@ byte onModeSenseCommand(byte scsi_cmd, byte dbd, byte cmd2, uint32_t len)
     a += 8;
   }
   switch(pageCode) {
-  case 0x3F:
-  case 0x01: // Read/Write Error Recovery
-    m_buf[a + 0] = 0x01;
+  case SCSI_SENSE_MODE_ALL:
+  case SCSI_SENSE_MODE_READ_WRITE_ERROR_RECOVERY:
+    m_buf[a + 0] = SCSI_SENSE_MODE_READ_WRITE_ERROR_RECOVERY;
     m_buf[a + 1] = 0x0A;
     a += 0x0C;
-    if(pageCode != 0x3F) break;
+    if(pageCode != SCSI_SENSE_MODE_ALL) break;
 
-  case 0x02: // Disconnect-Reconnect page
-    m_buf[a + 0] = 0x02;
+  case SCSI_SENSE_MODE_DISCONNECT_RECONNECT:
+    m_buf[a + 0] = SCSI_SENSE_MODE_DISCONNECT_RECONNECT;
     m_buf[a + 1] = 0x0A;
     a += 0x0C;
-    if(pageCode != 0x3f) break;
+    if(pageCode != SCSI_SENSE_MODE_ALL) break;
 
-  case 0x03:  //Drive parameters
-    m_buf[a + 0] = 0x03; //Page code
+  case SCSI_SENSE_MODE_FORMAT_DEVICE:  //Drive parameters
+    m_buf[a + 0] = SCSI_SENSE_MODE_FORMAT_DEVICE; //Page code
     m_buf[a + 1] = 0x16; // Page length
     if(pageControl != 1) {
       m_buf[a + 11] = 0x3F;//Number of sectors / track
@@ -1275,10 +1277,10 @@ byte onModeSenseCommand(byte scsi_cmd, byte dbd, byte cmd2, uint32_t len)
       m_buf[a + 15] = 0x1; // Interleave
     }
     a += 0x18;
-    if(pageCode != 0x3F) break;
+    if(pageCode != SCSI_SENSE_MODE_ALL) break;
 
-  case 0x04:  //Drive parameters
-    m_buf[a + 0] = 0x04; //Page code
+  case SCSI_SENSE_MODE_DISK_GEOMETRY:  //Drive parameters
+    m_buf[a + 0] = SCSI_SENSE_MODE_DISK_GEOMETRY; //Page code
     m_buf[a + 1] = 0x16; // Page length
     if(pageControl != 1) {
       unsigned cylinders = bc / (16 * 63);
@@ -1288,19 +1290,28 @@ byte onModeSenseCommand(byte scsi_cmd, byte dbd, byte cmd2, uint32_t len)
       m_buf[a + 5] = 16;   //Number of heads
     }
     a += 0x18;
-    if(pageCode != 0x3F) break;
-  case 0x30:
+    if(pageCode != SCSI_SENSE_MODE_ALL) break;
+  case SCSI_SENSE_MODE_FLEXABLE_GEOMETRY:
+    m_buf[a + 0] = SCSI_SENSE_MODE_FLEXABLE_GEOMETRY;
+    m_buf[a + 1] = 0x1E;  // Page length
+    m_buf[a + 2] = 0x03E8; // Transfer rate 1 mbit/s
+    m_buf[a + 4] = 16; // Number of heads
+    m_buf[a + 5] = 18; // Sectors per track
+    m_buf[a + 6] = 0x2000; // Data bytes per sector
+    a += 0x1E;
+    if(pageCode != SCSI_SENSE_MODE_ALL) break;
+  case SCSI_SENSE_MODE_VENDOR_APPLE:
     {
       const byte page30[0x14] = {0x41, 0x50, 0x50, 0x4C, 0x45, 0x20, 0x43, 0x4F, 0x4D, 0x50, 0x55, 0x54, 0x45, 0x52, 0x2C, 0x20, 0x49, 0x4E, 0x43, 0x20};
-      m_buf[a + 0] = 0x30; // Page code
+      m_buf[a + 0] = SCSI_SENSE_MODE_VENDOR_APPLE; // Page code
       m_buf[a + 1] = sizeof(page30); // Page length
       if(pageControl != 1) {
         memcpy(&m_buf[a + 2], page30, sizeof(page30));
       }
       a += 2 + sizeof(page30);
-      if(pageCode != 0x3F) break;
+      if(pageCode != SCSI_SENSE_MODE_ALL) break;
     }
-    break; // Don't want 0x3F falling through to error condition
+    break; // Don't want SCSI_SENSE_MODE_ALL falling through to error condition
 
   default:
     m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
@@ -1334,10 +1345,12 @@ byte onModeSelectCommand(byte scsi_cmd, byte flags, uint32_t len)
   //0 0 0 8 0 0 0 0 0 0 2 0 0 2 10 0 1 6 24 10 8 0 0 0
   //I believe mode page 0 set to 10 00 is Disable Unit Attention
   //Mode page 1 set to 24 10 08 00 00 00 is TB and PER set, read retry count 16, correction span 8
+  #if DEBUG > 0
   for (unsigned i = 0; i < len; i++) {
     LOGHEX(m_buf[i]);LOG(" ");
   }
   LOGN("");
+  #endif
   return SCSI_STATUS_GOOD;
 }
 
@@ -1354,6 +1367,127 @@ byte onTestUnitReady()
   }
   return SCSI_STATUS_GOOD;
 }
+/*
+ * ReZero Unit - Move to Logical Block Zero in file.
+ */
+byte onReZeroUnit() {
+  LOGN("-ReZeroUnit");
+  // Make sure we have an image with atleast a first byte.
+  // Actually seeking to the position wont do anything, so dont.
+  return checkBlockCommand(0, 0);
+}
+
+/*
+ * WriteBuffer - Used for testing buffer, no change to medium
+ */
+byte onWriteBuffer(byte mode, uint32_t allocLength)
+{
+  LOGN("-WriteBuffer");
+  LOGHEXN(mode);
+  LOGHEXN(allocLength);
+
+  if (mode == MODE_COMBINED_HEADER_DATA && (allocLength - 4) <= SCSI_BUF_SIZE)
+  {
+    byte tmp[allocLength];
+    readDataPhase(allocLength, tmp);
+    // Drop header
+    memcpy(m_scsi_buf, (&tmp[4]), allocLength - 4);
+    #if DEBUG > 0
+    for (unsigned i = 0; i < allocLength; i++) {
+      LOGHEX(tmp[i]);LOG(" ");
+    }
+    LOGN("");
+    #endif
+    return SCSI_STATUS_GOOD;
+  }
+  else if ( mode == MODE_DATA && allocLength <= SCSI_BUF_SIZE)
+  {
+    readDataPhase(allocLength, m_scsi_buf);
+    #if DEBUG > 0
+    for (unsigned i = 0; i < allocLength; i++) {
+      LOGHEX(m_scsi_buf[i]);LOG(" ");
+    }
+    LOGN("");
+    #endif
+    return SCSI_STATUS_GOOD;
+  }
+  else
+  {
+    m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
+    m_addition_sense = SCSI_ASC_INVALID_FIELD_IN_CDB;
+    return SCSI_STATUS_CHECK_CONDITION;
+  }
+}
+
+/*
+ * ReadBuffer - Used for testing buffer, no change to medium
+ */
+byte onReadBuffer(byte mode, uint32_t allocLength)
+{
+  LOGN("-ReadBuffer");
+  LOGHEXN(mode);
+  LOGHEXN(allocLength);
+
+  if (mode == MODE_COMBINED_HEADER_DATA)
+  {
+    byte scsi_buf_response[SCSI_BUF_SIZE + 4];
+    // four byte read buffer header
+    scsi_buf_response[0] = 0;
+    scsi_buf_response[1] = (SCSI_BUF_SIZE >> 16) & 0xff;
+    scsi_buf_response[2] = (SCSI_BUF_SIZE >> 8) & 0xff;
+    scsi_buf_response[3] = SCSI_BUF_SIZE & 0xff;
+    // actual data
+    memcpy((&scsi_buf_response[4]), m_scsi_buf, SCSI_BUF_SIZE);
+
+    writeDataPhase(SCSI_BUF_SIZE + 4, scsi_buf_response);
+
+    #if DEBUG > 0
+    for (unsigned i = 0; i < allocLength; i++) {
+      LOGHEX(m_scsi_buf[i]);LOG(" ");
+    }
+    LOGN("");
+    #endif
+    return SCSI_STATUS_GOOD;
+  }
+  else if (mode == MODE_DATA)
+  {
+    writeDataPhase(allocLength, m_scsi_buf);
+    #if DEBUG > 0
+    for (unsigned i = 0; i < allocLength; i++) {
+      LOGHEX(m_scsi_buf[i]);LOG(" ");
+    }
+    LOGN("");
+    #endif
+    return SCSI_STATUS_GOOD;
+  }
+  else
+  {
+    m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
+    m_addition_sense = SCSI_ASC_INVALID_FIELD_IN_CDB;
+    return SCSI_STATUS_CHECK_CONDITION;
+  }
+}
+
+/*
+ * On Send Diagnostic
+ */
+byte onSendDiagnostic(byte flags)
+{
+  int self_test = flags & 0x4;
+  LOGN("-SendDiagnostic");
+  LOGHEXN(flags);
+  if(self_test)
+  {
+    // Don't actually do a test, we're good.
+    return SCSI_STATUS_GOOD;
+  }
+  else
+  {
+    m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
+    m_addition_sense = SCSI_ASC_INVALID_FIELD_IN_CDB;
+    return SCSI_STATUS_CHECK_CONDITION;
+  }
+}
 
 /*
  * MsgIn2.
@@ -1521,8 +1655,9 @@ void loop()
     LOGN("[Test Unit Ready]");
     m_sts |= onTestUnitReady();
     break;
-  case SCSI_REZERO_UNIT: // TODO: Implement me!
+  case SCSI_REZERO_UNIT:
     LOGN("[Rezero Unit]");
+    m_sts |= onReZeroUnit();
     break;
   case SCSI_REQUEST_SENSE:
     LOGN("[RequestSense]");
@@ -1596,6 +1731,17 @@ void loop()
     LOGN("[ModeSense10]");
     m_sts |= onModeSenseCommand(cmd[0], cmd[1] & 0x80, cmd[2], ((uint32_t)cmd[7] << 8) | cmd[8]);
     break;
+  case SCSI_WRITE_BUFFER:
+    LOGN("[WriteBuffer]");
+    m_sts |= onWriteBuffer(cmd[1] & 7, ((uint32_t)cmd[6] << 16) | ((uint32_t)cmd[7] << 8) | cmd[8]);
+    break;
+  case SCSI_READ_BUFFER:
+    LOGN("[ReadBuffer]");
+    m_sts |= onReadBuffer(cmd[1] & 7, ((uint32_t)cmd[6] << 16) | ((uint32_t)cmd[7] << 8) | cmd[8]);
+    break;
+  case SCSI_SEND_DIAG:
+    m_sts |= onSendDiagnostic(cmd[1]);
+    break;
   default:
     LOGN("[*Unknown]");
     m_sts |= SCSI_STATUS_CHECK_CONDITION;

+ 9 - 0
src/scsi_mode.h

@@ -0,0 +1,9 @@
+#ifndef __SCSI_MODE_H__
+#define __SCSI_MODE_H__
+
+#define MODE_COMBINED_HEADER_DATA   0x00
+#define MODE_NOT_SUPPORTED          0x01
+#define MODE_DATA                   0x02
+#define MODE_DESCRIPTOR             0x03
+
+#endif

+ 14 - 0
src/scsi_sense.h

@@ -29,4 +29,18 @@
 #define SCSI_ASC_CANNOT_READ_MEDIUM_INCOMPATIBLE_FORMAT         0x3002
 #define SCSI_ASC_MEDIUM_NOT_PRESENT                             0x3A00
 #define SCSI_ASC_LUN_NOT_READY_MANUAL_INTERVENTION_REQUIRED     0x0403
+
+
+// SCSI mode page codes
+#define SCSI_SENSE_MODE_VENDOR                      0x00
+#define SCSI_SENSE_MODE_READ_WRITE_ERROR_RECOVERY   0x01
+#define SCSI_SENSE_MODE_DISCONNECT_RECONNECT        0x02
+#define SCSI_SENSE_MODE_FORMAT_DEVICE               0x03
+#define SCSI_SENSE_MODE_DISK_GEOMETRY               0x04
+#define SCSI_SENSE_MODE_FLEXABLE_GEOMETRY           0x05
+#define SCSI_SENSE_MODE_VENDOR_APPLE                0x30
+
+#define SCSI_SENSE_MODE_ALL                         0x3F
+
+
 #endif