📄 scsicmd.c
字号:
ScsiPrepareDiskInfo();
BulkSetDmaIn((UINT16)UsbDmaTotalLength);
BulkState = BULK_DMA_IN_COMPLETED;
}
else
{
BulkInStall();
BulkState = STALL_IN_COMPLETED;
}
}
//----------------------------------------------------------------------------
// ScsiCmdRquestSense
//----------------------------------------------------------------------------
void ScsiCmdRquestSense()
{
bit ClearSenseWord = true;
if (UsbDmaTotalLength > REQUEST_SENSE_DATA_LEN)
UsbDmaTotalLength = REQUEST_SENSE_DATA_LEN;
if ((ScsiLun > LastDevice) || (!(0x80 & BlockWrapper->Flags)))
{
//We put unsupport sense word on SenseKey,AddSenseCode,AddSenseCodeQ[MAX_DEVICE_NUM].
//It needn't to clear beause ScsiLun start from 0 to MAX_DEVICE_NUM - 1.
ScsiLun = MAX_DEVICE_NUM;
ClearSenseWord = false;
}
//Force to be Command Passed ????
CmdStatus = COMMAND_PASSED;
BulkFreeBuffer();
// Init Data of RequestSense.
SetBulkInFull();
memset((BYTE xdata *)(FIFO_ADDRESS_IN), 0, REQUEST_SENSE_DATA_LEN);
*(BYTE xdata *)(FIFO_ADDRESS_IN + 0) = 0x70;
*(BYTE xdata *)(FIFO_ADDRESS_IN + 7) = 0x0A;
*(BYTE xdata *)(FIFO_ADDRESS_IN + SENSE_KEY_INDEX) = (0xf & SenseKey);
*(BYTE xdata *)(FIFO_ADDRESS_IN + ADD_SENSE_CODE_INDEX) = AddSenseCode;
*(BYTE xdata *)(FIFO_ADDRESS_IN + ADD_SENSE_CODEQ_INDEX)= AddSenseCodeQ;
if (ClearSenseWord)
{
SenseKey = NO_SENSE;
AddSenseCode = 0x00;
AddSenseCodeQ = 0x00;
}
if (CmdStatus != PHASE_ERROR)
{
BulkSetDmaIn((UINT16)UsbDmaTotalLength);
BulkState = BULK_DMA_IN_COMPLETED;
}
else
{
BulkInStall();
BulkState = STALL_IN_COMPLETED;
}
}
//----------------------------------------------------------------------------
// ScsiCmdModeSense6
//----------------------------------------------------------------------------
void ScsiCmdModeSense6()
{
BYTE PageCode = (*(BYTE xdata *)(FIFO_ADDRESS_OUT + CBWCB_OFFSET + 2) & 0x3f);
if ( !(0x80 & BlockWrapper->Flags) )
ScsiInvalidFieldError(ScsiLun);
BulkFreeBuffer(); //Out端点接收使能
if (CmdStatus == COMMAND_PASSED)
{
SetBulkInFull();
ScsiPrepareModePage(PageCode, (UINT16)UsbDmaTotalLength);
BulkSetDmaIn((UINT16)UsbDmaTotalLength);
BulkState = BULK_DMA_IN_COMPLETED;
}
else
{
BulkInStall();
BulkState = STALL_IN_COMPLETED;
}
}
//----------------------------------------------------------------------------
// ScsiCmdModeSense10
//----------------------------------------------------------------------------
void ScsiCmdModeSense10()
{
BulkFreeBuffer();
SetBulkInFull();
// Always return the fixed data.
*(BYTE xdata *)(FIFO_ADDRESS_IN + 0) = 0x00;
*(BYTE xdata *)(FIFO_ADDRESS_IN + 1) = 0x06;
*(BYTE xdata *)(FIFO_ADDRESS_IN + 2) = 0x00;
if (ScsiWriteProtect[ScsiLun])
{
*(BYTE xdata *)(FIFO_ADDRESS_IN + 3) = 0x80;
}
else
{
*(BYTE xdata *)(FIFO_ADDRESS_IN + 3) = 0x00;
}
*(BYTE xdata *)(FIFO_ADDRESS_IN + 4) = 0x00;
*(BYTE xdata *)(FIFO_ADDRESS_IN + 5) = 0x00;
*(BYTE xdata *)(FIFO_ADDRESS_IN + 6) = 0x00;
*(BYTE xdata *)(FIFO_ADDRESS_IN + 7) = 0x00;
BulkSetDmaIn(8);
BulkState = BULK_DMA_IN_COMPLETED;
}
//----------------------------------------------------------------------------
// ScsiCmdReadBuf---2007.08.16
//----------------------------------------------------------------------------
void ScsiCmdReadBuf(void)
{
BulkFreeBuffer();
SetBulkInFull();
memset((BYTE xdata *)DMA_FIFOB0, 0, 8);
BulkSetDmaIn(8);
BulkState = BULK_DMA_IN_COMPLETED;
}
//----------------------------------------------------------------------------
// ScsiCmdStartStopUnit
//----------------------------------------------------------------------------
void ScsiCmdStartStopUnit()
{
if (ConvertEndian32(BlockWrapper->DataXsferLen) != 0)
ScsiInvalidFieldError(ScsiLun);
// Host request device to unload this LUN.
if (*(BYTE xdata *)(FIFO_ADDRESS_OUT + CBWCB_OFFSET + 4) == 0x02)
ScsiLoadStatus[ScsiLun] &= ~SCSI_LOAD_STATUS_MASK;
if (*(BYTE xdata *)(FIFO_ADDRESS_OUT + CBWCB_OFFSET + 0x04)) // detect start or stop device.
StorageStart(); // add by C.H. Liang
else
StorageEject(); // add by C.H. Liang
BulkFreeBuffer(); //
CmdStatus = 0x00;
BulkPrepareCSW(CmdStatus);
}
//----------------------------------------------------------------------------
// ScsiCmdPreventRemoval
//----------------------------------------------------------------------------
void ScsiCmdPreventRemoval()
{
if (ConvertEndian32(BlockWrapper->DataXsferLen) != 0)
ScsiInvalidFieldError(ScsiLun);
// We don't support link SCSI commands.
if (*(BYTE xdata *)(FIFO_ADDRESS_OUT + CBWCB_OFFSET + 5) & SCSI_CTRL_LINK_BIT)
{
SET_ILLEGAL_REQUEST(ScsiLun);
CmdStatus = COMMAND_FAILED;
}
BulkFreeBuffer(); //Out端点接收使能
if (CmdStatus == COMMAND_PASSED)
BulkPrepareCSW(CmdStatus);
else
{
BulkInStall();
BulkState = STALL_IN_COMPLETED;
}
}
//----------------------------------------------------------------------------
// ScsiCmdReadCapacity10
//----------------------------------------------------------------------------
void ScsiCmdReadCapacity10()
{
if (UsbDmaTotalLength > CAPACITY10_DATA_LEN)
UsbDmaTotalLength = CAPACITY10_DATA_LEN;
if (!(0x80 & BlockWrapper->Flags))
ScsiInvalidFieldError(ScsiLun);
BulkFreeBuffer(); //Out端点接收使能
if (CmdStatus == COMMAND_PASSED)
{
SetBulkInFull();
ScsiGetLunCapacity();
BulkSetDmaIn((UINT16)UsbDmaTotalLength);
BulkState = BULK_DMA_IN_COMPLETED;
}
else
{
BulkInStall(); //将IN STALL位置1
BulkState = STALL_IN_COMPLETED; //转到STALL_IN_COMPLETED状态处理
}
}
//----------------------------------------------------------------------------
// ScsiCmdRead10
//----------------------------------------------------------------------------
void ScsiCmdRead10()
{
STATUS Status;
SectorStart = *(UINT32 xdata *)(FIFO_ADDRESS_OUT + CBWCB_OFFSET + 2);
SectorCount = *(UINT16 xdata *)(FIFO_ADDRESS_OUT + CBWCB_OFFSET + 7);
if(!(BlockWrapper->Flags & 0x80))
{
SetSenseErrCmdField();
}
BulkFreeBuffer();//Out端点接收使能
if(CmdStatus == COMMAND_PASSED)
{
Status = ReadSector(); //derek
if(Status != STATUS_SUCCESS)
{
CmdStatus = COMMAND_FAILED;
SetSenseDataRd(Status);
}
}
if(CmdStatus == COMMAND_PASSED)
{
BulkState = BULK_DMA_IN_COMPLETED;
BulkSetDmaIn(BYTES_PER_SECTOR);
}
else
{
BulkInStall();
BulkState = STALL_IN_COMPLETED;
}
}
//----------------------------------------------------------------------------
// ScsiCmdWrite10
//----------------------------------------------------------------------------
void ScsiCmdWrite10()
{
SectorStart = *(UINT32 xdata *)(FIFO_ADDRESS_OUT + CBWCB_OFFSET + 2);
SectorCount = *(UINT16 xdata *)(FIFO_ADDRESS_OUT + CBWCB_OFFSET + 7);
if(0x80 & BlockWrapper->Flags)
{
SetSenseErrCmdField();
}
BulkFreeBuffer();//Out端点接收使能
if(CmdStatus == COMMAND_PASSED)
{
FirstWrite = true;
BulkState = BULK_DMA_OUT_COMPLETED;
}
if(CmdStatus != COMMAND_PASSED)
{
BulkInStall();
BulkState = STALL_IN_COMPLETED;
}
}
//----------------------------------------------------------------------------
// ScsiCmdVerify10
//----------------------------------------------------------------------------
void ScsiCmdVerify10()
{
if (ConvertEndian32(BlockWrapper->DataXsferLen) != 0)
ScsiInvalidFieldError(ScsiLun);
BulkFreeBuffer(); //Out端点接收使能
if (CmdStatus == COMMAND_PASSED)
BulkPrepareCSW(CmdStatus);
else
{
BulkInStall();
BulkState = STALL_IN_COMPLETED;
}
}
//----------------------------------------------------------------------------
// ScsiCmdModeSelect6
//----------------------------------------------------------------------------
void ScsiCmdModeSelect6()
{
if (0x80 & BlockWrapper->Flags)
{
ScsiInvalidFieldError(ScsiLun);
}
// We don't support this command.
CmdStatus = COMMAND_FAILED;
BulkFreeBuffer(); //Out端点接收使能
if (CmdStatus != PHASE_ERROR)
{
SET_ILLEGAL_REQUEST(ScsiLun);
// Wait Data Received Ready.
BulkWaitOutDataReady(); // Wait Data Received Ready.
BulkPrepareCSW(CmdStatus);
}
else
{
BulkInStall();
BulkState = STALL_IN_COMPLETED;
}
}
//----------------------------------------------------------------------------
// OpCode = 0x23.
//----------------------------------------------------------------------------
void ScsiCmdOpCode23H()
{
BulkFreeBuffer();
SetBulkInFull();
memset((BYTE xdata *)(FIFO_ADDRESS_IN), 0, 12);
// Emulate PenDrive behavior to run BIOS Boot.
*(BYTE xdata *)(FIFO_ADDRESS_IN + 3) = 0x08;
*(BYTE xdata *)(FIFO_ADDRESS_IN + 5) = 0x01;
*(BYTE xdata *)(FIFO_ADDRESS_IN + 6) = 0xF4;
*(BYTE xdata *)(FIFO_ADDRESS_IN + 8) = 0x02;
*(BYTE xdata *)(FIFO_ADDRESS_IN + 10) = 0x02;
BulkSetDmaIn(12);
BulkState = BULK_DMA_IN_COMPLETED;
}
/***************************************************************************
SCSI COMMAND END
***************************************************************************/
//----------------------------------------------------------------------------
// Do some initializations before a new SCSI command executed.
//----------------------------------------------------------------------------
void ScsiCmdNewStart()
{
// Update the memory address of BlockWrapper.
BlockWrapper = (CMD_BLOCK_WRAPPER xdata *)(FIFO_ADDRESS_OUT);
// UsbDmaTotalLength is used on other Scsicmd other than reading and writing.
UsbDmaTotalLength = ConvertEndian32(BlockWrapper->DataXsferLen);
SectorStart = 0; //reset SectorStart & SectorCount
SectorCount = 0;
CmdStatus = COMMAND_PASSED;
ScsiLun = BlockWrapper->CbwcbLun;
WrapperTag = BlockWrapper->Tag;
}
//----------------------------------------------------------------------------
// Init SCSI used parameters.
//----------------------------------------------------------------------------
void ScsiInit()
{
BYTE i;
SenseKey = NO_SENSE;
AddSenseCode = 0x00;
AddSenseCodeQ = 0x00;
for (i = 0; i < MAX_DEVICE_NUM ; i++)
{
ScsiWriteProtect[i] = false;
ScsiWriteProtectChange[i] = false;
}
}
//----------------------------------------------------------------------------
// Check SCSI Command
//----------------------------------------------------------------------------
void ScsiCheckCmd()
{
BYTE OpCode;
ScsiCmdNewStart();
OpCode = *(BYTE xdata *)(FIFO_ADDRESS_OUT + CBWCB_OFFSET);
//
ScsiLunValidCheck();
if(CmdStatus == PHASE_ERROR)
{
SetSenseDataRd(STATUS_NO_MEDIA);
BulkInStall();
BulkState = STALL_IN_COMPLETED;
return;
}
if(BlockWrapper->Sign != CBW_SIGNATURE)
{
SetSenseErrCmdField();
CmdStatus = PHASE_ERROR;
BulkInStall();
BulkState = STALL_IN_COMPLETED;
return;
}
switch (OpCode)
{
case TEST_UNIT_READY_OPCODE: ScsiCmdTestUnitReady(); return;
case REQUEST_SENSE_OPCODE : ScsiCmdRquestSense(); return;
case MODE_SELECT6_OPCODE : ScsiCmdModeSelect6(); return;
case MODE_SENSE6_OPCODE : ScsiCmdModeSense6(); return;
case INQUIRY_OPCODE : ScsiCmdInquiry(); return;
case START_STOP_UNIT_OPCODE: ScsiCmdStartStopUnit(); return;
case PREVENT_REMOVAL_OPCODE: ScsiCmdPreventRemoval();return;
case READ_CAPACITY10_OPCODE: ScsiCmdReadCapacity10();return;
case READ10_OPCODE : ScsiCmdRead10(); return;
case WRITE10_OPCODE : ScsiCmdWrite10(); return;
case VERIFY10_OPCODE : ScsiCmdVerify10(); return;
case _23_OPCODE : ScsiCmdOpCode23H(); return;
case MODE_SENSE10_OPCODE : ScsiCmdModeSense10(); return;
case READ_BUFFER : ScsiCmdReadBuf(); return; //2007.08.16
default:
CmdStatus = PHASE_ERROR;
SetSenseErrOpCode();
BulkInStall();
BulkState = STALL_IN_COMPLETED;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -