Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apple HD SC Setup support #71

Merged
merged 2 commits into from
Mar 25, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 154 additions & 22 deletions src/BlueSCSI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ typedef struct hddimg_struct
HDDIMG img[NUM_SCSIID][NUM_SCSILUN]; // Maximum number

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_resetJmp = false; // Call longjmp on reset
jmp_buf m_resetJmpBuf;
Expand Down Expand Up @@ -925,6 +925,30 @@ void readDataPhaseSD(uint32_t adds, uint32_t len)
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.
*/
Expand Down Expand Up @@ -980,7 +1004,11 @@ void onRequestSenseCommand(byte len)
*/
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 bc = m_img->m_fileSize / bl - 1; // Points to last LBA
Expand All @@ -992,6 +1020,27 @@ byte onReadCapacityCommand(byte pmi)
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.
*/
Expand All @@ -1001,8 +1050,10 @@ byte onReadCommand(uint32_t adds, uint32_t len)
LOGHEXN(adds);
LOGHEXN(len);

if(!m_img) return 0x02; // Image file absent

byte sts = checkBlockCommand(adds, len);
if (sts) {
return sts;
}
LED_ON();
writeDataPhaseSD(adds, len);
LED_OFF();
Expand All @@ -1018,21 +1069,50 @@ byte onWriteCommand(uint32_t adds, uint32_t len)
LOGHEXN(adds);
LOGHEXN(len);

if(!m_img) return 0x02; // Image file absent

byte sts = checkBlockCommand(adds, len);
if (sts) {
return sts;
}
LED_ON();
readDataPhaseSD(adds, len);
LED_OFF();
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;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mactcp should this be =?

}
LED_ON();
verifyDataPhaseSD(adds, len);
LED_OFF();
}
return 0x00;
}

/*
* MODE SENSE command processing.
*/
#if SCSI_SELECT == 2
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;

Expand Down Expand Up @@ -1112,15 +1192,20 @@ byte onModeSenseCommand(byte scsi_cmd, byte dbd, int cmd2, uint32_t len)
return 0x00;
}
#else
byte onModeSenseCommand(byte scsi_cmd, byte dbd, int 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 bc = m_img->m_fileSize / bl;

memset(m_buf, 0, sizeof(m_buf));
int pageCode = cmd2 & 0x3F;
int pageControl = cmd2 >> 6;
int a = 4;
if(scsi_cmd == 0x5A) a = 8;

Expand Down Expand Up @@ -1151,24 +1236,37 @@ byte onModeSenseCommand(byte scsi_cmd, byte dbd, int cmd2, uint32_t len)
case 0x03: //Drive parameters
m_buf[a + 0] = 0x03; //Page code
m_buf[a + 1] = 0x16; // Page length
m_buf[a + 11] = 0x3F;//Number of sectors / track
m_buf[a + 12] = (byte)(m_img->m_blocksize >> 8);
m_buf[a + 13] = (byte)m_img->m_blocksize;
m_buf[a + 15] = 0x1; // Interleave
if(pageControl != 1) {
m_buf[a + 11] = 0x3F;//Number of sectors / track
m_buf[a + 12] = (byte)(m_img->m_blocksize >> 8);
m_buf[a + 13] = (byte)m_img->m_blocksize;
m_buf[a + 15] = 0x1; // Interleave
}
a += 0x18;
if(pageCode != 0x3F) break;

case 0x04: //Drive parameters
m_buf[a + 0] = 0x04; //Page code
m_buf[a + 1] = 0x16; // Page length
if(pageControl != 1) {
unsigned cylinders = bc / (16 * 63);
m_buf[a + 2] = (byte)(cylinders >> 16); // Cylinders
m_buf[a + 3] = (byte)(cylinders >> 8);
m_buf[a + 4] = (byte)cylinders;
m_buf[a + 5] = 16; //Number of heads
}
a += 0x18;
if(pageCode != 0x3F) break;
case 0x30:
{
unsigned cylinders = bc / (16 * 63);
m_buf[a + 0] = 0x04; //Page code
m_buf[a + 1] = 0x16; // Page length
m_buf[a + 2] = (byte)(cylinders >> 16); // Cylinders
m_buf[a + 3] = (byte)(cylinders >> 8);
m_buf[a + 4] = (byte)cylinders;
m_buf[a + 5] = 16; //Number of heads
a += 0x18;
if(pageCode != 0x3F) break;
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 + 1] = sizeof(page30); // Page length
if(pageControl != 1) {
memcpy(&m_buf[a + 2], page30, sizeof(page30));
}
a += 2 + sizeof(page30);
if(pageCode != 0x3F) break;
}
break; // Don't want 0x3F falling through to error condition

Expand All @@ -1193,6 +1291,25 @@ byte onModeSenseCommand(byte scsi_cmd, byte dbd, int cmd2, uint32_t len)
}
#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
/*
* dtc510b_setDriveparameter
Expand Down Expand Up @@ -1441,6 +1558,10 @@ void loop()
LOGN("[Inquiry]");
m_sts |= onInquiryCommand(cmd[4]);
break;
case 0x15:
LOGN("[ModeSelect6]");
m_sts |= onModeSelectCommand(cmd[0], cmd[1], cmd[4]);
break;
case 0x1A:
LOGN("[ModeSense6]");
m_sts |= onModeSenseCommand(cmd[0], cmd[1]&0x80, cmd[2], cmd[4]);
Expand All @@ -1466,6 +1587,17 @@ void loop()
case 0x2B:
LOGN("[Seek10]");
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:
LOGN("[SynchronizeCache10]");
break;
case 0x55:
LOGN("[ModeSelect10");
m_sts |= onModeSelectCommand(cmd[0], cmd[1], ((uint32_t)cmd[7] << 8) | cmd[8]);
break;
case 0x5A:
LOGN("[ModeSense10]");
m_sts |= onModeSenseCommand(cmd[0], cmd[1] & 0x80, cmd[2], ((uint32_t)cmd[7] << 8) | cmd[8]);
Expand Down