|
@@ -47,13 +47,14 @@
|
|
// 1: Debug information output to USB Serial
|
|
// 1: Debug information output to USB Serial
|
|
// 2: Debug information output to LOG.txt (slow)
|
|
// 2: Debug information output to LOG.txt (slow)
|
|
|
|
|
|
-#define VDS "2022-09-20"
|
|
|
|
|
|
+#define VDS "2025-01-04"
|
|
|
|
|
|
// Log File
|
|
// Log File
|
|
-#define VERSION "1.1-" VDS "-BLACKSASI"
|
|
|
|
|
|
+#define VERSION "1.2-" VDS "-BLACKSASI"
|
|
#define LOG_FILENAME "LOG.txt"
|
|
#define LOG_FILENAME "LOG.txt"
|
|
|
|
|
|
#include "blacksasi.h"
|
|
#include "blacksasi.h"
|
|
|
|
+#include "config.h"
|
|
#include "scsi_cmds.h"
|
|
#include "scsi_cmds.h"
|
|
#include "scsi_sense.h"
|
|
#include "scsi_sense.h"
|
|
#include "scsi_status.h"
|
|
#include "scsi_status.h"
|
|
@@ -114,6 +115,10 @@ SCSI_COMMAND_HANDLER(onReadTOC);
|
|
SCSI_COMMAND_HANDLER(onReadDVDStructure);
|
|
SCSI_COMMAND_HANDLER(onReadDVDStructure);
|
|
SCSI_COMMAND_HANDLER(onReadDiscInformation);
|
|
SCSI_COMMAND_HANDLER(onReadDiscInformation);
|
|
|
|
|
|
|
|
+SCSI_COMMAND_HANDLER(onFormat4);
|
|
|
|
+SCSI_COMMAND_HANDLER(onFormat6);
|
|
|
|
+SCSI_COMMAND_HANDLER(onReadXebec0x0C);
|
|
|
|
+
|
|
static uint32_t MSFtoLBA(const byte *msf);
|
|
static uint32_t MSFtoLBA(const byte *msf);
|
|
static void LBAtoMSF(const uint32_t lba, byte *msf);
|
|
static void LBAtoMSF(const uint32_t lba, byte *msf);
|
|
|
|
|
|
@@ -137,38 +142,6 @@ inline byte readIO(void)
|
|
return bret;
|
|
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)
|
|
bool VerifyISOPVD(SCSI_DEVICE *dev, unsigned sector_size, bool mode2)
|
|
@@ -290,7 +263,7 @@ void setup()
|
|
}
|
|
}
|
|
// Serial initialization
|
|
// Serial initialization
|
|
#if DEBUG == 1
|
|
#if DEBUG == 1
|
|
- serial.begin(9600);
|
|
|
|
|
|
+ serial.begin(115200);
|
|
// If using a USB->TTL monitor instead of USB serial monitor - you can uncomment this.
|
|
// If using a USB->TTL monitor instead of USB serial monitor - you can uncomment this.
|
|
//while (!Serial);
|
|
//while (!Serial);
|
|
#endif
|
|
#endif
|
|
@@ -307,8 +280,7 @@ void setup()
|
|
}
|
|
}
|
|
|
|
|
|
// SCSI commands that just need to return ok
|
|
// 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_REASSIGN_BLOCKS] = onNOP;
|
|
scsi_command_table[SCSI_SEEK6] = onNOP;
|
|
scsi_command_table[SCSI_SEEK6] = onNOP;
|
|
scsi_command_table[SCSI_SEEK10] = onNOP;
|
|
scsi_command_table[SCSI_SEEK10] = onNOP;
|
|
@@ -317,8 +289,14 @@ void setup()
|
|
scsi_command_table[SCSI_RELEASE] = onNOP;
|
|
scsi_command_table[SCSI_RELEASE] = onNOP;
|
|
scsi_command_table[SCSI_RESERVE] = onNOP;
|
|
scsi_command_table[SCSI_RESERVE] = onNOP;
|
|
scsi_command_table[SCSI_TEST_UNIT_READY] = 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 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_REZERO_UNIT] = onReZeroUnit;
|
|
scsi_command_table[SCSI_REQUEST_SENSE] = onRequestSense;
|
|
scsi_command_table[SCSI_REQUEST_SENSE] = onRequestSense;
|
|
scsi_command_table[SCSI_READ6] = onRead6;
|
|
scsi_command_table[SCSI_READ6] = onRead6;
|
|
@@ -670,7 +648,7 @@ inline byte readHandshake(void)
|
|
|
|
|
|
SCSI_OUT(vREQ,active);
|
|
SCSI_OUT(vREQ,active);
|
|
while( ! SCSI_IN(vACK));
|
|
while( ! SCSI_IN(vACK));
|
|
- NOP(10);
|
|
|
|
|
|
+ NOP(20);
|
|
|
|
|
|
byte r = readIO();
|
|
byte r = readIO();
|
|
SCSI_OUT(vREQ,inactive)
|
|
SCSI_OUT(vREQ,inactive)
|
|
@@ -698,7 +676,7 @@ inline void writeHandshake(byte d)
|
|
while(!SCSI_IN(vACK));
|
|
while(!SCSI_IN(vACK));
|
|
// ACK.Fall to REQ.Raise delay 500ns(typ.) (DTC-510B)
|
|
// ACK.Fall to REQ.Raise delay 500ns(typ.) (DTC-510B)
|
|
uint32_t bsrrCall = (db_bsrr[0xff] );
|
|
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)
|
|
SCSI_OUT(vREQ,inactive)
|
|
// REQ.Raise to DB hold time 0ns
|
|
// REQ.Raise to DB hold time 0ns
|
|
SCSI_DB_INPUT() // (150ns)
|
|
SCSI_DB_INPUT() // (150ns)
|
|
@@ -752,7 +730,14 @@ void writeDataLoop(uint32_t blocksize, const byte* srcptr) {
|
|
FETCH_BSRR_DB();
|
|
FETCH_BSRR_DB();
|
|
WAIT_ACK_ACTIVE();
|
|
WAIT_ACK_ACTIVE();
|
|
REQ_OFF_DB_SET(bsrr_val);
|
|
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);
|
|
}while(srcptr < endptr);
|
|
WAIT_ACK_INACTIVE();
|
|
WAIT_ACK_INACTIVE();
|
|
// Finish the last bus cycle, byte is already on DB.
|
|
// 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.
|
|
// Start of the do/while and WAIT are already aligned to 8 bytes.
|
|
do {
|
|
do {
|
|
WAIT_ACK_ACTIVE();
|
|
WAIT_ACK_ACTIVE();
|
|
-NOP(10);
|
|
|
|
|
|
+ NOP(17);
|
|
|
|
|
|
|
|
|
|
uint32_t ret = PDREG->IDR;
|
|
uint32_t ret = PDREG->IDR;
|
|
@@ -846,7 +831,7 @@ NOP(10);
|
|
asm("nop");
|
|
asm("nop");
|
|
} while(dstptr<endptr);
|
|
} while(dstptr<endptr);
|
|
WAIT_ACK_ACTIVE();
|
|
WAIT_ACK_ACTIVE();
|
|
-NOP(10);
|
|
|
|
|
|
+ NOP(17);
|
|
uint32_t ret = PDREG->IDR;
|
|
uint32_t ret = PDREG->IDR;
|
|
REQ_OFF();
|
|
REQ_OFF();
|
|
*dstptr = (byte)~(((ret ) & 0b11111111) );
|
|
*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.
|
|
// Bus settle delay 400ns. The following code was measured at 450ns before REQ asserted. STM32F103.
|
|
readDataLoop(len, p);
|
|
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.
|
|
* Data out phase.
|
|
* Write to SD card while reading len block.
|
|
* 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));
|
|
//do {} while( SCSI_IN(vBSY) || !SCSI_IN(vSEL) || SCSI_IN(vRST));
|
|
//LOG(" S:"); LOGHEX(readIO()); LOG(" ");
|
|
//LOG(" S:"); LOGHEX(readIO()); LOG(" ");
|
|
// We're in SELECTION
|
|
// We're in SELECTION
|
|
-
|
|
|
|
|
|
+
|
|
byte scsiid = readIO() & scsi_id_mask;
|
|
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);
|
|
delayMicroseconds(1);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -1040,9 +1046,6 @@ void loop()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- LOG("CMD:");
|
|
|
|
-
|
|
|
|
SCSI_PHASE_CHANGE(SCSI_PHASE_COMMAND);
|
|
SCSI_PHASE_CHANGE(SCSI_PHASE_COMMAND);
|
|
SCSI_BSY_ACTIVE();
|
|
SCSI_BSY_ACTIVE();
|
|
TRANSCEIVER_IO_SET(vTAD,TR_INPUT);
|
|
TRANSCEIVER_IO_SET(vTAD,TR_INPUT);
|
|
@@ -1060,16 +1063,22 @@ void loop()
|
|
// so just read it and re-read it again to get the
|
|
// so just read it and re-read it again to get the
|
|
// real command byte
|
|
// real command byte
|
|
if(cmd[0] == SCSI_ICD_EXTENDED_CMD) { cmd[0] = readHandshake(); }
|
|
if(cmd[0] == SCSI_ICD_EXTENDED_CMD) { cmd[0] = readHandshake(); }
|
|
-
|
|
|
|
|
|
+ LOG("CMD:");
|
|
LOGHEX(cmd[0]);
|
|
LOGHEX(cmd[0]);
|
|
// Command length selection, reception
|
|
// Command length selection, reception
|
|
static const int cmd_class_len[8]={6,10,10,6,6,12,6,6};
|
|
static const int cmd_class_len[8]={6,10,10,6,6,12,6,6};
|
|
len = cmd_class_len[cmd[0] >> 5];
|
|
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
|
|
// Receive the remaining commands
|
|
for(int i = 6; i < len; i++ ) {
|
|
for(int i = 6; i < len; i++ ) {
|
|
cmd[i] = readHandshake();
|
|
cmd[i] = readHandshake();
|
|
@@ -1079,10 +1088,17 @@ void loop()
|
|
|
|
|
|
// LUN confirmation
|
|
// LUN confirmation
|
|
// if it wasn't set in the IDENTIFY then grab it from the CDB
|
|
// 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(":ID ");
|
|
LOG(m_id);
|
|
LOG(m_id);
|
|
@@ -1138,15 +1154,32 @@ void loop()
|
|
dev = &(scsi_device_list[m_id][m_lun]);
|
|
dev = &(scsi_device_list[m_id][m_lun]);
|
|
if(!dev->m_file)
|
|
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;
|
|
dev->m_additional_sense_code = SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED;
|
|
m_sts = SCSI_STATUS_CHECK_CONDITION;
|
|
m_sts = SCSI_STATUS_CHECK_CONDITION;
|
|
goto Status;
|
|
goto Status;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+ Command:
|
|
m_sts = scsi_command_table[cmd[0]](dev, cmd);
|
|
m_sts = scsi_command_table[cmd[0]](dev, cmd);
|
|
|
|
|
|
Status:
|
|
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);
|
|
LOG(" STS:"); LOGHEX(m_sts);
|
|
|
|
|
|
SCSI_PHASE_CHANGE(SCSI_PHASE_STATUS);
|
|
SCSI_PHASE_CHANGE(SCSI_PHASE_STATUS);
|
|
@@ -1160,6 +1193,9 @@ Status:
|
|
// Bus settle delay 400ns built in to writeHandshake
|
|
// Bus settle delay 400ns built in to writeHandshake
|
|
writeHandshake(m_msg);
|
|
writeHandshake(m_msg);
|
|
|
|
|
|
|
|
+ TRANSCEIVER_IO_SET(vDTD,DB_INPUT)
|
|
|
|
+ SCSI_DB_INPUT()
|
|
|
|
+
|
|
BusFree:
|
|
BusFree:
|
|
LOGN(" BF ");
|
|
LOGN(" BF ");
|
|
m_isBusReset = false;
|
|
m_isBusReset = false;
|
|
@@ -1211,21 +1247,36 @@ byte onInquiry(SCSI_DEVICE *dev, const byte *cdb)
|
|
*/
|
|
*/
|
|
byte onRequestSense(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;
|
|
return SCSI_STATUS_GOOD;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1249,7 +1300,33 @@ byte onReadCapacity(SCSI_DEVICE *dev, const byte *cdb)
|
|
writeDataPhase(sizeof(buf), buf);
|
|
writeDataPhase(sizeof(buf), buf);
|
|
return SCSI_STATUS_GOOD;
|
|
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.
|
|
* 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) {
|
|
if (sts) {
|
|
return sts;
|
|
return sts;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+ LED_ACT_ON();
|
|
writeDataPhaseSD(dev, adds, len);
|
|
writeDataPhaseSD(dev, adds, len);
|
|
|
|
+ LED_ACT_OFF();
|
|
return SCSI_STATUS_GOOD;
|
|
return SCSI_STATUS_GOOD;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1305,12 +1383,23 @@ static byte onRead10(SCSI_DEVICE *dev, const byte *cdb)
|
|
if (sts) {
|
|
if (sts) {
|
|
return sts;
|
|
return sts;
|
|
}
|
|
}
|
|
- LED3_OFF();
|
|
|
|
|
|
+ LED_ACT_OFF();
|
|
writeDataPhaseSD(dev, adds, len);
|
|
writeDataPhaseSD(dev, adds, len);
|
|
- LED3_OFF();
|
|
|
|
|
|
+ LED_ACT_OFF();
|
|
return SCSI_STATUS_GOOD;
|
|
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.
|
|
* WRITE6 / 10 Command processing.
|
|
*/
|
|
*/
|