|
@@ -186,7 +186,7 @@ typedef struct hddimg_struct
|
|
|
HDDIMG img[NUM_SCSIID][NUM_SCSILUN]; // Maximum number
|
|
HDDIMG img[NUM_SCSIID][NUM_SCSILUN]; // Maximum number
|
|
|
|
|
|
|
|
uint8_t m_senseKey = 0; // Sense key
|
|
uint8_t m_senseKey = 0; // Sense key
|
|
|
-unsigned m_addition_sense = 0; // Additional sense information
|
|
|
|
|
|
|
+uint16_t m_addition_sense = 0; // Additional sense information
|
|
|
volatile bool m_isBusReset = false; // Bus reset
|
|
volatile bool m_isBusReset = false; // Bus reset
|
|
|
volatile bool m_resetJmp = false; // Call longjmp on reset
|
|
volatile bool m_resetJmp = false; // Call longjmp on reset
|
|
|
jmp_buf m_resetJmpBuf;
|
|
jmp_buf m_resetJmpBuf;
|
|
@@ -925,6 +925,30 @@ void readDataPhaseSD(uint32_t adds, uint32_t len)
|
|
|
enableResetJmp();
|
|
enableResetJmp();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * Data out phase.
|
|
|
|
|
+ * Compare to SD card while reading len block.
|
|
|
|
|
+ */
|
|
|
|
|
+void verifyDataPhaseSD(uint32_t adds, uint32_t len)
|
|
|
|
|
+{
|
|
|
|
|
+ LOGN("DATAOUT PHASE(SD)");
|
|
|
|
|
+ uint32_t pos = adds * m_img->m_blocksize;
|
|
|
|
|
+ m_img->m_file.seek(pos);
|
|
|
|
|
+ SCSI_OUT(vMSG,inactive) // gpio_write(MSG, low);
|
|
|
|
|
+ SCSI_OUT(vCD ,inactive) // gpio_write(CD, low);
|
|
|
|
|
+ SCSI_OUT(vIO ,inactive) // gpio_write(IO, low);
|
|
|
|
|
+ for(uint32_t i = 0; i < len; i++) {
|
|
|
|
|
+#if WRITE_SPEED_OPTIMIZE
|
|
|
|
|
+ readDataLoop(m_img->m_blocksize);
|
|
|
|
|
+#else
|
|
|
|
|
+ for(int j = 0; j < m_img->m_blocksize; j++) {
|
|
|
|
|
+ m_buf[j] = readHandshake();
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+ // This has just gone through the transfer to make things work, a compare would go here.
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* INQUIRY command processing.
|
|
* INQUIRY command processing.
|
|
|
*/
|
|
*/
|
|
@@ -980,7 +1004,11 @@ void onRequestSenseCommand(byte len)
|
|
|
*/
|
|
*/
|
|
|
byte onReadCapacityCommand(byte pmi)
|
|
byte onReadCapacityCommand(byte pmi)
|
|
|
{
|
|
{
|
|
|
- if(!m_img) return 0x02; // Image file absent
|
|
|
|
|
|
|
+ if(!m_img) {
|
|
|
|
|
+ m_senseKey = 2; // Not ready
|
|
|
|
|
+ m_addition_sense = 0x0403; // Logical Unit Not Ready, Manual Intervention Required
|
|
|
|
|
+ return 0x02; // Image file absent
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
uint32_t bl = m_img->m_blocksize;
|
|
uint32_t bl = m_img->m_blocksize;
|
|
|
uint32_t bc = m_img->m_fileSize / bl - 1; // Points to last LBA
|
|
uint32_t bc = m_img->m_fileSize / bl - 1; // Points to last LBA
|
|
@@ -992,6 +1020,27 @@ byte onReadCapacityCommand(byte pmi)
|
|
|
return 0x00;
|
|
return 0x00;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * Check that the image file is present and the block range is valid.
|
|
|
|
|
+ */
|
|
|
|
|
+byte checkBlockCommand(uint32_t adds, uint32_t len)
|
|
|
|
|
+{
|
|
|
|
|
+ // Check that image file is present
|
|
|
|
|
+ if(!m_img) {
|
|
|
|
|
+ m_senseKey = 2; // Not ready
|
|
|
|
|
+ m_addition_sense = 0x0403; // Logical Unit Not Ready, Manual Intervention Required
|
|
|
|
|
+ return 0x02;
|
|
|
|
|
+ }
|
|
|
|
|
+ // Check block range is valid
|
|
|
|
|
+ uint32_t bc = m_img->m_fileSize / m_img->m_blocksize;
|
|
|
|
|
+ if (adds >= bc || (adds + len) > bc) {
|
|
|
|
|
+ m_senseKey = 5; // Illegal request
|
|
|
|
|
+ m_addition_sense = 0x2100; // Logical block address out of range
|
|
|
|
|
+ return 0x02;
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0x00;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* READ6 / 10 Command processing.
|
|
* READ6 / 10 Command processing.
|
|
|
*/
|
|
*/
|
|
@@ -1001,8 +1050,10 @@ byte onReadCommand(uint32_t adds, uint32_t len)
|
|
|
LOGHEXN(adds);
|
|
LOGHEXN(adds);
|
|
|
LOGHEXN(len);
|
|
LOGHEXN(len);
|
|
|
|
|
|
|
|
- if(!m_img) return 0x02; // Image file absent
|
|
|
|
|
-
|
|
|
|
|
|
|
+ byte sts = checkBlockCommand(adds, len);
|
|
|
|
|
+ if (sts) {
|
|
|
|
|
+ return sts;
|
|
|
|
|
+ }
|
|
|
LED_ON();
|
|
LED_ON();
|
|
|
writeDataPhaseSD(adds, len);
|
|
writeDataPhaseSD(adds, len);
|
|
|
LED_OFF();
|
|
LED_OFF();
|
|
@@ -1018,21 +1069,50 @@ byte onWriteCommand(uint32_t adds, uint32_t len)
|
|
|
LOGHEXN(adds);
|
|
LOGHEXN(adds);
|
|
|
LOGHEXN(len);
|
|
LOGHEXN(len);
|
|
|
|
|
|
|
|
- if(!m_img) return 0x02; // Image file absent
|
|
|
|
|
-
|
|
|
|
|
|
|
+ byte sts = checkBlockCommand(adds, len);
|
|
|
|
|
+ if (sts) {
|
|
|
|
|
+ return sts;
|
|
|
|
|
+ }
|
|
|
LED_ON();
|
|
LED_ON();
|
|
|
readDataPhaseSD(adds, len);
|
|
readDataPhaseSD(adds, len);
|
|
|
LED_OFF();
|
|
LED_OFF();
|
|
|
return 0; //sts
|
|
return 0; //sts
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * VERIFY10 Command processing.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+byte onVerifyCommand(byte flags, uint32_t adds, uint32_t len)
|
|
|
|
|
+{
|
|
|
|
|
+ byte sts = checkBlockCommand(adds, len);
|
|
|
|
|
+ if (sts) {
|
|
|
|
|
+ return sts;
|
|
|
|
|
+ }
|
|
|
|
|
+ int bytchk = (flags >> 1) & 0x03;
|
|
|
|
|
+ if (bytchk != 0) {
|
|
|
|
|
+ if (bytchk == 3) {
|
|
|
|
|
+ // Data-Out buffer is single logical block for repeated verification.
|
|
|
|
|
+ len == m_img->m_blocksize;
|
|
|
|
|
+ }
|
|
|
|
|
+ LED_ON();
|
|
|
|
|
+ verifyDataPhaseSD(adds, len);
|
|
|
|
|
+ LED_OFF();
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0x00;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* MODE SENSE command processing.
|
|
* MODE SENSE command processing.
|
|
|
*/
|
|
*/
|
|
|
#if SCSI_SELECT == 2
|
|
#if SCSI_SELECT == 2
|
|
|
byte onModeSenseCommand(byte scsi_cmd, byte dbd, int cmd2, uint32_t len)
|
|
byte onModeSenseCommand(byte scsi_cmd, byte dbd, int cmd2, uint32_t len)
|
|
|
{
|
|
{
|
|
|
- if(!m_img) return 0x02; // Image file absent
|
|
|
|
|
|
|
+ if(!m_img) {
|
|
|
|
|
+ m_senseKey = 2; // Not ready
|
|
|
|
|
+ m_addition_sense = 0x0403; // Logical Unit Not Ready, Manual Intervention Required
|
|
|
|
|
+ return 0x02; // Image file absent
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
int pageCode = cmd2 & 0x3F;
|
|
int pageCode = cmd2 & 0x3F;
|
|
|
|
|
|
|
@@ -1114,7 +1194,11 @@ byte onModeSenseCommand(byte scsi_cmd, byte dbd, int cmd2, uint32_t len)
|
|
|
#else
|
|
#else
|
|
|
byte onModeSenseCommand(byte scsi_cmd, byte dbd, byte cmd2, uint32_t len)
|
|
byte onModeSenseCommand(byte scsi_cmd, byte dbd, byte cmd2, uint32_t len)
|
|
|
{
|
|
{
|
|
|
- if(!m_img) return 0x02; // No image file
|
|
|
|
|
|
|
+ if(!m_img) {
|
|
|
|
|
+ m_senseKey = 2; // Not ready
|
|
|
|
|
+ m_addition_sense = 0x0403; // Logical Unit Not Ready, Manual Intervention Required
|
|
|
|
|
+ return 0x02; // No image file
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
uint32_t bl = m_img->m_blocksize;
|
|
uint32_t bl = m_img->m_blocksize;
|
|
|
uint32_t bc = m_img->m_fileSize / bl;
|
|
uint32_t bc = m_img->m_fileSize / bl;
|
|
@@ -1207,6 +1291,25 @@ byte onModeSenseCommand(byte scsi_cmd, byte dbd, byte cmd2, uint32_t len)
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+byte onModeSelectCommand(byte scsi_cmd, byte flags, uint32_t len)
|
|
|
|
|
+{
|
|
|
|
|
+ if (len > MAX_BLOCKSIZE) {
|
|
|
|
|
+ m_senseKey = 5; // Illegal request
|
|
|
|
|
+ m_addition_sense = 0x2400; // Invalid field in CDB
|
|
|
|
|
+ return 0x02;
|
|
|
|
|
+ }
|
|
|
|
|
+ readDataPhase(len, m_buf);
|
|
|
|
|
+ //Apple HD SC Setup sends:
|
|
|
|
|
+ //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
|
|
|
|
|
+ for (unsigned i = 0; i < len; i++) {
|
|
|
|
|
+ LOGHEX(m_buf[i]);LOG(" ");
|
|
|
|
|
+ }
|
|
|
|
|
+ LOGN("");
|
|
|
|
|
+ return 0x00;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#if SCSI_SELECT == 1
|
|
#if SCSI_SELECT == 1
|
|
|
/*
|
|
/*
|
|
|
* dtc510b_setDriveparameter
|
|
* dtc510b_setDriveparameter
|
|
@@ -1455,6 +1558,10 @@ void loop()
|
|
|
LOGN("[Inquiry]");
|
|
LOGN("[Inquiry]");
|
|
|
m_sts |= onInquiryCommand(cmd[4]);
|
|
m_sts |= onInquiryCommand(cmd[4]);
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case 0x15:
|
|
|
|
|
+ LOGN("[ModeSelect6]");
|
|
|
|
|
+ m_sts |= onModeSelectCommand(cmd[0], cmd[1], cmd[4]);
|
|
|
|
|
+ break;
|
|
|
case 0x1A:
|
|
case 0x1A:
|
|
|
LOGN("[ModeSense6]");
|
|
LOGN("[ModeSense6]");
|
|
|
m_sts |= onModeSenseCommand(cmd[0], cmd[1]&0x80, cmd[2], cmd[4]);
|
|
m_sts |= onModeSenseCommand(cmd[0], cmd[1]&0x80, cmd[2], cmd[4]);
|
|
@@ -1480,9 +1587,17 @@ void loop()
|
|
|
case 0x2B:
|
|
case 0x2B:
|
|
|
LOGN("[Seek10]");
|
|
LOGN("[Seek10]");
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case 0x2F:
|
|
|
|
|
+ LOGN("[Verify10]");
|
|
|
|
|
+ m_sts |= onVerifyCommand(cmd[1], ((uint32_t)cmd[2] << 24) | ((uint32_t)cmd[3] << 16) | ((uint32_t)cmd[4] << 8) | cmd[5], ((uint32_t)cmd[7] << 8) | cmd[8]);
|
|
|
|
|
+ break;
|
|
|
case 0x35:
|
|
case 0x35:
|
|
|
LOGN("[SynchronizeCache10]");
|
|
LOGN("[SynchronizeCache10]");
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case 0x55:
|
|
|
|
|
+ LOGN("[ModeSelect10");
|
|
|
|
|
+ m_sts |= onModeSelectCommand(cmd[0], cmd[1], ((uint32_t)cmd[7] << 8) | cmd[8]);
|
|
|
|
|
+ break;
|
|
|
case 0x5A:
|
|
case 0x5A:
|
|
|
LOGN("[ModeSense10]");
|
|
LOGN("[ModeSense10]");
|
|
|
m_sts |= onModeSenseCommand(cmd[0], cmd[1] & 0x80, cmd[2], ((uint32_t)cmd[7] << 8) | cmd[8]);
|
|
m_sts |= onModeSenseCommand(cmd[0], cmd[1] & 0x80, cmd[2], ((uint32_t)cmd[7] << 8) | cmd[8]);
|