Procházet zdrojové kódy

Initial XEBEX support

Per Mårtensson před 5 měsíci
rodič
revize
cc740b2c88
8 změnil soubory, kde provedl 329 přidání a 151 odebrání
  1. 6 0
      sw/blacksasi.json
  2. 2 65
      sw/include/blacksasi.h
  3. 74 1
      sw/include/config.h
  4. 5 0
      sw/include/scsi_cmds.h
  5. 5 4
      sw/platformio.ini
  6. 66 0
      sw/src/config.cpp
  7. 1 0
      sw/src/gpio.cpp
  8. 170 81
      sw/src/main.cpp

+ 6 - 0
sw/blacksasi.json

@@ -0,0 +1,6 @@
+{
+    "controller" : "XEBEC",
+    "vendor" : "Seagate",
+    "model" : "ST410800N",
+    "version" : "1.0"
+}

+ 2 - 65
sw/include/blacksasi.h

@@ -159,7 +159,7 @@ void finalizeFileLog(void);
 #define MAX_SCSIID  7          // Maximum number of supported SCSI-IDs (The minimum is 0)
 #define MAX_SCSILUN 8          // Maximum number of LUNs supported     (The minimum is 0)
 #define NUM_SCSIID  MAX_SCSIID // Number of enabled SCSI IDs
-#define NUM_SCSILUN 1          // Number of enabled LUNs
+#define NUM_SCSILUN 2          // Number of enabled LUNs
 #define READ_PARITY_CHECK 0    // Perform read parity check (unverified)
 #define DEFAULT_SCSI_ID 1
 #define DEFAULT_SCSI_LUN 0
