merged in latest HEAD, cleaned up some warnings

This commit is contained in:
Troy 2022-07-17 11:49:08 -04:00
parent 2611ec885b
commit 30b794e03d
2 changed files with 92 additions and 351 deletions

View File

@ -620,30 +620,15 @@ void findDriveImages(FsFile root) {
switch(dev->m_type)
{
case SCSI_DEVICE_HDD:
// default SCSI HDD
dev->inquiry_block.ansi_version = 1;
dev->inquiry_block.response_format = 1;
dev->inquiry_block.additional_length = 31;
memcpy(dev->inquiry_block.vendor, "QUANTUM", 7);
memcpy(dev->inquiry_block.product, "FIREBALL1", 9);
memcpy(dev->inquiry_block.revision, "1.0", 3);
break;
case SCSI_DEVICE_OPTICAL:
// default SCSI CDROM
dev->inquiry_block.peripheral_device_type = 5;
dev->inquiry_block.rmb = 1;
dev->inquiry_block.ansi_version = 1;
dev->inquiry_block.response_format = 1;
dev->inquiry_block.additional_length = 42;
dev->inquiry_block.sync = 1;
memcpy(dev->inquiry_block.vendor, "BLUESCSI", 8);
memcpy(dev->inquiry_block.product, "CD-ROM CDU-55S", 14);
memcpy(dev->inquiry_block.revision, "1.9a", 4);
dev->inquiry_block.release = 0x20;
memcpy(dev->inquiry_block.revision_date, "1995", 4);
break;
case SCSI_DEVICE_HDD:
// default SCSI HDD
dev->inquiry_block = &default_hdd;
break;
case SCSI_DEVICE_OPTICAL:
// default SCSI CDROM
dev->inquiry_block = &default_optical;
break;
}
readSCSIDeviceConfig(dev);
@ -1088,26 +1073,25 @@ void loop()
m_lun = 0xff;
SCSI_DEVICE *dev = (SCSI_DEVICE *)0; // HDD image for current SCSI-ID, LUN
// Wait until RST = H, BSY = H, SEL = L
//do {} while( SCSI_IN(vBSY) || !SCSI_IN(vSEL) || SCSI_IN(vRST));
do {} while( !SCSI_IN(vBSY) || SCSI_IN(vRST));
// We're in ARBITRATION
//LOG(" A:"); LOGHEX(readIO()); LOG(" ");
do {} while( SCSI_IN(vBSY) || !SCSI_IN(vSEL) || SCSI_IN(vRST));
//LOG(" S:"); LOGHEX(readIO()); LOG(" ");
// BSY+ SEL-
// If the ID to respond is not driven, wait for the next
//byte db = readIO();
//byte scsiid = db & scsi_id_mask;
// We're in SELECTION
byte scsiid = readIO() & scsi_id_mask;
if(SCSI_IN(vIO) || (scsiid) == 0) {
delayMicroseconds(1);
return;
}
// We've been selected
#ifdef XCVR
#ifdef XCVR
// Reconfigure target pins to output mode, after resetting their values
GPIOB->regs->BSRR = 0x000000E8; // MSG, CD, REQ, IO
// GPIOA->regs->BSRR = 0x00000200; // BSY
// GPIOA->regs->BSRR = 0x00000200; // BSY
#endif
SCSI_TARGET_ACTIVE() // (BSY), REQ, MSG, CD, IO output turned on
@ -1117,19 +1101,18 @@ void loop()
// Wait until SEL becomes inactive
while(isHigh(gpio_read(SEL))) {}
// Ask for a TARGET-ID to respond
m_id = 31 - __builtin_clz(scsiid);
m_isBusReset = false;
if (setjmp(m_resetJmpBuf) == 1) {
LOGN("Reset, going to BusFree");
goto BusFree;
}
enableResetJmp();
// Ask for a TARGET-ID to respond
m_id = 31 - __builtin_clz(scsiid);
//
// In SCSI-2 this is mandatory, but in SCSI-1 it's optional
if(isHigh(gpio_read(ATN))) {
LOG(" MO:");
SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEOUT);
// Bus settle delay 400ns. Following code was measured at 350ns before REQ asserted. Added another 50ns. STM32F103.
SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEOUT);// 28ns delay STM32F103
@ -1142,7 +1125,6 @@ void loop()
m_msb[msc++] = readHandshake();
}
for(int i = 0; i < msc; i++) {
LOGHEX(m_msb[i]); LOG(":");
// ABORT
if (m_msb[i] == 0x06) {
goto BusFree;
@ -1155,14 +1137,6 @@ void loop()
// IDENTIFY
if (m_msb[i] >= 0x80) {
m_lun = m_msb[i] & 0x1f;
if(m_lun >= NUM_SCSILUN)
{
SCSI_DEVICE *d = &scsi_device_list[m_id][m_lun];
d->m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
d->m_additional_sense_code = SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED;
m_sts |= SCSI_STATUS_CHECK_CONDITION;
goto Status;
}
}
// Extended message
if (m_msb[i] == 0x01) {
@ -1192,13 +1166,21 @@ void loop()
}
}
LOG(" CMD:");
LOG("Command:");
SCSI_PHASE_CHANGE(SCSI_PHASE_COMMAND);
// Bus settle delay 400ns. The following code was measured at 20ns before REQ asserted. Added another 380ns. STM32F103.
asm("nop;nop;nop;nop;nop;nop;nop;nop");// This asm causes some code reodering, which adds 270ns, plus 8 nop cycles for an additional 110ns. STM32F103
int len;
byte cmd[12];
byte cmd[20];
cmd[0] = readHandshake();
// Atari ST ICD extension support
// It sends a 0x1F as a indicator there is a
// proper full size SCSI command byte to follow
// 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(); }
LOGHEX(cmd[0]);
// Command length selection, reception
static const int cmd_class_len[8]={6,10,10,6,6,12,6,6};
@ -1215,52 +1197,71 @@ void loop()
LOGHEX(cmd[i]);
}
// LUN confirmation
m_sts = cmd[1]&0xe0; // Preset LUN in status byte
// if it wasn't set in the IDENTIFY then grab it from the CDB
if(m_lun > NUM_SCSILUN)
if(m_lun > MAX_SCSILUN)
{
m_lun = m_sts>>5;
m_lun = (cmd[1] & 0xe0) >> 5;
}
LOG(":ID ");
LOG(m_id);
LOG(":LUN ");
LOG(m_lun);
LOG(" ");
LOGN("");
dev = &(scsi_device_list[m_id][m_lun]);
// HDD Image selection
if(m_lun >= NUM_SCSILUN || !dev->m_file)
if(m_lun >= NUM_SCSILUN)
{
// REQUEST SENSE and INQUIRY are handled different with invalid LUNs
if(cmd[0] != SCSI_REQUEST_SENSE || cmd[0] != SCSI_INQUIRY)
{
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;
}
m_sts = SCSI_STATUS_GOOD;
// REQUEST SENSE and INQUIRY are handled different with invalid LUNs
if(cmd[0] == SCSI_INQUIRY)
{
// Special INQUIRY handling for invalid LUNs
LOG(" onInquiry-InvalidLUN ");
LOGN("onInquiry - InvalidLUN");
dev = &(scsi_device_list[m_id][0]);
byte temp = dev->inquiry_block.raw[0];
byte temp = dev->inquiry_block->raw[0];
// If the LUN is invalid byte 0 of inquiry block needs to be 7fh
dev->inquiry_block.raw[0] = 0x7f;
dev->inquiry_block->raw[0] = 0x7f;
// only write back what was asked for
writeDataPhase(cmd[4], dev->inquiry_block.raw);
writeDataPhase(cmd[4], dev->inquiry_block->raw);
// return it back to normal if it was altered
dev->inquiry_block.raw[0] = temp;
m_sts = SCSI_STATUS_GOOD;
goto Status;
dev->inquiry_block->raw[0] = temp;
}
else if(cmd[0] == SCSI_REQUEST_SENSE)
{
byte buf[18] = {
0x70, //CheckCondition
0, //Segment number
SCSI_SENSE_ILLEGAL_REQUEST, //Sense key
0, 0, 0, 0, //information
10, //Additional data length
0, 0, 0, 0, // command specific information bytes
(byte)(SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED >> 8),
(byte)SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
0, 0, 0, 0,
};
writeDataPhase(cmd[4] < 18 ? cmd[4] : 18, buf);
}
else
{
m_sts = SCSI_STATUS_CHECK_CONDITION;
}
goto Status;
}
dev = &(scsi_device_list[m_id][m_lun]);
if(!dev->m_file)
{
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;
}
LED_ON();
@ -1268,17 +1269,18 @@ void loop()
LED_OFF();
Status:
LOG(" S:"); LOGHEX(m_sts);
LOGN("Sts");
SCSI_PHASE_CHANGE(SCSI_PHASE_STATUS);
// Bus settle delay 400ns built in to writeHandshake
writeHandshake(m_sts);
LOG(" MI:"); LOGHEX(m_msg);
LOGN("MsgIn");
SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEIN);
// Bus settle delay 400ns built in to writeHandshake
writeHandshake(m_msg);
BusFree:
LOGN(" BF");
LOGN("BusFree");
m_isBusReset = false;
//SCSI_OUT(vREQ,inactive) // gpio_write(REQ, low);
//SCSI_OUT(vMSG,inactive) // gpio_write(MSG, low);
@ -1323,7 +1325,7 @@ static byte onNOP(SCSI_DEVICE *dev, const byte *cdb)
*/
byte onInquiry(SCSI_DEVICE *dev, const byte *cdb)
{
writeDataPhase(cdb[4] < 47 ? cdb[4] : 47, dev->inquiry_block.raw);
writeDataPhase(cdb[4] < 47 ? cdb[4] : 47, dev->inquiry_block->raw);
return SCSI_STATUS_GOOD;
}
@ -1357,14 +1359,14 @@ byte onReadCapacity(SCSI_DEVICE *dev, const byte *cdb)
{
uint32_t lastlba = dev->m_blockcount - 1; // Points to last LBA
uint8_t buf[8] = {
lastlba >> 24,
lastlba >> 16,
lastlba >> 8,
lastlba,
dev->m_blocksize >> 24,
dev->m_blocksize >> 16,
dev->m_blocksize >> 8,
dev->m_blocksize
(byte)(lastlba >> 24),
(byte)(lastlba >> 16),
(byte)(lastlba >> 8),
(byte)(lastlba),
(byte)(dev->m_blocksize >> 24),
(byte)(dev->m_blocksize >> 16),
(byte)(dev->m_blocksize >> 8),
(byte)(dev->m_blocksize)
};
writeDataPhase(sizeof(buf), buf);
return SCSI_STATUS_GOOD;
@ -1544,13 +1546,13 @@ byte onModeSense(SCSI_DEVICE *dev, const byte *cdb)
if(!dbd && dev->m_type != SCSI_DEVICE_OPTICAL) {
byte c[8] = {
0,//Density code
dev->m_blockcount >> 16,
dev->m_blockcount >> 8,
dev->m_blockcount,
(byte)(dev->m_blockcount >> 16),
(byte)(dev->m_blockcount >> 8),
(byte)(dev->m_blockcount),
0, //Reserve
dev->m_blocksize >> 16,
dev->m_blocksize >> 8,
dev->m_blocksize,
(byte)(dev->m_blocksize >> 16),
(byte)(dev->m_blocksize >> 8),
(byte)(dev->m_blocksize),
};
memcpy(&m_buf[a], c, 8);
a += 8;
@ -1916,269 +1918,8 @@ byte onReadDefectData(SCSI_DEVICE *dev, const byte *cdb)
return SCSI_STATUS_GOOD;
}
<<<<<<< HEAD
<<<<<<< HEAD
/*
* MsgIn2.
*/
void MsgIn2(int msg)
{
LOGN("MsgIn2");
SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEIN);
// Bus settle delay 400ns built in to writeHandshake
writeHandshake(msg);
}
/*
* Main loop.
*/
void loop()
{
#ifdef XCVR
// Reset all DB and Target pins, switch transceivers to input
// Precaution against bugs or jumps which don't clean up properly
SCSI_DB_INPUT();
TRANSCEIVER_IO_SET(vTR_DBP,TR_INPUT)
SCSI_TARGET_INACTIVE();
TRANSCEIVER_IO_SET(vTR_INITIATOR,TR_INPUT)
#endif
//int msg = 0;
m_msg = 0;
m_lun = 0xff;
SCSI_DEVICE *dev = (SCSI_DEVICE *)0; // HDD image for current SCSI-ID, LUN
do {} while( !SCSI_IN(vBSY) || SCSI_IN(vRST));
// We're in ARBITRATION
//LOG(" A:"); LOGHEX(readIO()); LOG(" ");
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) {
delayMicroseconds(1);
return;
}
// We've been selected
#ifdef XCVR
// Reconfigure target pins to output mode, after resetting their values
GPIOB->regs->BSRR = 0x000000E8; // MSG, CD, REQ, IO
// GPIOA->regs->BSRR = 0x00000200; // BSY
#endif
SCSI_TARGET_ACTIVE() // (BSY), REQ, MSG, CD, IO output turned on
// Set BSY to-when selected
SCSI_BSY_ACTIVE(); // Turn only BSY output ON, ACTIVE
// Wait until SEL becomes inactive
while(isHigh(gpio_read(SEL))) {}
// Ask for a TARGET-ID to respond
m_id = 31 - __builtin_clz(scsiid);
m_isBusReset = false;
if (setjmp(m_resetJmpBuf) == 1) {
LOGN("Reset, going to BusFree");
goto BusFree;
}
enableResetJmp();
// In SCSI-2 this is mandatory, but in SCSI-1 it's optional
if(isHigh(gpio_read(ATN))) {
SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEOUT);
// Bus settle delay 400ns. Following code was measured at 350ns before REQ asserted. Added another 50ns. STM32F103.
SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEOUT);// 28ns delay STM32F103
SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEOUT);// 28ns delay STM32F103
bool syncenable = false;
int syncperiod = 50;
int syncoffset = 0;
int msc = 0;
while(isHigh(gpio_read(ATN)) && msc < 255) {
m_msb[msc++] = readHandshake();
}
for(int i = 0; i < msc; i++) {
// ABORT
if (m_msb[i] == 0x06) {
goto BusFree;
}
// BUS DEVICE RESET
if (m_msb[i] == 0x0C) {
syncoffset = 0;
goto BusFree;
}
// IDENTIFY
if (m_msb[i] >= 0x80) {
m_lun = m_msb[i] & 0x1f;
}
// Extended message
if (m_msb[i] == 0x01) {
// Check only when synchronous transfer is possible
if (!syncenable || m_msb[i + 2] != 0x01) {
MsgIn2(0x07);
break;
}
// Transfer period factor(50 x 4 = Limited to 200ns)
syncperiod = m_msb[i + 3];
if (syncperiod > 50) {
syncperiod = 50;
}
// REQ/ACK offset(Limited to 16)
syncoffset = m_msb[i + 4];
if (syncoffset > 16) {
syncoffset = 16;
}
// STDR response message generation
MsgIn2(0x01);
MsgIn2(0x03);
MsgIn2(0x01);
MsgIn2(syncperiod);
MsgIn2(syncoffset);
break;
}
}
}
LOG("Command:");
SCSI_PHASE_CHANGE(SCSI_PHASE_COMMAND);
// Bus settle delay 400ns. The following code was measured at 20ns before REQ asserted. Added another 380ns. STM32F103.
asm("nop;nop;nop;nop;nop;nop;nop;nop");// This asm causes some code reodering, which adds 270ns, plus 8 nop cycles for an additional 110ns. STM32F103
int len;
byte cmd[20];
cmd[0] = readHandshake();
// Atari ST ICD extension support
// It sends a 0x1F as a indicator there is a
// proper full size SCSI command byte to follow
// 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(); }
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]);
// Receive the remaining commands
for(int i = 6; i < len; i++ ) {
cmd[i] = readHandshake();
LOG(":");
LOGHEX(cmd[i]);
}
// 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;
}
LOG(":ID ");
LOG(m_id);
LOG(":LUN ");
LOG(m_lun);
LOGN("");
// HDD Image selection
if(m_lun >= NUM_SCSILUN)
{
m_sts = SCSI_STATUS_GOOD;
// REQUEST SENSE and INQUIRY are handled different with invalid LUNs
if(cmd[0] == SCSI_INQUIRY)
{
// Special INQUIRY handling for invalid LUNs
LOGN("onInquiry - InvalidLUN");
dev = &(scsi_device_list[m_id][0]);
byte temp = dev->inquiry_block->raw[0];
// If the LUN is invalid byte 0 of inquiry block needs to be 7fh
dev->inquiry_block->raw[0] = 0x7f;
// only write back what was asked for
writeDataPhase(cmd[4], dev->inquiry_block->raw);
// return it back to normal if it was altered
dev->inquiry_block->raw[0] = temp;
}
else if(cmd[0] == SCSI_REQUEST_SENSE)
{
byte buf[18] = {
0x70, //CheckCondition
0, //Segment number
SCSI_SENSE_ILLEGAL_REQUEST, //Sense key
0, 0, 0, 0, //information
10, //Additional data length
0, 0, 0, 0, // command specific information bytes
(byte)(SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED >> 8),
(byte)SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
0, 0, 0, 0,
};
writeDataPhase(cmd[4] < 18 ? cmd[4] : 18, buf);
}
else
{
m_sts = SCSI_STATUS_CHECK_CONDITION;
}
goto Status;
}
dev = &(scsi_device_list[m_id][m_lun]);
if(!dev->m_file)
{
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;
}
LED_ON();
m_sts = scsi_command_table[cmd[0]](dev, cmd);
LED_OFF();
Status:
LOGN("Sts");
SCSI_PHASE_CHANGE(SCSI_PHASE_STATUS);
// Bus settle delay 400ns built in to writeHandshake
writeHandshake(m_sts);
LOGN("MsgIn");
SCSI_PHASE_CHANGE(SCSI_PHASE_MESSAGEIN);
// Bus settle delay 400ns built in to writeHandshake
writeHandshake(m_msg);
BusFree:
LOGN("BusFree");
m_isBusReset = false;
//SCSI_OUT(vREQ,inactive) // gpio_write(REQ, low);
//SCSI_OUT(vMSG,inactive) // gpio_write(MSG, low);
//SCSI_OUT(vCD ,inactive) // gpio_write(CD, low);
//SCSI_OUT(vIO ,inactive) // gpio_write(IO, low);
//SCSI_OUT(vBSY,inactive)
SCSI_TARGET_INACTIVE() // Turn off BSY, REQ, MSG, CD, IO output
#ifdef XCVR
TRANSCEIVER_IO_SET(vTR_TARGET,TR_INPUT);
// Something in code linked after this function is performing better with a +4 alignment.
// Adding this nop is causing the next function (_GLOBAL__sub_I_SD) to have an address with a last digit of 0x4.
// Last digit of 0xc also works.
// This affects both with and without XCVR, currently without XCVR doesn't need any padding.
// Until the culprit can be tracked down and fixed, it may be necessary to do manual adjustment.
asm("nop.w");
#endif
}
=======
>>>>>>> faed60f (code layout adjustments)
=======
static byte onReadTOC(SCSI_DEVICE *dev, const byte *cdb)
{
unsigned lba = 0;
uint8_t msf = cdb[1] & 0x02;
uint8_t track = cdb[6];
unsigned len = ((uint32_t)cdb[7] << 8) | cdb[8];

View File

@ -218,7 +218,7 @@ enum SCSI_DEVICE_TYPE
// Put DB and DP in output mode
#define SCSI_DB_OUTPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_OUT; PBREG->CRH = 0x11111111*DB_MODE_OUT; }
// Put DB and DP in input mode
#define SCSI_DB_INPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_IN ; PBREG->CRH = 0x11111111*DB_MODE_IN; }
#define SCSI_DB_INPUT() { PBREG->CRL=(PBREG->CRL &0xfffffff0)|DB_MODE_IN ; PBREG->CRH = (uint32_t)0x11111111*DB_MODE_IN; }
// HDDiamge file
#define HDIMG_ID_POS 2 // Position to embed ID number