|  | @@ -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.
 | 
	
		
			
				|  |  |   */
 |