@@ -288,7 +288,7 @@ static uint32_t genBSRR(uint32_t data) {
   // DB0, DB1, DB2, DB4, DB5, DB6, DB7 in order
   uint8_t positions[] = {0UL, 1UL, 2UL, 3UL, 4UL, 5UL, 6UL, 7UL};
   uint8_t dbpPosition = 8UL;
-  int reqPosition = 0;
+  int reqPosition =  0;
   uint8_t bitsAsserted = 0;
 
  //PM2022 Fix this in better way since we now have the bits correct
@@ -332,67 +332,4 @@ static uint32_t genBSRR(uint32_t data) {
 
 
 
-struct SCSI_INQUIRY_DATA
-{
-  union
-  {
-  struct {
-    // bitfields are in REVERSE order for ARM
-    // byte 0
-    byte peripheral_device_type:5;
-    byte peripheral_qualifier:3;
-    // byte 1
-    byte reserved_byte2:7;
-    byte rmb:1;
-    // byte 2
-    byte ansi_version:3;
-    byte always_zero_byte3:5;
-    // byte 3
-    byte response_format:4;
-    byte reserved_byte4:2;
-    byte tiop:1;
-    byte always_zero_byte4:1;
-    // byte 4
-    byte additional_length;
-    // byte 5-6
-    byte reserved_byte5;
-    byte reserved_byte6;
-    // byte 7
-    byte sync:1;
-    byte always_zero_byte7_more:4;
-    byte always_zero_byte7:3;
-    // byte 8-15
-    char vendor[8];
-    // byte 16-31
-    char product[16];
-    // byte 32-35
-    char revision[4];
-    // byte 36
-    byte release;
-    // 37-46
-    char revision_date[10];
-  };
-  // raw bytes
-  byte raw[64];
-  };
-};
-
-// HDD image
-typedef __attribute__((aligned(4))) struct _SCSI_DEVICE
-{
-	FsFile        *m_file;                  // File object
-	uint64_t      m_fileSize;               // File size
-	uint16_t      m_blocksize;              // SCSI BLOCK size
-  uint16_t      m_rawblocksize;           // OPTICAL raw sector size
-  uint8_t       m_type;                   // SCSI device type
-  uint32_t      m_blockcount;             // blockcount
-  bool          m_raw;                    // Raw disk
-  SCSI_INQUIRY_DATA *inquiry_block;       // SCSI information
-  uint8_t       m_senseKey;               // Sense key
-  uint16_t      m_additional_sense_code;  // ASC/ASCQ 
-  bool          m_mode2;                  // MODE2 CDROM
-  uint8_t       m_sector_offset;          // optical sector offset for missing sync header
-} SCSI_DEVICE;
-
-
 #endif // __BLACKSASI_H__

+ 74 - 1
sw/include/config.h

@@ -3,6 +3,79 @@
 #include <SdFat.h>
 #include "sdios.h"
 #include "blacksasi.h"
-void readSCSIDeviceConfig(uint8_t disc);
+
+typedef enum
+{
+	S2S_CFG_QUIRKS_NONE = 0,
+	S2S_CFG_QUIRKS_APPLE = 1,
+	S2S_CFG_QUIRKS_OMTI = 2,
+	S2S_CFG_QUIRKS_XEBEC = 4,
+	S2S_CFG_QUIRKS_VMS = 8,
+	S2S_CFG_QUIRKS_X68000 = 16,
+} S2S_CFG_QUIRKS;
+
+struct SCSI_INQUIRY_DATA
+{
+  union
+  {
+  struct {
+    // bitfields are in REVERSE order for ARM
+    // byte 0
+    byte peripheral_device_type:5;
+    byte peripheral_qualifier:3;
+    // byte 1
+    byte reserved_byte2:7;
+    byte rmb:1;
+    // byte 2
+    byte ansi_version:3;
+    byte always_zero_byte3:5;
+    // byte 3
+    byte response_format:4;
+    byte reserved_byte4:2;
+    byte tiop:1;
+    byte always_zero_byte4:1;
+    // byte 4
+    byte additional_length;
+    // byte 5-6
+    byte reserved_byte5;
+    byte reserved_byte6;
+    // byte 7
+    byte sync:1;
+    byte always_zero_byte7_more:4;
+    byte always_zero_byte7:3;
+    // byte 8-15
+    char vendor[8];
+    // byte 16-31
+    char product[16];
+    // byte 32-35
+    char revision[4];
+    // byte 36
+    byte release;
+    // 37-46
+    char revision_date[10];
+  };
+  // raw bytes
+  byte raw[64];
+  };
+};
+// HDD image
+typedef __attribute__((aligned(4))) struct _SCSI_DEVICE
+{
+	FsFile        *m_file;                  // File object
+	uint64_t      m_fileSize;               // File size
+	uint16_t      m_blocksize;              // SCSI BLOCK size
+  uint16_t      m_rawblocksize;           // OPTICAL raw sector size
+  uint8_t       m_type;                   // SCSI device type
+  uint32_t      m_blockcount;             // blockcount
+  bool          m_raw;                    // Raw disk
+  SCSI_INQUIRY_DATA *inquiry_block;       // SCSI information
+  uint8_t       m_senseKey;               // Sense key
+  uint16_t      m_additional_sense_code;  // ASC/ASCQ 
+  bool          m_mode2;                  // MODE2 CDROM
+  uint8_t       m_sector_offset;          // optical sector offset for missing sync header
+  uint16_t      m_quirks;
+} SCSI_DEVICE;
+
+uint32 readSCSIDeviceConfig(SCSI_DEVICE *dev);
 uint32 readHWVersion();
 #endif // __BLACKSASI_CONFIG_H__

+ 5 - 0
sw/include/scsi_cmds.h

@@ -2,6 +2,11 @@
 #define __SCSI_CMDS_H__
 
 // defines for SCSI commands
+#define SCSI_XEBEB_INIT_DRIVE       0xC
+#define SCSI_XEBEB_WRITE_SECTOR_BUF 0xF
+#define SCSI_XEBEC_RAM_DIAGNOSTIC   0xE0
+#define SCSI_ZEBEC_DRIVE_DIAGNOSTIC 0xE4
+
 #define SCSI_TEST_UNIT_READY        0
 #define SCSI_REZERO_UNIT            0x1
 #define SCSI_REQUEST_SENSE          0x3

+ 5 - 4
sw/platformio.ini

@@ -12,17 +12,18 @@
 platform = ststm32
 board = blacksasi_f411m
 
-;board.variants_dir = /home/pm/project/stm32/BlackSASI/sw/variant/blacksasi_f411m
+board.variants_dir = /home/pm/project/stm32/BlackSASI/sw/variant/blacksasi_f411m
 
-board.variants_dir = C:\Users\martenssonp\projects\BlackSASI\sw\variant\blacksasi_f411m
+;board.variants_dir = C:\Users\martenssonp\projects\BlackSASI\sw\variant\blacksasi_f411m
 framework = arduino
 board_build.core = maple
 lib_deps =
   greiman/SdFat@^2.2.0
   bblanchon/ArduinoJson @ ^6.19.3
   ;https://github.com/ZulNs/STM32F1_RTC#master
-upload_protocol = stlink
-debug_tool = stlink
+upload_protocol = jlink
+
+debug_tool = jlink
 ; Different gcc versions produce much different binaries in terms of speed.
 ; 1.40804.0 ; 985kb/sec
 ; 1.60301.0 ; 1012kb/sec ***

+ 66 - 0
sw/src/config.cpp

@@ -0,0 +1,66 @@
+#include <Arduino.h>
+#include "config.h"
+#include "sdcard.h"
+#include "ArduinoJson.h"
+#include "blacksasi.h"
+extern SdFs SD;
+extern FsFile LOG_FILE;
+extern byte SCSI_INFO_BUF[SCSI_INFO_BUF_SIZE];
+extern SCSI_DEVICE scsi_device_list[NUM_SCSIID][NUM_SCSILUN]; // Maximum number
+// 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.
+uint32 readSCSIDeviceConfig(SCSI_DEVICE *dev) {
+
+  SCSI_INQUIRY_DATA *iq = dev->inquiry_block;
+
+  StaticJsonDocument<2048> config;
+  delay(1000);
+  FsFile config_file = SD.open("blacksasi.json", O_RDONLY);
+  char vendor[9];
+  char product[17];
+  char version[5];
+  memset(vendor, 0, sizeof(vendor));
+
+  if (!config_file.isOpen()) {
+    return 1;
+  }
+  
+  DeserializationError error = deserializeJson(config, config_file);
+  if (error){
+    Serial.println(F("Failed to read file"));
+    return 1;
+  }
+  String vendorx = config["vendor"];
+  uint16 len = (vendorx.length()>8?8:vendorx.length());
+  memset(&iq->vendor, 0, sizeof(vendor));
+  vendorx.toCharArray(vendor,len);
+  memcpy(&iq->vendor, vendor, len);
+
+  String productx = config["product"];
+  len = (productx .length()>16?16:productx .length());
+  memset(&iq->product, 0, sizeof(product));
+  productx.toCharArray(product,len);
+  memcpy(&iq->product, product, len);
+
+  String configx = config["version"];
+  len = (configx.length()>4?4:configx.length());
+  memset(&iq->revision, 0, sizeof(version));
+  configx.toCharArray(version,len);
+  memcpy(&iq->revision, version, len);
+
+  
+  dev->m_quirks=S2S_CFG_QUIRKS_NONE;
+  
+  if (config["controller"]){
+    String controller = config["controller"];
+    controller.toUpperCase();
+    if (controller=="XEBEC" )
+      dev->m_quirks=S2S_CFG_QUIRKS_XEBEC;
+  }
+  return 0;
+
+}
+uint32 readHWVersion(){
+    return((digitalRead(BOARD_REV_PIN0 ) == LOW) ) | ((digitalRead(BOARD_REV_PIN1 ) == LOW) ) << 1 | ((digitalRead(BOARD_REV_PIN2) == LOW) ) << 2;
+  
+}

+ 1 - 0
sw/src/gpio.cpp

@@ -53,6 +53,7 @@ bool gpioInit(void){
     pinMode(BOARD_SCSI_MSG, INPUT_PULLUP);
     pinMode(BOARD_SCSI_CD, INPUT_PULLUP);
     pinMode(BOARD_SCSI_REQ, INPUT_PULLUP);
+    pinMode(BOARD_SCSI_REQ2, INPUT_FLOATING);
     pinMode(BOARD_SCSI_IO, INPUT_PULLUP);
     TRANSCEIVER_IO_SET(vTAD,TR_INPUT);
 

+ 170 - 81
sw/src/main.cpp

@@ -47,13 +47,14 @@
                                 // 1: Debug information output to USB Serial
                                 // 2: Debug information output to LOG.txt (slow)
 
-#define VDS "2022-09-20"
+#define VDS "2025-01-04"
 
 // Log File
-#define VERSION "1.1-" VDS "-BLACKSASI"
+#define VERSION "1.2-" VDS "-BLACKSASI"
 #define LOG_FILENAME "LOG.txt"
 
 #include "blacksasi.h"
+#include "config.h"
 #include "scsi_cmds.h"
 #include "scsi_sense.h"
 #include "scsi_status.h"
@@ -114,6 +115,10 @@ SCSI_COMMAND_HANDLER(onReadTOC);
 SCSI_COMMAND_HANDLER(onReadDVDStructure);
 SCSI_COMMAND_HANDLER(onReadDiscInformation);
 
+SCSI_COMMAND_HANDLER(onFormat4);
+SCSI_COMMAND_HANDLER(onFormat6);
+SCSI_COMMAND_HANDLER(onReadXebec0x0C);
+
 static uint32_t MSFtoLBA(const byte *msf);
 static void LBAtoMSF(const uint32_t lba, byte *msf);
 
@@ -137,38 +142,6 @@ inline byte readIO(void)
   return bret;
 }
 
-// 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 readSCSIDeviceConfig(SCSI_DEVICE *dev) {
-  FsFile config_file = SD.open("scsi-config.txt", O_RDONLY);
-  if (!config_file.isOpen()) {
-    return;
-  }
-  SCSI_INQUIRY_DATA *iq = dev->inquiry_block;
-
-  char vendor[9];
-  memset(vendor, 0, sizeof(vendor));
-  config_file.readBytes(vendor, sizeof(vendor));
-  LOG_FILE.print("SCSI VENDOR: ");
-  LOG_FILE.println(vendor);
-  memcpy(&iq->vendor, vendor, 8);
-
-  char product[17];
-  memset(product, 0, sizeof(product));
-  config_file.readBytes(product, sizeof(product));
-  LOG_FILE.print("SCSI PRODUCT: ");
-  LOG_FILE.println(product);
-  memcpy(&iq->product, product, 16);
-
-  char version[5];
-  memset(version, 0, sizeof(version));
-  config_file.readBytes(version, sizeof(version));
-  LOG_FILE.print("SCSI VERSION: ");
-  LOG_FILE.println(version);
-  memcpy(&iq->revision, version, 4);
-  config_file.close();
-}
-
 
 
 bool VerifyISOPVD(SCSI_DEVICE *dev, unsigned sector_size, bool mode2)
@@ -290,7 +263,7 @@ void setup()
   }
     // Serial initialization
 #if DEBUG == 1
