Release/Reserve Commands

This commit is contained in:
Eric Helgeson 2022-06-01 22:32:01 -05:00
parent 2338d8f153
commit ec3f5133b8
1 changed files with 76 additions and 5 deletions

View File

@ -218,11 +218,12 @@ SdFs SD;
// 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; }
// HDDiamge file
// HDD image file
#define HDIMG_ID_POS 2 // Position to embed ID number
#define HDIMG_LUN_POS 3 // Position to embed LUN numbers
#define HDIMG_BLK_POS 5 // Position to embed block size numbers
#define MAX_FILE_PATH 32 // Maximum file name length
#define RESERVE_FREE -1 // No reservation
// HDD image
typedef struct hddimg_struct
@ -230,6 +231,8 @@ typedef struct hddimg_struct
FsFile m_file; // File object
uint64_t m_fileSize; // File size
size_t m_blocksize; // SCSI BLOCK size
uint8_t m_reservation_id = RESERVE_FREE; // Reservation ID for Release/Reserve
uint8_t m_reserved_by_id = RESERVE_FREE; // ID of the target reserving
}HDDIMG;
HDDIMG img[NUM_SCSIID][NUM_SCSILUN]; // Maximum number
@ -240,6 +243,7 @@ volatile bool m_resetJmp = false; // Call longjmp on reset
jmp_buf m_resetJmpBuf;
byte scsi_id_mask; // Mask list of responding SCSI IDs
byte m_initiator_scsi_id; // Current target SCSI-ID
byte m_id; // Currently responding SCSI-ID
byte m_lun; // Logical unit number currently responding
byte m_sts; // Status byte
@ -760,7 +764,7 @@ void onFalseInit(void)
}
/*
* No SC Card found, blink 5x fast
* No SD Card found, blink 5x fast
*/
void noSDCardFound(void)
{
@ -1468,6 +1472,56 @@ byte onReadBuffer(byte mode, uint32_t allocLength)
}
}
/*
* On Release Reserve
*/
byte onReleaseReserve(const byte *cdb, HDDIMG *dev) {
byte cmd = cdb[0];
int reservation_id = cdb[2];
int extent_reservation = cdb[1] & 0x01;
int third_party = (cdb[1] >> 4) & 0x01;
int third_party_id = (cdb[1] >> 1) & 0x07;
reservation_id = third_party ? third_party_id : reservation_id;
if (extent_reservation)
{
m_senseKey = SCSI_SENSE_ILLEGAL_REQUEST;
m_addition_sense = SCSI_ASC_INVALID_FIELD_IN_CDB;
return SCSI_STATUS_CHECK_CONDITION;
}
int allowed_action = ((dev->m_reserved_by_id == m_initiator_scsi_id) ||
(dev->m_reservation_id == reservation_id));
if(cmd == SCSI_RESERVE)
{
if((dev->m_reservation_id == RESERVE_FREE) || allowed_action)
{
dev->m_reserved_by_id = m_initiator_scsi_id;
dev->m_reservation_id = reservation_id;
return SCSI_STATUS_GOOD;
}
else
{
return SCSI_STATUS_RESERVATION_CONFLICT;
}
}
else // SCSI_RELEASE
{
if(dev->m_reservation_id != RESERVE_FREE && allowed_action)
{
dev->m_reservation_id = RESERVE_FREE;
dev->m_reserved_by_id = RESERVE_FREE;
return SCSI_STATUS_GOOD;
}
else
{
return SCSI_STATUS_RESERVATION_CONFLICT;
}
}
return SCSI_STATUS_GOOD;
}
/*
* On Send Diagnostic
*/
@ -1524,8 +1578,8 @@ void loop()
// If the ID to respond is not driven, wait for the next
//byte db = readIO();
//byte scsiid = db & scsi_id_mask;
byte scsiid = readIO() & scsi_id_mask;
if((scsiid) == 0) {
m_initiator_scsi_id = readIO() & scsi_id_mask;
if((m_initiator_scsi_id) == 0) {
delayMicroseconds(1);
return;
}
@ -1541,7 +1595,7 @@ void loop()
SCSI_BSY_ACTIVE(); // Turn only BSY output ON, ACTIVE
// Ask for a TARGET-ID to respond
m_id = 31 - __builtin_clz(scsiid);
m_id = 31 - __builtin_clz(m_initiator_scsi_id);
// Wait until SEL becomes inactive
while(isHigh(gpio_read(SEL)) && isLow(gpio_read(BSY))) {
@ -1650,6 +1704,17 @@ void loop()
LOG(m_lun);
LOGN("");
// If this device is reserved, and the current initiator id is not the reserved by id, then
if(m_img->m_reserved_by_id != RESERVE_FREE && m_initiator_scsi_id != m_img->m_reserved_by_id)
{
// Return conflict if not one of these commands
if(cmd[0] != SCSI_INQUIRY && cmd[0] != SCSI_REQUEST_SENSE && cmd[0] != SCSI_RELEASE &&
(cmd[0] == SCSI_PREVENT_ALLOW_REMOVAL && ((cmd[4] & 1) != 0))) // Prevent removal only allowed if prevent is 1
{
m_sts |= SCSI_STATUS_RESERVATION_CONFLICT;
goto Status;
}
}
switch(cmd[0]) {
case SCSI_READ6:
LOGN("[Read6]");
@ -1734,6 +1799,11 @@ void loop()
case SCSI_SEND_DIAG:
m_sts |= onSendDiagnostic(cmd[1]);
break;
case SCSI_RELEASE:
case SCSI_RESERVE:
LOGN("[ReleaseReserve]");
m_sts |= onReleaseReserve(cmd, m_img);
break;
case SCSI_LOCK_UNLOCK_CACHE: // Commands we dont have anything to do but can safely respond GOOD.
case SCSI_PREFETCH: // In the future we could implement something to mimic these.
case SCSI_PREVENT_ALLOW_REMOVAL:
@ -1749,6 +1819,7 @@ void loop()
break;
}
Status:
LOGN("Sts");
SCSI_PHASE_CHANGE(SCSI_PHASE_STATUS);
// Bus settle delay 400ns built in to writeHandshake