mirror of
https://github.com/dkgrizzly/GreenSCSI.git
synced 2025-04-10 07:38:47 +00:00
This commit is seemingly stable with transfer speeds around 1.5MB/s - 1.6MB/s, equal to speeds obtained
from TinySCSIEmu with the NCR5380 PHY. Successfully booted OpenVMS and Digital UNIX on an DEC Alpha 3000/300. + Interrupt-driven SCSI Data bus for Read & Write block routines + Low-Level Hardware register access for GPIO manipulation + Initial Optical Drive Emulation ported from TinySCSIEmu + Additional Mode Sense / Mode Select work to enable booting OpenVMS and Digital UNIX from CD or HD + Per-ID Inquiry Response editing via [CH]Dxx_xxx.cfg files instead of SCSI_CONFIG.TXT (same format) + Images should now be named CDxx_xxx.img or HDxx_xxx.img instead of HDxx_xxx.hda
This commit is contained in:
parent
f4bb40a094
commit
c2bac1a9d0
120
src/disk.ino
Executable file
120
src/disk.ino
Executable file
@ -0,0 +1,120 @@
|
||||
#include "scsi_defs.h"
|
||||
|
||||
void Read6CommandHandler() {
|
||||
LOG("[Read6]");
|
||||
m_sts |= onReadCommand((((uint32_t)m_cmd[1] & 0x1F) << 16) | ((uint32_t)m_cmd[2] << 8) | m_cmd[3], (m_cmd[4] == 0) ? 0x100 : m_cmd[4]);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void Write6CommandHandler() {
|
||||
LOG("[Write6]");
|
||||
m_sts |= onWriteCommand((((uint32_t)m_cmd[1] & 0x1F) << 16) | ((uint32_t)m_cmd[2] << 8) | m_cmd[3], (m_cmd[4] == 0) ? 0x100 : m_cmd[4]);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void Seek6CommandHandler() {
|
||||
LOG("[Seek6]");
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* READ CAPACITY command processing.
|
||||
*/
|
||||
void ReadCapacityCommandHandler() {
|
||||
LOGN("[ReadCapacity]");
|
||||
if(!m_img) {
|
||||
m_sts |= 0x02; // Image file absent
|
||||
m_phase = PHASE_STATUSIN;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t bl = m_img->m_blocksize;
|
||||
uint32_t bc = m_img->m_fileSize / bl;
|
||||
uint8_t buf[8] = {
|
||||
(uint8_t)(((uint32_t)(bc >> 24))&0xff), (uint8_t)(((uint32_t)(bc >> 16))&0xff), (uint8_t)(((uint32_t)(bc >> 8))&0xff), (uint8_t)(((uint32_t)(bc))&0xff),
|
||||
(uint8_t)(((uint32_t)(bl >> 24))&0xff), (uint8_t)(((uint32_t)(bl >> 16))&0xff), (uint8_t)(((uint32_t)(bl >> 8))&0xff), (uint8_t)(((uint32_t)(bl))&0xff)
|
||||
};
|
||||
writeDataPhase(8, buf);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void Read10CommandHandler() {
|
||||
LOG("[Read10]");
|
||||
m_sts |= onReadCommand(((uint32_t)m_cmd[2] << 24) | ((uint32_t)m_cmd[3] << 16) | ((uint32_t)m_cmd[4] << 8) | m_cmd[5], ((uint32_t)m_cmd[7] << 8) | m_cmd[8]);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void Write10CommandHandler() {
|
||||
LOG("[Write10]");
|
||||
m_sts |= onWriteCommand(((uint32_t)m_cmd[2] << 24) | ((uint32_t)m_cmd[3] << 16) | ((uint32_t)m_cmd[4] << 8) | m_cmd[5], ((uint32_t)m_cmd[7] << 8) | m_cmd[8]);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void Seek10CommandHandler() {
|
||||
LOG("[Seek10]");
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* READ6 / 10 Command processing.
|
||||
*/
|
||||
uint8_t onReadCommand(uint32_t adds, uint32_t len)
|
||||
{
|
||||
LOG("-R ");
|
||||
LOGHEX6(adds);
|
||||
LOG(" ");
|
||||
LOGHEX4N(len);
|
||||
|
||||
if(!m_img) return 0x02; // Image file absent
|
||||
|
||||
LED_ON();
|
||||
writeDataPhaseSD(adds, len);
|
||||
LED_OFF();
|
||||
return 0x00; //sts
|
||||
}
|
||||
|
||||
/*
|
||||
* WRITE6 / 10 Command processing.
|
||||
*/
|
||||
uint8_t onWriteCommand(uint32_t adds, uint32_t len)
|
||||
{
|
||||
LOG("-W ");
|
||||
LOGHEX6(adds);
|
||||
LOG(" ");
|
||||
LOGHEX4N(len);
|
||||
|
||||
if(!m_img) return 0x02; // Image file absent
|
||||
|
||||
LED_ON();
|
||||
readDataPhaseSD(adds, len);
|
||||
LED_OFF();
|
||||
return 0; //sts
|
||||
}
|
||||
|
||||
void ConfigureDiskHandlers(int id) {
|
||||
for(int c = 0; c < 256; c++)
|
||||
m_handler[id][c] = &UnknownCommandHandler;
|
||||
|
||||
m_handler[id][CMD_TEST_UNIT_READY] = &TestUnitCommandHandler;
|
||||
m_handler[id][CMD_REZERO_UNIT] = &RezeroUnitCommandHandler;
|
||||
m_handler[id][CMD_REQUEST_SENSE] = &RequestSenseCommandHandler;
|
||||
m_handler[id][CMD_FORMAT_UNIT] = &FormatUnitCommandHandler;
|
||||
m_handler[id][0x06] = &FormatUnitCommandHandler;
|
||||
m_handler[id][0x07] = &ReassignBlocksCommandHandler;
|
||||
m_handler[id][CMD_READ6] = &Read6CommandHandler;
|
||||
m_handler[id][CMD_WRITE6] = &Write6CommandHandler;
|
||||
m_handler[id][CMD_SEEK6] = &Seek6CommandHandler;
|
||||
m_handler[id][CMD_INQUIRY] = &InquiryCommandHandler;
|
||||
m_handler[id][CMD_MODE_SELECT6] = &ModeSelect6CommandHandler;
|
||||
m_handler[id][CMD_MODE_SENSE6] = &ModeSense6CommandHandler;
|
||||
m_handler[id][CMD_START_STOP_UNIT] = &StartStopUnitCommandHandler;
|
||||
m_handler[id][CMD_PREVENT_REMOVAL] = &PreAllowMediumRemovalCommandHandler;
|
||||
m_handler[id][CMD_READ_CAPACITY10] = &ReadCapacityCommandHandler;
|
||||
m_handler[id][CMD_READ10] = &Read10CommandHandler;
|
||||
m_handler[id][CMD_WRITE10] = &Write10CommandHandler;
|
||||
m_handler[id][CMD_SEEK10] = &Seek10CommandHandler;
|
||||
m_handler[id][CMD_MODE_SENSE10] = &ModeSense10CommandHandler;
|
||||
#if SCSI_SELECT == 1
|
||||
m_handler[id][0xC2] = &DTCsetDriveParameterCommandHandler;
|
||||
#endif
|
||||
}
|
140
src/general.ino
Executable file
140
src/general.ino
Executable file
@ -0,0 +1,140 @@
|
||||
#include "scsi_defs.h"
|
||||
|
||||
|
||||
/*
|
||||
* INQUIRY command processing.
|
||||
*/
|
||||
void InquiryCommandHandler() {
|
||||
LOGN("[Inquiry]");
|
||||
uint8_t len = m_cmd[4];
|
||||
uint8_t buf[36];
|
||||
memcpy(buf, m_inquiryresponse[m_id], 36);
|
||||
|
||||
if(!m_img) buf[0] = 0x7f;
|
||||
|
||||
writeDataPhase(len < 36 ? len : 36, buf);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* REQUEST SENSE command processing.
|
||||
*/
|
||||
void RequestSenseCommandHandler() {
|
||||
LOGN("[RequestSense]");
|
||||
uint8_t len = m_cmd[4];
|
||||
uint8_t buf[18] = {
|
||||
0x70, //CheckCondition
|
||||
0, //Segment number
|
||||
0x00, //Sense key
|
||||
0, 0, 0, 0, //information
|
||||
17 - 7 , //Additional data length
|
||||
0,
|
||||
};
|
||||
|
||||
if(!m_img) {
|
||||
// Image file absent
|
||||
buf[2] = 0x02; // NOT_READY
|
||||
buf[12] = 0x25; // Logical Unit Not Supported
|
||||
} else {
|
||||
buf[2] = m_sense[m_id][m_lun].m_key;
|
||||
m_sense[m_id][m_lun].m_key = 0;
|
||||
}
|
||||
writeDataPhase(len < 18 ? len : 18, buf);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void TestUnitCommandHandler() {
|
||||
LOGN("[TestUnit]");
|
||||
if(!m_img) {
|
||||
// Image file absent
|
||||
m_sense[m_id][m_lun].m_key = NOT_READY; // NOT_READY
|
||||
m_sense[m_id][m_lun].m_code = NO_MEDIA; // Logical Unit Not Supported
|
||||
}
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void RezeroUnitCommandHandler() {
|
||||
LOGN("[RezeroUnit]");
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void FormatUnitCommandHandler() {
|
||||
LOGN("[FormatUnit]");
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void ReassignBlocksCommandHandler() {
|
||||
LOGN("[ReassignBlocks]");
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void ModeSense6CommandHandler() {
|
||||
LOGN("[ModeSense6]");
|
||||
m_sts |= onModeSenseCommand(m_cmd[1]&0x80, m_cmd[2], m_cmd[4]);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
uint8_t onModeSelectCommand() {
|
||||
m_sense[m_id][m_lun].m_code = INVALID_FIELD_IN_CDB; /* "Invalid field in CDB" */
|
||||
m_sense[m_id][m_lun].m_key_specific[0] = ERROR_IN_OPCODE; /* "Error in Byte 2" */
|
||||
m_sense[m_id][m_lun].m_key_specific[1] = 0x00;
|
||||
m_sense[m_id][m_lun].m_key_specific[2] = 0x04;
|
||||
return 0x02;
|
||||
}
|
||||
|
||||
void ModeSelect6CommandHandler() {
|
||||
LOG("[ModeSelect6] ");
|
||||
uint16_t len = m_cmd[4];
|
||||
readDataPhase(len, m_buf);
|
||||
|
||||
for(int i = 1; i < len; i++ ) {
|
||||
LOG(":");
|
||||
LOGHEX2(m_buf[i]);
|
||||
}
|
||||
LOGN("");
|
||||
// m_sts |= onModeSelectCommand();
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void ModeSelect10CommandHandler() {
|
||||
LOGN("[ModeSelect10]");
|
||||
uint16_t len = ((uint16_t)m_cmd[7] << 8) | m_cmd[8];
|
||||
readDataPhase(len, m_buf);
|
||||
|
||||
for(int i = 1; i < len; i++ ) {
|
||||
LOG(":");
|
||||
LOGHEX2(m_buf[i]);
|
||||
}
|
||||
LOGN("");
|
||||
// m_sts |= onModeSelectCommand();
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void StartStopUnitCommandHandler() {
|
||||
LOGN("[StartStopUnit]");
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void PreAllowMediumRemovalCommandHandler() {
|
||||
LOGN("[PreAllowMed.Removal]");
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void ModeSense10CommandHandler() {
|
||||
LOGN("[ModeSense10]");
|
||||
onModeSenseCommand(m_cmd[1] & 0x80, m_cmd[2], ((uint32_t)m_cmd[7] << 8) | m_cmd[8]);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void UnknownCommandHandler() {
|
||||
LOGN("[*Unknown]");
|
||||
m_sts |= 0x02;
|
||||
m_sense[m_id][m_lun].m_key = 5;
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void BadLunCommandHandler() {
|
||||
LOGN("[Bad LUN]");
|
||||
m_sts |= 0x02;
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
1614
src/greenscsi-next.ino
Executable file
1614
src/greenscsi-next.ino
Executable file
File diff suppressed because it is too large
Load Diff
660
src/optical.ino
Executable file
660
src/optical.ino
Executable file
@ -0,0 +1,660 @@
|
||||
#include "scsi_defs.h"
|
||||
|
||||
static const uint8_t SessionTOC[] =
|
||||
{
|
||||
0x00, // toc length, MSB
|
||||
0x0A, // toc length, LSB
|
||||
0x01, // First session number
|
||||
0x01, // Last session number,
|
||||
// TRACK 1 Descriptor
|
||||
0x00, // reserved
|
||||
0x14, // Q sub-channel encodes current position, Digital track
|
||||
0x01, // First track number in last complete session
|
||||
0x00, // Reserved
|
||||
0x00,0x00,0x00,0x00 // LBA of first track in last session
|
||||
};
|
||||
|
||||
static const uint8_t FullTOC[] =
|
||||
{
|
||||
0x00, // toc length, MSB
|
||||
0x44, // toc length, LSB
|
||||
0x01, // First session number
|
||||
0x01, // Last session number,
|
||||
// A0 Descriptor
|
||||
0x01, // session number
|
||||
0x14, // ADR/Control
|
||||
0x00, // TNO
|
||||
0xA0, // POINT
|
||||
0x00, // Min
|
||||
0x00, // Sec
|
||||
0x00, // Frame
|
||||
0x00, // Zero
|
||||
0x01, // First Track number.
|
||||
0x00, // Disc type 00 = Mode 1
|
||||
0x00, // PFRAME
|
||||
// A1
|
||||
0x01, // session number
|
||||
0x14, // ADR/Control
|
||||
0x00, // TNO
|
||||
0xA1, // POINT
|
||||
0x00, // Min
|
||||
0x00, // Sec
|
||||
0x00, // Frame
|
||||
0x00, // Zero
|
||||
0x01, // Last Track number
|
||||
0x00, // PSEC
|
||||
0x00, // PFRAME
|
||||
// A2
|
||||
0x01, // session number
|
||||
0x14, // ADR/Control
|
||||
0x00, // TNO
|
||||
0xA2, // POINT
|
||||
0x00, // Min
|
||||
0x00, // Sec
|
||||
0x00, // Frame
|
||||
0x00, // Zero
|
||||
0x79, // LEADOUT position BCD
|
||||
0x59, // leadout PSEC BCD
|
||||
0x74, // leadout PFRAME BCD
|
||||
// TRACK 1 Descriptor
|
||||
0x01, // session number
|
||||
0x14, // ADR/Control
|
||||
0x00, // TNO
|
||||
0x01, // Point
|
||||
0x00, // Min
|
||||
0x00, // Sec
|
||||
0x00, // Frame
|
||||
0x00, // Zero
|
||||
0x00, // PMIN
|
||||
0x00, // PSEC
|
||||
0x00, // PFRAME
|
||||
// b0
|
||||
0x01, // session number
|
||||
0x54, // ADR/Control
|
||||
0x00, // TNO
|
||||
0xB1, // POINT
|
||||
0x79, // Min BCD
|
||||
0x59, // Sec BCD
|
||||
0x74, // Frame BCD
|
||||
0x00, // Zero
|
||||
0x79, // PMIN BCD
|
||||
0x59, // PSEC BCD
|
||||
0x74, // PFRAME BCD
|
||||
// c0
|
||||
0x01, // session number
|
||||
0x54, // ADR/Control
|
||||
0x00, // TNO
|
||||
0xC0, // POINT
|
||||
0x00, // Min
|
||||
0x00, // Sec
|
||||
0x00, // Frame
|
||||
0x00, // Zero
|
||||
0x00, // PMIN
|
||||
0x00, // PSEC
|
||||
0x00 // PFRAME
|
||||
};
|
||||
|
||||
static const uint8_t DiscInfoBlock[] =
|
||||
{
|
||||
0x00, // disc info length, MSB
|
||||
0x44, // disc info length, LSB
|
||||
0x0e, // DiscStatus = Complete
|
||||
0x01, // First Track on Disc
|
||||
0x01, // Sessions on Disc (LSB)
|
||||
0x01, // First Track in Last Session (LSB)
|
||||
0x01, // Last Track in Last Session (LSB)
|
||||
0x20, // DID_V DBC_V URU
|
||||
0x00, // Disc Type
|
||||
0x00, // Sessions on Disc (MSB)
|
||||
0x00, // First Track in Last Session (MSB)
|
||||
0x00, // Last Track in Last Session (MSB)
|
||||
0x00, // DiscID (MSB)
|
||||
0x00, // DiscID
|
||||
0x00, // DiscID
|
||||
0x00, // DiscID (LSB)
|
||||
0x00, // Last Session Lead-In Start (MSB)
|
||||
0x00, // IN MSF
|
||||
0x00, //
|
||||
0x00, // Last Session Lead-In Start (LSB)
|
||||
0x00, // Last Possible Lead-Out Start (MSB)
|
||||
0x00, // IN MSF
|
||||
0x00, //
|
||||
0x00, // Last Possible Lead-Out Start (LSB)
|
||||
0x00, // Bar Code (MSB)
|
||||
0x00, //
|
||||
0x00, //
|
||||
0x00, //
|
||||
0x00, //
|
||||
0x00, //
|
||||
0x00, //
|
||||
0x00, // Bar Code (LSB)
|
||||
0x00, // Reserved
|
||||
0x00, // Number of OPC Entries
|
||||
};
|
||||
|
||||
static void LBA2MSF(uint32_t LBA, uint8_t* MSF)
|
||||
{
|
||||
MSF[0] = 0; // reserved.
|
||||
MSF[3] = (uint32_t)(LBA % 75); // F
|
||||
uint32_t rem = LBA / 75;
|
||||
|
||||
MSF[2] = (uint32_t)(rem % 60); // S
|
||||
MSF[1] = (uint32_t)(rem / 60); // M
|
||||
}
|
||||
|
||||
|
||||
void OpticalModeSense6CommandHandler() {
|
||||
uint8_t len;
|
||||
int page, pagemax, pagemin;
|
||||
|
||||
LOGN("[ModeSense6]");
|
||||
/* Check whether medium is present */
|
||||
if(!m_img) {
|
||||
m_sts |= 0x02;
|
||||
m_phase = PHASE_STATUSIN;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(m_responsebuffer, 0, sizeof(m_responsebuffer));
|
||||
|
||||
len = 1;
|
||||
/* Default medium type */
|
||||
m_responsebuffer[len++] = 0xf0;
|
||||
/* Write protected */
|
||||
m_responsebuffer[len++] = 0x80;
|
||||
|
||||
/* Add block descriptor if DBD is not set */
|
||||
if (m_cmd[1] & 0x08) {
|
||||
m_responsebuffer[len++] = 0; /* No block descriptor */
|
||||
} else {
|
||||
uint32_t capacity = (m_img->m_fileSize / m_img->m_blocksize) - 1;
|
||||
m_responsebuffer[len++] = 8; /* Block descriptor length */
|
||||
m_responsebuffer[len++] = (capacity >> 24) & 0xff;
|
||||
m_responsebuffer[len++] = (capacity >> 16) & 0xff;
|
||||
m_responsebuffer[len++] = (capacity >> 8) & 0xff;
|
||||
m_responsebuffer[len++] = capacity & 0xff;
|
||||
m_responsebuffer[len++] = (m_img->m_blocksize >> 24) & 0xff;
|
||||
m_responsebuffer[len++] = (m_img->m_blocksize >> 16) & 0xff;
|
||||
m_responsebuffer[len++] = (m_img->m_blocksize >> 8) & 0xff;
|
||||
m_responsebuffer[len++] = (m_img->m_blocksize) & 0xff;
|
||||
}
|
||||
|
||||
/* Check for requested mode page */
|
||||
page = m_cmd[2] & 0x3F;
|
||||
pagemax = (page != 0x3f) ? page : 0x3e;
|
||||
pagemin = (page != 0x3f) ? page : 0x00;
|
||||
for(page = pagemax; page >= pagemin; page--) {
|
||||
switch (page) {
|
||||
case MODEPAGE_VENDOR_SPECIFIC:
|
||||
/* Accept request only for current values */
|
||||
if (m_cmd[2] & 0xC0) {
|
||||
//DEBUGPRINT(DBG_TRACE, " [2]==%d", m_cmd[2]);
|
||||
/* Prepare sense data */
|
||||
m_sts |= STATUS_CHECK;
|
||||
m_sense[m_id][m_lun].m_key = ILLEGAL_REQUEST;
|
||||
m_sense[m_id][m_lun].m_code = INVALID_FIELD_IN_CDB; /* "Invalid field in CDB" */
|
||||
m_sense[m_id][m_lun].m_key_specific[0] = ERROR_IN_OPCODE; /* "Error in Byte 2" */
|
||||
m_sense[m_id][m_lun].m_key_specific[1] = 0x00;
|
||||
m_sense[m_id][m_lun].m_key_specific[2] = 0x02;
|
||||
m_phase = PHASE_STATUSIN;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unit attention */
|
||||
m_responsebuffer[len++] = 0x80; // PS, page id
|
||||
m_responsebuffer[len++] = 0x02; // Page length
|
||||
m_responsebuffer[len++] = 0x00;
|
||||
m_responsebuffer[len++] = 0x00;
|
||||
break;
|
||||
#if 0
|
||||
case MODEPAGE_DCRC_PARAMETERS:
|
||||
m_responsebuffer[len++] = 0x82; // PS, page id
|
||||
m_responsebuffer[len++] = 0x0e; // Page length
|
||||
m_responsebuffer[len++] = 0xe6; // Buffer full ratio, 90%
|
||||
m_responsebuffer[len++] = 0x1a; // Buffer empty ratio, 10%
|
||||
m_responsebuffer[len++] = 0x00; // Bus inactivity limit
|
||||
m_responsebuffer[len++] = 0x00;
|
||||
m_responsebuffer[len++] = 0x00; // Disconnect time limit
|
||||
m_responsebuffer[len++] = 0x00;
|
||||
m_responsebuffer[len++] = 0x00; // Connect time limit
|
||||
m_responsebuffer[len++] = 0x00;
|
||||
m_responsebuffer[len++] = 0x00; // Maximum burst size
|
||||
m_responsebuffer[len++] = 0x00;
|
||||
m_responsebuffer[len++] = 0x00; // EMDP, Dimm, DTDC
|
||||
m_responsebuffer[len++] = 0x00; // Reserved
|
||||
m_responsebuffer[len++] = 0x00; // Reserved
|
||||
m_responsebuffer[len++] = 0x00; // Reserved
|
||||
break;
|
||||
#endif
|
||||
case MODEPAGE_RW_ERROR_RECOVERY:
|
||||
m_responsebuffer[len++] = 0x81; // PS, page id
|
||||
m_responsebuffer[len++] = 0x0a; // Page length
|
||||
m_responsebuffer[len++] = 0x07; //
|
||||
m_responsebuffer[len++] = 0x00; // Read Retry Count
|
||||
m_responsebuffer[len++] = 0x00; // Reserved
|
||||
m_responsebuffer[len++] = 0x00; // Reserved
|
||||
m_responsebuffer[len++] = 0x00; // Reserved
|
||||
m_responsebuffer[len++] = 0x00; // Reserved
|
||||
m_responsebuffer[len++] = 0x00; // Write Retry Count
|
||||
m_responsebuffer[len++] = 0x00; // Reserved
|
||||
m_responsebuffer[len++] = 0x00; // Recovery Time Limit
|
||||
m_responsebuffer[len++] = 0x00;
|
||||
break;
|
||||
default:
|
||||
if(pagemin == pagemax) {
|
||||
/* Requested mode page is not supported */
|
||||
/* Prepare sense data */
|
||||
m_sts |= STATUS_CHECK;
|
||||
m_sense[m_id][m_lun].m_key = ILLEGAL_REQUEST;
|
||||
m_sense[m_id][m_lun].m_code = INVALID_FIELD_IN_CDB; /* "Invalid field in CDB" */
|
||||
m_sense[m_id][m_lun].m_key_specific[0] = ERROR_IN_OPCODE; /* "Error in Byte 2" */
|
||||
m_sense[m_id][m_lun].m_key_specific[1] = 0x00;
|
||||
m_sense[m_id][m_lun].m_key_specific[2] = 0x02;
|
||||
m_phase = PHASE_STATUSIN;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Report size of requested data */
|
||||
m_responsebuffer[0] = len;
|
||||
|
||||
/* Truncate data if necessary */
|
||||
if (m_cmd[4] < len) {
|
||||
len = m_cmd[4];
|
||||
}
|
||||
|
||||
// Send it
|
||||
writeDataPhase(len, m_responsebuffer);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void OpticalReadSimpleTOC()
|
||||
{
|
||||
int MSF = m_cmd[1] & 0x02 ? 1 : 0;
|
||||
uint16_t allocationLength = (m_cmd[7] << 8) | m_cmd[8];
|
||||
uint8_t len = 0;
|
||||
|
||||
if(!m_img) {
|
||||
m_sts |= 0x02;
|
||||
m_phase = PHASE_STATUSIN;
|
||||
return;
|
||||
}
|
||||
|
||||
memset(m_responsebuffer, 0, sizeof(m_responsebuffer));
|
||||
|
||||
uint32_t capacity = (m_img->m_fileSize / m_img->m_blocksize) - 1;
|
||||
m_responsebuffer[len++] = 0x00; // toc length, MSB
|
||||
m_responsebuffer[len++] = 0x00; // toc length, LSB
|
||||
m_responsebuffer[len++] = 0x01; // First track number
|
||||
m_responsebuffer[len++] = 0x01; // Last track number
|
||||
|
||||
// We only support track 1 and 0xaa (lead-out).
|
||||
// track 0 means "return all tracks"
|
||||
switch (m_cmd[6]) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
m_responsebuffer[len++] = 0x00; // reserved
|
||||
m_responsebuffer[len++] = 0x14; // Q sub-channel encodes current position, Digital track
|
||||
m_responsebuffer[len++] = 0x01; // Track 1
|
||||
m_responsebuffer[len++] = 0x00; // Reserved
|
||||
m_responsebuffer[len++] = 0x00; // MSB LBA
|
||||
m_responsebuffer[len++] = 0x00; //
|
||||
m_responsebuffer[len++] = 0x00; //
|
||||
m_responsebuffer[len++] = 0x00; // LSB LBA
|
||||
case 0xAA:
|
||||
m_responsebuffer[len++] = 0x00; // reserved
|
||||
m_responsebuffer[len++] = 0x14; // Q sub-channel encodes current position, Digital track
|
||||
m_responsebuffer[len++] = 0xAA; // Leadout Track
|
||||
m_responsebuffer[len++] = 0x00; // Reserved
|
||||
// Replace start of leadout track
|
||||
if (MSF)
|
||||
{
|
||||
LBA2MSF(capacity, m_responsebuffer + len);
|
||||
len+=4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Track start sector (LBA)
|
||||
m_responsebuffer[len++] = capacity >> 24;
|
||||
m_responsebuffer[len++] = capacity >> 16;
|
||||
m_responsebuffer[len++] = capacity >> 8;
|
||||
m_responsebuffer[len++] = capacity;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_sts |= STATUS_CHECK;
|
||||
m_sense[m_id][m_lun].m_key = ILLEGAL_REQUEST; // Illegal Request
|
||||
m_sense[m_id][m_lun].m_code = INVALID_FIELD_IN_CDB; // Invalid field in CDB
|
||||
m_sense[m_id][m_lun].m_key_specific[0] = ERROR_IN_OPCODE; // Error in Byte 6
|
||||
m_sense[m_id][m_lun].m_key_specific[1] = 0x00;
|
||||
m_sense[m_id][m_lun].m_key_specific[2] = 0x06;
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
m_responsebuffer[0] = (len >> 8) & 0xff;
|
||||
m_responsebuffer[1] = len & 0xff;
|
||||
|
||||
// Truncate if necessary
|
||||
if(allocationLength < len)
|
||||
len = allocationLength;
|
||||
|
||||
// Send it
|
||||
writeDataPhase(len, m_responsebuffer);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void OpticalReadSessionInfo()
|
||||
{
|
||||
// int MSF = m_cmd[1] & 0x02 ? 1 : 0;
|
||||
uint16_t allocationLength = (m_cmd[7] << 8) | m_cmd[8];
|
||||
uint32_t len = sizeof(SessionTOC);
|
||||
memcpy(m_responsebuffer, SessionTOC, len);
|
||||
|
||||
// Truncate if necessary
|
||||
if(allocationLength < len)
|
||||
len = allocationLength;
|
||||
|
||||
// Send it
|
||||
writeDataPhase(len, m_responsebuffer);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
uint8_t fromBCD(uint8_t val)
|
||||
{
|
||||
return ((val >> 4) * 10) + (val & 0xF);
|
||||
}
|
||||
|
||||
void OpticalReadFullTOC(int convertBCD)
|
||||
{
|
||||
uint16_t allocationLength = (m_cmd[7] << 8) | m_cmd[8];
|
||||
// We only support session 1.
|
||||
if (m_cmd[6] > 1) {
|
||||
m_sts |= STATUS_CHECK;
|
||||
m_sense[m_id][m_lun].m_key = ILLEGAL_REQUEST; // Illegal Request
|
||||
m_sense[m_id][m_lun].m_code = INVALID_FIELD_IN_CDB; // Invalid field in CDB
|
||||
m_sense[m_id][m_lun].m_key_specific[0] = ERROR_IN_OPCODE; // Error in Byte 6
|
||||
m_sense[m_id][m_lun].m_key_specific[1] = 0x00;
|
||||
m_sense[m_id][m_lun].m_key_specific[2] = 0x06;
|
||||
m_phase = PHASE_STATUSIN;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t len = sizeof(FullTOC);
|
||||
memcpy(m_responsebuffer, FullTOC, len);
|
||||
|
||||
if (convertBCD)
|
||||
{
|
||||
uint32_t descriptor = 4;
|
||||
while (descriptor < len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 7; ++i)
|
||||
{
|
||||
m_responsebuffer[descriptor + i] =
|
||||
fromBCD(m_responsebuffer[descriptor + 4 + i]);
|
||||
}
|
||||
descriptor += 11;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Truncate if necessary
|
||||
if(allocationLength < len)
|
||||
len = allocationLength;
|
||||
|
||||
// Send it
|
||||
writeDataPhase(len, m_responsebuffer);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void OpticalReadTOCCommandHandler()
|
||||
{
|
||||
LOGN("[Read TOC]");
|
||||
switch(m_cmd[2] & 0xf) {
|
||||
case 0:
|
||||
LOGN("Simple");
|
||||
OpticalReadSimpleTOC();
|
||||
return;
|
||||
case 1:
|
||||
LOGN("Session");
|
||||
OpticalReadSessionInfo();
|
||||
return;
|
||||
case 2:
|
||||
LOGN("Full 0");
|
||||
OpticalReadFullTOC(0);
|
||||
return;
|
||||
case 3:
|
||||
LOGN("Full 1");
|
||||
OpticalReadFullTOC(1);
|
||||
return;
|
||||
}
|
||||
|
||||
m_sts |= STATUS_CHECK;
|
||||
m_sense[m_id][m_lun].m_key = ILLEGAL_REQUEST; // Illegal Request
|
||||
m_sense[m_id][m_lun].m_code = INVALID_FIELD_IN_CDB; // Invalid field in CDB
|
||||
m_sense[m_id][m_lun].m_key_specific[0] = ERROR_IN_OPCODE; // Error in Byte 2
|
||||
m_sense[m_id][m_lun].m_key_specific[1] = 0x00;
|
||||
m_sense[m_id][m_lun].m_key_specific[2] = 0x02;
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
static uint8_t SimpleHeader[] =
|
||||
{
|
||||
0x01, // 2048byte user data, L-EC in 288 byte aux field.
|
||||
0x00, // reserved
|
||||
0x00, // reserved
|
||||
0x00, // reserved
|
||||
0x00,0x00,0x00,0x00 // Track start sector (LBA or MSF)
|
||||
};
|
||||
|
||||
void OpticalHeaderCommandHandler()
|
||||
{
|
||||
uint32_t len = sizeof(SimpleHeader);
|
||||
memcpy(m_responsebuffer, SimpleHeader, len);
|
||||
|
||||
LOGN("[Read Header]");
|
||||
|
||||
//int MSF = m_cmd[1] & 0x02 ? 1 : 0;
|
||||
//uint32_t lba = 0;
|
||||
uint16_t allocationLength = (m_cmd[7] << 8) | m_cmd[8];
|
||||
|
||||
// Truncate if necessary
|
||||
if(allocationLength < len)
|
||||
len = allocationLength;
|
||||
|
||||
// Send it
|
||||
writeDataPhase(len, m_responsebuffer);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
|
||||
void OpticalReadDiscInfoCommandHandler()
|
||||
{
|
||||
uint16_t allocationLength = (m_cmd[7] << 8) | m_cmd[8];
|
||||
uint32_t len = sizeof(DiscInfoBlock);
|
||||
uint32_t capacity = (m_img->m_fileSize / m_img->m_blocksize) - 1;
|
||||
memcpy(m_responsebuffer, DiscInfoBlock, len);
|
||||
|
||||
LOGN("[DiscInfo]");
|
||||
|
||||
// Truncate if necessary
|
||||
if(allocationLength < len)
|
||||
len = allocationLength;
|
||||
|
||||
LBA2MSF(capacity, m_responsebuffer + 20);
|
||||
|
||||
// Send it
|
||||
writeDataPhase(len, m_responsebuffer);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
uint16_t SupportedFeatures[] = {
|
||||
0x0001, // Core Features
|
||||
0x0003, // Removable Media
|
||||
0x0010, // Random Readable
|
||||
0x001D, // Reads all Media Types
|
||||
0x001E, // Reads CD Structures
|
||||
};
|
||||
|
||||
void OpticalGetConfigurationCommandHandler()
|
||||
{
|
||||
uint16_t sfn = (m_cmd[2] << 8) | m_cmd[3];
|
||||
uint16_t allocationLength = (m_cmd[7] << 8) | m_cmd[8];
|
||||
uint16_t sfnmax = (allocationLength - 8) / 4;
|
||||
uint16_t sfi = 0;
|
||||
uint8_t len;
|
||||
|
||||
memset(m_responsebuffer, 0, sizeof(m_responsebuffer));
|
||||
|
||||
switch(m_cmd[1] & 0x3) {
|
||||
case 0: {
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
sfnmax = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
len = 8;
|
||||
for(sfi = 0; (sfi < sizeof(SupportedFeatures)) && sfnmax; sfi++) {
|
||||
if( SupportedFeatures[sfi] > sfn ) {
|
||||
m_responsebuffer[len++] = (SupportedFeatures[sfi] >> 8) & 0xff;
|
||||
m_responsebuffer[len++] = SupportedFeatures[sfi] & 0xff;
|
||||
m_responsebuffer[len++] = 0;
|
||||
m_responsebuffer[len++] = 0;
|
||||
sfnmax--;
|
||||
}
|
||||
}
|
||||
|
||||
m_responsebuffer[0] = (len >> 24) & 0xff;
|
||||
m_responsebuffer[1] = (len >> 16) & 0xff;
|
||||
m_responsebuffer[2] = (len >> 8) & 0xff;
|
||||
m_responsebuffer[3] = (len) & 0xff;
|
||||
|
||||
m_responsebuffer[6] = 0x00; // CD-ROM Profile
|
||||
m_responsebuffer[7] = 0x08;
|
||||
|
||||
// Truncate if necessary
|
||||
if(allocationLength < len)
|
||||
len = allocationLength;
|
||||
|
||||
// Send it
|
||||
writeDataPhase(len, m_responsebuffer);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
|
||||
void OpticalEventStatusCommandHandler()
|
||||
{
|
||||
uint8_t len = 0;
|
||||
memset(m_responsebuffer, 0, sizeof(m_responsebuffer));
|
||||
|
||||
LOGN("[Read Event Status]");
|
||||
|
||||
if((m_cmd[1] & 1) == 0) {
|
||||
m_sts |= STATUS_CHECK;
|
||||
m_sense[m_id][m_lun].m_key = ILLEGAL_REQUEST; // Illegal Request
|
||||
m_sense[m_id][m_lun].m_code = INVALID_FIELD_IN_CDB; // Invalid field in CDB
|
||||
m_sense[m_id][m_lun].m_key_specific[0] = ERROR_IN_OPCODE; // Error in Byte 1
|
||||
m_sense[m_id][m_lun].m_key_specific[1] = 0x00;
|
||||
m_sense[m_id][m_lun].m_key_specific[2] = 0x01;
|
||||
m_phase = PHASE_STATUSIN;
|
||||
return;
|
||||
}
|
||||
|
||||
int ncr;
|
||||
for(ncr = 0; ncr < 8; ncr++) {
|
||||
if(m_cmd[4] & (1<<ncr)) {
|
||||
switch (ncr) {
|
||||
case 1:
|
||||
m_responsebuffer[len++] = 0x00; // MSB Descriptor Length
|
||||
m_responsebuffer[len++] = 0x06; // LSB
|
||||
m_responsebuffer[len++] = 0x02; // Operational Change Event
|
||||
m_responsebuffer[len++] = 0x12; // Supported Event Class
|
||||
m_responsebuffer[len++] = 0x00; // No Change
|
||||
m_responsebuffer[len++] = 0x00; // Operational Status
|
||||
m_responsebuffer[len++] = 0x00; // MSB Operational Change
|
||||
m_responsebuffer[len++] = 0x00; // LSB
|
||||
break;
|
||||
case 4:
|
||||
m_responsebuffer[len++] = 0x00; // MSB Descriptor Length
|
||||
m_responsebuffer[len++] = 0x06; // LSB
|
||||
m_responsebuffer[len++] = 0x04; // Media Change Event
|
||||
m_responsebuffer[len++] = 0x12; // Supported Event Class
|
||||
m_responsebuffer[len++] = 0x00; // No Change
|
||||
m_responsebuffer[len++] = (!m_img) ? 0x00 : 0x02; // Media Present
|
||||
m_responsebuffer[len++] = 0x00; // Start Slot
|
||||
m_responsebuffer[len++] = 0x00; // End Slot
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t allocationLength = (m_cmd[7] << 8) | m_cmd[8];
|
||||
|
||||
// Truncate if necessary
|
||||
if(allocationLength < len)
|
||||
len = allocationLength;
|
||||
|
||||
// Send it
|
||||
writeDataPhase(len, m_responsebuffer);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void OpticalLockTrayCommandHandler() {
|
||||
if(m_cmd[4] & 1) {
|
||||
LOGN("[Lock Tray]");
|
||||
} else {
|
||||
LOGN("[Unlock Tray]");
|
||||
}
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void OpticalReadCapacityCommandHandler() {
|
||||
LOGN("[ReadCapacity]");
|
||||
if(!m_img) {
|
||||
m_sts |= 0x02; // Image file absent
|
||||
m_phase = PHASE_STATUSIN;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t bl = m_img->m_blocksize;
|
||||
uint32_t bc = m_img->m_fileSize / bl;
|
||||
uint8_t buf[8] = {
|
||||
(uint8_t)(((uint32_t)(bc >> 24))&0xff), (uint8_t)(((uint32_t)(bc >> 16))&0xff), (uint8_t)(((uint32_t)(bc >> 8))&0xff), (uint8_t)(((uint32_t)(bc))&0xff),
|
||||
(uint8_t)(((uint32_t)(bl >> 24))&0xff), (uint8_t)(((uint32_t)(bl >> 16))&0xff), (uint8_t)(((uint32_t)(bl >> 8))&0xff), (uint8_t)(((uint32_t)(bl))&0xff)
|
||||
};
|
||||
writeDataPhase(8, buf);
|
||||
m_phase = PHASE_STATUSIN;
|
||||
}
|
||||
|
||||
void ConfigureOpticalHandlers(int id) {
|
||||
for(int c = 0; c < 256; c++)
|
||||
m_handler[id][c] = &UnknownCommandHandler;
|
||||
|
||||
m_handler[id][CMD_TEST_UNIT_READY] = &TestUnitCommandHandler;
|
||||
m_handler[id][CMD_REZERO_UNIT] = &RezeroUnitCommandHandler;
|
||||
m_handler[id][CMD_REQUEST_SENSE] = &RequestSenseCommandHandler;
|
||||
m_handler[id][CMD_READ6] = &Read6CommandHandler;
|
||||
m_handler[id][CMD_SEEK6] = &Seek6CommandHandler;
|
||||
m_handler[id][CMD_INQUIRY] = &InquiryCommandHandler;
|
||||
m_handler[id][CMD_MODE_SELECT6] = &ModeSelect6CommandHandler;
|
||||
m_handler[id][CMD_MODE_SENSE6] = &OpticalModeSense6CommandHandler;
|
||||
m_handler[id][CMD_START_STOP_UNIT] = &StartStopUnitCommandHandler;
|
||||
m_handler[id][CMD_PREVENT_REMOVAL] = &OpticalLockTrayCommandHandler;
|
||||
m_handler[id][CMD_READ_CAPACITY10] = &OpticalReadCapacityCommandHandler;
|
||||
m_handler[id][CMD_READ10] = &Read10CommandHandler;
|
||||
m_handler[id][CMD_SEEK10] = &Seek10CommandHandler;
|
||||
m_handler[id][CMD_READ_TOC] = &OpticalReadTOCCommandHandler;
|
||||
m_handler[id][CMD_READ_HEADER] = &OpticalHeaderCommandHandler;
|
||||
m_handler[id][CMD_GET_CONFIGURATION] = &OpticalGetConfigurationCommandHandler;
|
||||
m_handler[id][CMD_GET_EVENT_STATUS_NOTIFICATION] = &OpticalEventStatusCommandHandler;
|
||||
m_handler[id][CMD_READ_DISC_INFORMATION] = &OpticalReadDiscInfoCommandHandler;
|
||||
m_handler[id][CMD_MODE_SELECT10] = &ModeSelect10CommandHandler;
|
||||
m_handler[id][CMD_MODE_SENSE10] = &ModeSense10CommandHandler;
|
||||
}
|
151
src/scsi_defs.h
Executable file
151
src/scsi_defs.h
Executable file
@ -0,0 +1,151 @@
|
||||
|
||||
/* Mode pages */
|
||||
#define MODEPAGE_VENDOR_SPECIFIC 0x00
|
||||
#define MODEPAGE_RW_ERROR_RECOVERY 0x01
|
||||
#define MODEPAGE_DCRC_PARAMETERS 0x02
|
||||
#define MODEPAGE_FORMAT_PARAMETERS 0x03
|
||||
#define MODEPAGE_RIGID_GEOMETRY 0x04
|
||||
#define MODEPAGE_APPLE 0x30
|
||||
#define MODEPAGE_ALL_PAGES 0x3F
|
||||
|
||||
/* 6 Byte command opcodes */
|
||||
#define CMD_TEST_UNIT_READY 0x00
|
||||
#define CMD_REZERO_UNIT 0x01
|
||||
#define CMD_REQUEST_SENSE 0x03
|
||||
#define CMD_FORMAT_UNIT 0x04
|
||||
#define CMD_READ_BLOCK_LIMITS 0x05
|
||||
#define CMD_READ6 0x08
|
||||
#define CMD_WRITE6 0x0A /* Optional */
|
||||
#define CMD_SEEK6 0x0B /* Optional */
|
||||
|
||||
#define CMD_WRITE_FILEMARKS 0x10
|
||||
#define CMD_SPACE 0x11
|
||||
#define CMD_INQUIRY 0x12
|
||||
#define CMD_MODE_SELECT6 0x15 /* Optional */
|
||||
#define CMD_RESERVE6 0x16 /* Optional */
|
||||
#define CMD_RELEASE6 0x17 /* Optional */
|
||||
#define CMD_ERASE 0x19
|
||||
#define CMD_MODE_SENSE6 0x1A /* Optional */
|
||||
#define CMD_START_STOP_UNIT 0x1B /* Optional */
|
||||
#define CMD_RECV_DIAGNOSTIC 0x1C
|
||||
#define CMD_SEND_DIAGNOSTIC 0x1D
|
||||
#define CMD_PREVENT_REMOVAL 0x1E
|
||||
/* 10 Byte command opcodes */
|
||||
#define CMD_READ_CAPACITY10 0x25
|
||||
#define CMD_READ10 0x28
|
||||
#define CMD_WRITE10 0x2A /* Optional */
|
||||
#define CMD_SEEK10 0x2B /* Optional */
|
||||
#define CMD_READUPDATEDBLOCK10 0x2D
|
||||
#define CMD_WRITEANDVERIFY10 0x2E /* Optional */
|
||||
#define CMD_VERIFY10 0x2F
|
||||
#define CMD_PREFETCH_CACHE10 0x34 /* Optional */
|
||||
#define CMD_SYNCHRONIZE_CACHE10 0x35 /* Optional */
|
||||
#define CMD_LOCKUNLOCK_CACHE10 0x36 /* Optional */
|
||||
#define CMD_READ_DEFECT_DATA 0x37 /* Optional */
|
||||
#define CMD_WRITEBUFFER 0x3B /* Optional */
|
||||
#define CMD_READBUFFER 0x3C /* Optional */
|
||||
#define CMD_READLONG10 0x3E /* Optional */
|
||||
#define CMD_WRITELONG10 0x3F /* Optional */
|
||||
#define CMD_READ_TOC 0x43
|
||||
#define CMD_READ_HEADER 0x44
|
||||
#define CMD_GET_CONFIGURATION 0x46
|
||||
#define CMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
|
||||
#define CMD_READ_DISC_INFORMATION 0x51
|
||||
#define CMD_MODE_SELECT10 0x55
|
||||
#define CMD_RESERVE10 0x56
|
||||
#define CMD_RELEASE10 0x57
|
||||
#define CMD_MODE_SENSE10 0x5A /* Optional */
|
||||
/* 12 Byte command opcodes */
|
||||
#define CMD_REPORT_LUNS 0xA0 /* Optional */
|
||||
#define CMD_MAC_UNKNOWN 0xEE /* Unknown */
|
||||
|
||||
/* Dayna SCSI/Link Ethernet */
|
||||
#define CMD_SCSILINK_STATS 0x09
|
||||
#define CMD_SCSILINK_ENABLE 0x0E
|
||||
#define CMD_SCSILINK_SET 0x0C
|
||||
#define CMD_SCSILINK_SETMODE 0x80
|
||||
#define CMD_SCSILINK_SETMAC 0x40
|
||||
|
||||
/* Cabletron Ethernet */
|
||||
#define CMD_CABLETRON_SEND 0x0c01
|
||||
#define CMD_CABLETRON_RECV 0xe1
|
||||
#define CMD_CABLETRON_GET_ADDR 0x0c04
|
||||
#define CMD_CABLETRON_ADD_PROTO 0x0d01
|
||||
#define CMD_CABLETRON_REM_PROTO 0x0d02
|
||||
#define CMD_CABLETRON_SET_MODE 0x0d03
|
||||
#define CMD_CABLETRON_SET_MULTI 0x0d04
|
||||
#define CMD_CABLETRON_REMOVE_MULTI 0x0d05
|
||||
#define CMD_CABLETRON_GET_STATS 0x0d06
|
||||
#define CMD_CABLETRON_SET_MEDIA 0x0d07
|
||||
#define CMD_CABLETRON_GET_MEDIA 0x0d08
|
||||
#define CMD_CABLETRON_LOAD_IMAGE 0x0d09
|
||||
#define CMD_CABLETRON_SET_ADDR 0x0d0a
|
||||
|
||||
|
||||
/*
|
||||
* SCSI MESSAGE CODES
|
||||
*/
|
||||
|
||||
#define COMMAND_COMPLETE 0x00
|
||||
#define EXTENDED_MESSAGE 0x01
|
||||
#define EXTENDED_MODIFY_DATA_POINTER 0x00
|
||||
#define EXTENDED_SDTR 0x01
|
||||
#define EXTENDED_EXTENDED_IDENTIFY 0x02 /* SCSI-I only */
|
||||
#define EXTENDED_WDTR 0x03
|
||||
#define EXTENDED_PPR 0x04
|
||||
#define EXTENDED_MODIFY_BIDI_DATA_PTR 0x05
|
||||
#define SAVE_POINTERS 0x02
|
||||
#define RESTORE_POINTERS 0x03
|
||||
#define DISCONNECT 0x04
|
||||
#define INITIATOR_ERROR 0x05
|
||||
#define ABORT_TASK_SET 0x06
|
||||
#define MESSAGE_REJECT 0x07
|
||||
#define NOP 0x08
|
||||
#define MSG_PARITY_ERROR 0x09
|
||||
#define LINKED_CMD_COMPLETE 0x0a
|
||||
#define LINKED_FLG_CMD_COMPLETE 0x0b
|
||||
#define TARGET_RESET 0x0c
|
||||
#define ABORT_TASK 0x0d
|
||||
#define CLEAR_TASK_SET 0x0e
|
||||
#define INITIATE_RECOVERY 0x0f /* SCSI-II only */
|
||||
#define RELEASE_RECOVERY 0x10 /* SCSI-II only */
|
||||
#define CLEAR_ACA 0x16
|
||||
#define LOGICAL_UNIT_RESET 0x17
|
||||
#define SIMPLE_QUEUE_TAG 0x20
|
||||
#define HEAD_OF_QUEUE_TAG 0x21
|
||||
#define ORDERED_QUEUE_TAG 0x22
|
||||
#define IGNORE_WIDE_RESIDUE 0x23
|
||||
#define ACA 0x24
|
||||
#define QAS_REQUEST 0x55
|
||||
#define IDENTIFY 0x80
|
||||
|
||||
|
||||
/* Task states */
|
||||
#define ENDED 0x00
|
||||
#define CURRENT 0x01
|
||||
|
||||
/* Status */
|
||||
#define STATUS_GOOD 0x00
|
||||
#define STATUS_CHECK 0x02
|
||||
#define STATUS_BUSY 0x08
|
||||
#define STATUS_INTERMEDIATE 0x10
|
||||
#define STATUS_CONFLICT 0x18
|
||||
|
||||
/* Sense keys */
|
||||
#define NO_SENSE 0x00
|
||||
#define RECOVERED_ERROR 0x01
|
||||
#define NOT_READY 0x02
|
||||
#define MEDIUM_ERROR 0x03
|
||||
#define HARDWARE_ERROR 0x04
|
||||
#define ILLEGAL_REQUEST 0x05
|
||||
#define UNIT_ATTENTION 0x06
|
||||
#define DATA_PROTECT 0x07
|
||||
|
||||
/* Additional Sense Information */
|
||||
#define NO_ADDITIONAL_SENSE_INFORMATION 0x00
|
||||
#define INVALID_LBA 0x21
|
||||
#define INVALID_FIELD_IN_CDB 0x24
|
||||
#define NOTREADY_TO_READY_CHANGE 0x28
|
||||
#define UNIT_POWERON_RESET 0x29
|
||||
#define NO_MEDIA 0x3A
|
||||
#define ERROR_IN_OPCODE 0xC0
|
Loading…
x
Reference in New Issue
Block a user