-  serial.begin(9600);
+  serial.begin(115200);
   // If using a USB->TTL monitor instead of USB serial monitor - you can uncomment this.
   //while (!Serial);
 #endif
@@ -307,8 +280,7 @@ void setup()
   }
 
   // SCSI commands that just need to return ok
-  scsi_command_table[SCSI_FORMAT_UNIT4] = onNOP;
-  scsi_command_table[SCSI_FORMAT_UNIT6] = onNOP;
+
   scsi_command_table[SCSI_REASSIGN_BLOCKS] = onNOP;
   scsi_command_table[SCSI_SEEK6] = onNOP;
   scsi_command_table[SCSI_SEEK10] = onNOP;
@@ -317,8 +289,14 @@ void setup()
   scsi_command_table[SCSI_RELEASE] = onNOP;
   scsi_command_table[SCSI_RESERVE] = onNOP;
   scsi_command_table[SCSI_TEST_UNIT_READY] = onNOP;
-  
+
+  scsi_command_table[SCSI_XEBEB_WRITE_SECTOR_BUF] = onNOP;
+  scsi_command_table[SCSI_XEBEC_RAM_DIAGNOSTIC ] = onNOP;
+  scsi_command_table[SCSI_ZEBEC_DRIVE_DIAGNOSTIC] = onNOP;
   // SCSI commands that have handlers
+    scsi_command_table[SCSI_XEBEB_INIT_DRIVE] = onReadXebec0x0C;
+    scsi_command_table[SCSI_FORMAT_UNIT4] = onFormat4;
+    scsi_command_table[SCSI_FORMAT_UNIT6] = onFormat6;
   scsi_command_table[SCSI_REZERO_UNIT] = onReZeroUnit;
   scsi_command_table[SCSI_REQUEST_SENSE] = onRequestSense;
   scsi_command_table[SCSI_READ6] = onRead6;
@@ -670,7 +648,7 @@ inline byte readHandshake(void)
   
   SCSI_OUT(vREQ,active);
   while( ! SCSI_IN(vACK));
-  NOP(10);
+  NOP(20); 
 
   byte r = readIO();
   SCSI_OUT(vREQ,inactive)
@@ -698,7 +676,7 @@ inline void writeHandshake(byte d)
   while(!SCSI_IN(vACK));
   // ACK.Fall to REQ.Raise delay 500ns(typ.) (DTC-510B)
   uint32_t bsrrCall = (db_bsrr[0xff] );
-  GPIOD->regs->BSRR = bsrrCall;  // DB=0xFF , SCSI_OUT(vREQ,inactive) //PM2022 should wirite data to bus
+  GPIOD->regs->BSRR = bsrrCall;  // DB=0xFF , SCSI_OUT(vREQ,inactive) //PM2022 should write data to bus
   SCSI_OUT(vREQ,inactive)
   // REQ.Raise to DB hold time 0ns
   SCSI_DB_INPUT() // (150ns)
@@ -752,7 +730,14 @@ void writeDataLoop(uint32_t blocksize, const byte* srcptr) {
     FETCH_BSRR_DB();
     WAIT_ACK_ACTIVE();
     REQ_OFF_DB_SET(bsrr_val);
-   NOP(10);
+    NOP(6);  
+    asm("NOP"); 
+    asm("NOP");
+    asm("NOP");
+    asm("NOP"); 
+    asm("NOP");
+    asm("NOP");
+  
   }while(srcptr < endptr);
   WAIT_ACK_INACTIVE();
   // Finish the last bus cycle, byte is already on DB.
@@ -830,7 +815,7 @@ void readDataLoop(uint32_t blockSize, byte* dstptr)
   // Start of the do/while and WAIT are already aligned to 8 bytes.
   do {
     WAIT_ACK_ACTIVE();
-NOP(10);
+    NOP(17);
 
     
     uint32_t ret = PDREG->IDR;
@@ -846,7 +831,7 @@ NOP(10);
     asm("nop");
   } while(dstptr<endptr);
   WAIT_ACK_ACTIVE();
-NOP(10);
+  NOP(17);
   uint32_t ret = PDREG->IDR;
   REQ_OFF();
   *dstptr = (byte)~(((ret ) & 0b11111111) );
@@ -865,7 +850,28 @@ void readDataPhase(int len, byte* p)
   // Bus settle delay 400ns. The following code was measured at 450ns before REQ asserted. STM32F103.
   readDataLoop(len, p);
 }
-
+void formatPhaseSD(SCSI_DEVICE *dev,uint32_t adds){
+  uint64_t pos = (uint64_t)adds * dev->m_blocksize;
+  dev->m_file->seekSet(pos);
+  uint32_t len = dev->m_fileSize;
+  m_buf[0]=0x6C;
+  LED_ACT_ON();
+  for(uint32_t i = 0; i < len; i++) {
+    dev->m_file->write(m_buf, 1);
+  }
+  LED_ACT_OFF();
+}
+void formatTrackPhaseSD(SCSI_DEVICE *dev,uint32_t adds){
+  uint64_t pos = (uint64_t)adds * dev->m_blocksize;
+  dev->m_file->seekSet(pos);
+  uint32_t len = dev->m_blocksize* (dev->m_blocksize==256?32:16);
+  m_buf[0]=0x6C;
+  LED_ACT_ON();
+  for(uint32_t i = 0; i < len; i++) {
+    dev->m_file->write(m_buf, 1);
+  }
+  LED_ACT_OFF();
+}
 /*
  * Data out phase.
  *  Write to SD card while reading len block.
@@ -956,10 +962,10 @@ void loop()
   //do {} while( SCSI_IN(vBSY) || !SCSI_IN(vSEL) || SCSI_IN(vRST));
   //LOG(" S:"); LOGHEX(readIO()); LOG(" ");
   // We're in SELECTION
-
+ 
   byte scsiid = readIO() & scsi_id_mask;
 
-  if(SCSI_IN(vIO) || (scsiid) == 0) {
+  if((SCSI_IN(vIO) || ((scsiid) == 0) && scsi_device_list[0][0].m_quirks!=S2S_CFG_QUIRKS_XEBEC)) {
     delayMicroseconds(1);
     return;
   }
@@ -1040,9 +1046,6 @@ void loop()
     }
   }
 
-
-  LOG("CMD:");
-
   SCSI_PHASE_CHANGE(SCSI_PHASE_COMMAND);
   SCSI_BSY_ACTIVE(); 
   TRANSCEIVER_IO_SET(vTAD,TR_INPUT);
@@ -1060,16 +1063,22 @@ void loop()
   // so just read it and re-read it again to get the
   // real command byte
   if(cmd[0] == SCSI_ICD_EXTENDED_CMD) { cmd[0] = readHandshake(); }
-
+  LOG("CMD:");
   LOGHEX(cmd[0]);
   // Command length selection, reception
   static const int cmd_class_len[8]={6,10,10,6,6,12,6,6};
   len = cmd_class_len[cmd[0] >> 5];
-  cmd[1] = readHandshake(); LOG(":");LOGHEX(cmd[1]);
-  cmd[2] = readHandshake(); LOG(":");LOGHEX(cmd[2]);
-  cmd[3] = readHandshake(); LOG(":");LOGHEX(cmd[3]);
-  cmd[4] = readHandshake(); LOG(":");LOGHEX(cmd[4]);
-  cmd[5] = readHandshake(); LOG(":");LOGHEX(cmd[5]);
+
+  cmd[1] = readHandshake(); 
+  cmd[2] = readHandshake(); 
+  cmd[3] = readHandshake();
+  cmd[4] = readHandshake(); 
+  cmd[5] = readHandshake(); 
+  LOG(":");LOGHEX(cmd[1]);
+  LOG(":");LOGHEX(cmd[2]);
+  LOG(":");LOGHEX(cmd[3]);
+  LOG(":");LOGHEX(cmd[4]);
+  LOG(":");LOGHEX(cmd[5]);
   // Receive the remaining commands
   for(int i = 6; i < len; i++ ) {
     cmd[i] = readHandshake();
@@ -1079,10 +1088,17 @@ void loop()
 
   // LUN confirmation
   // if it wasn't set in the IDENTIFY then grab it from the CDB
-  if(m_lun > MAX_SCSILUN)
-  {
-      m_lun = (cmd[1] & 0xe0) >> 5;
-  }
+	if (m_lun > MAX_SCSILUN)
+	{
+		if (dev->m_quirks==S2S_CFG_QUIRKS_XEBEC) // XEBEC s1410
+		{
+			m_lun = 0;
+		}
+		else
+		{
+			m_lun = cmd[1] >> 5;
+		}
+	}
 
   LOG(":ID ");
   LOG(m_id);
@@ -1138,15 +1154,32 @@ void loop()
   dev = &(scsi_device_list[m_id][m_lun]);
   if(!dev->m_file)
   {
-    dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
+    
+    //XEBEC
+    if(dev->m_quirks == S2S_CFG_QUIRKS_XEBEC){
+      dev->m_senseKey =SCSI_SENSE_HARDWARE_ERROR;
+      m_sts=SCSI_STATUS_GOOD ;
+      goto Command;
+    }
+    else
+      dev->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
     dev->m_additional_sense_code = SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED;
     m_sts = SCSI_STATUS_CHECK_CONDITION;
     goto Status;
   }
-
+  Command:
   m_sts = scsi_command_table[cmd[0]](dev, cmd);
 
 Status:
+  
+  TRANSCEIVER_IO_SET(vDTD,DB_OUTPUT)
+  SCSI_DB_OUTPUT()
+  if (m_sts==SCSI_STATUS_CHECK_CONDITION && cmd[0]!=0x01)
+   m_sts = 0;
+  if (m_lun==1 && dev->m_quirks == S2S_CFG_QUIRKS_XEBEC){
+    m_sts = m_sts | 0x20;
+  }
+
   LOG(" STS:"); LOGHEX(m_sts);
 
   SCSI_PHASE_CHANGE(SCSI_PHASE_STATUS);
@@ -1160,6 +1193,9 @@ Status:
   // Bus settle delay 400ns built in to writeHandshake
   writeHandshake(m_msg);
 
+  TRANSCEIVER_IO_SET(vDTD,DB_INPUT)
+  SCSI_DB_INPUT()
+
 BusFree:
   LOGN(" BF ");
   m_isBusReset = false;
@@ -1211,21 +1247,36 @@ byte onInquiry(SCSI_DEVICE *dev, const byte *cdb)
  */
 byte onRequestSense(SCSI_DEVICE *dev, const byte *cdb)
 {
-  byte buf[18] = {
-    0x70,   //CheckCondition
-    0,      //Segment number
-    dev->m_senseKey,   //Sense key
-    0, 0, 0, 0,  //information
-    10,   //Additional data length
-    0, 0, 0, 0, // command specific information bytes
-    (byte)(dev->m_additional_sense_code >> 8),
-    (byte)dev->m_additional_sense_code,
-    0, 0, 0, 0,
-  };
-  dev->m_senseKey = 0;
-  dev->m_additional_sense_code = 0;
-  writeDataPhase(cdb[4] < 18 ? cdb[4] : 18, buf);  
-
+  if (dev->m_quirks != S2S_CFG_QUIRKS_XEBEC){
+    byte buf[18] = {
+      0x70,   //CheckCondition
+      0,      //Segment number
+      dev->m_senseKey,   //Sense key
+      0, 0, 0, 0,  //information
+      10,   //Additional data length
+      0, 0, 0, 0, // command specific information bytes
+      (byte)(dev->m_additional_sense_code >> 8),
+      (byte)dev->m_additional_sense_code,
+      0, 0, 0, 0,
+    };
+    dev->m_senseKey = 0;
+    dev->m_additional_sense_code = 0;
+    TRANSCEIVER_IO_SET(vDTD,DB_OUTPUT)
+    SCSI_DB_OUTPUT()
+    writeDataPhase(cdb[4] < 18 ? cdb[4] : 18, buf); 
+    TRANSCEIVER_IO_SET(vDTD,DB_INPUT)
+    SCSI_DB_INPUT()
+  }else{
+    byte buf[4]={0x04,0x20,0x00,0x00};
+    dev->m_senseKey = 0;
+    dev->m_additional_sense_code = 0;
+    TRANSCEIVER_IO_SET(vDTD,DB_OUTPUT)
+    SCSI_DB_OUTPUT()
+    writeDataPhase(4, buf); 
+    TRANSCEIVER_IO_SET(vDTD,DB_INPUT)
+    SCSI_DB_INPUT()
+  }
+  
   return SCSI_STATUS_GOOD;
 }
 
@@ -1249,7 +1300,33 @@ byte onReadCapacity(SCSI_DEVICE *dev, const byte *cdb)
   writeDataPhase(sizeof(buf), buf);
   return SCSI_STATUS_GOOD;
 }
-
+/*
+ * READ XEBEC 0x0C command processing.
+ */
+byte onReadXebec0x0C(SCSI_DEVICE *dev, const byte *cdb)
+{
+  uint8_t buf[8];
+  memset(buf, 0, 8);
+  readDataPhase(sizeof(buf), buf);
+    int cylinders = ((uint16_t)buf[0] << 8) + buf[1];
+		int heads = buf[2];
+		int reducedWrite = ((uint16_t)buf[3] << 8) + buf[4];
+		int writePrecomp = ((uint16_t)buf[5] << 8) + buf[6];
+		int eccBurst = buf[7];
+  String str="---- Xebec Initialize Drive Characteristics: cylinders=";
+  str += cylinders;
+  str += " heads=";
+  str += heads;
+  str += " reducedWrite=";
+  str += reducedWrite;
+  str += " writePrecomp=";
+  str += writePrecomp;
+  str += " eccBurst=";
+  str += eccBurst;
+
+  LOG(str);
+  return SCSI_STATUS_GOOD;
+}
 /*
  * Check that the image file is present and the block range is valid.
  */
@@ -1283,8 +1360,9 @@ static byte onRead6(SCSI_DEVICE *dev, const byte *cdb)
   if (sts) {
     return sts;
   }
-  
+  LED_ACT_ON();
   writeDataPhaseSD(dev, adds, len);
+  LED_ACT_OFF();
   return SCSI_STATUS_GOOD;
 }
 
@@ -1305,12 +1383,23 @@ static byte onRead10(SCSI_DEVICE *dev, const byte *cdb)
   if (sts) {
     return sts;
   }
-   LED3_OFF(); 
+  LED_ACT_OFF(); 
   writeDataPhaseSD(dev, adds, len);
-  LED3_OFF();
+  LED_ACT_OFF();
   return SCSI_STATUS_GOOD;
 }
-
+static byte onFormat4(SCSI_DEVICE *dev, const byte *cdb)
+{
+  unsigned adds = (((uint32_t)cdb[1] & 0x1F) << 16) | ((uint32_t)cdb[2] << 8) | cdb[3];
+  formatPhaseSD(dev,adds);
+  return SCSI_STATUS_GOOD;  
+}
+static byte onFormat6(SCSI_DEVICE *dev, const byte *cdb)
+{
+  unsigned adds = (((uint32_t)cdb[1] & 0x1F) << 16) | ((uint32_t)cdb[2] << 8) | cdb[3];
+  formatTrackPhaseSD(dev,adds);
+  return SCSI_STATUS_GOOD;  
+}
 /*
  * WRITE6 / 10 Command processing.
  */