📄 scsi.c
字号:
BotStatus.DataComplete = DataComplete;
// Update DataResidue
Csw.dCSWDataResidue -= DataSize;
// Init DMA Transfer form BOT OUT EP
USB_DmaInitTransfer((USB_Endpoint_t)BulkInEp,
DMA_BOT_IN_DES,
(pInt32U)pData,
BulkInEpMaxSize,
DataSize,
NULL,
FALSE);
__set_interrupt_state(save);
return BotPass;
}
/*************************************************************************
* Function Name: BotSendStatus
* Parameters: Int32U DataSize, Int8U * pData, Boolean DataComplete
*
* Return: BotToUserStatus_t
*
* Description: Init Transmit of the CSW
*
*************************************************************************/
void BotSendStatus (void)
{
Int32U save = __get_interrupt_state();
__disable_interrupt();
BotState = BotSendCsw;
if(BotStatus.PhaseError)
{
Csw.bCSWStatus = CswPhaseError;
}
else if (BotStatus.CmdFault)
{
Csw.bCSWStatus = CswFailed;
}
else
{
Csw.bCSWStatus = CswPassed;
}
BotStatus.BotStatus = TRUE;
USB_DmaInitTransfer((USB_Endpoint_t)BulkInEp,
DMA_BOT_IN_DES,
(pInt32U)&Csw,
BulkInEpMaxSize,
sizeof(Csw_t),
NULL,
FALSE);
__set_interrupt_state(save);
}
/*************************************************************************
* Function Name: ScsiCommImpl
* Parameters: none
*
* Return: none
*
* Description: Scsi commands implement
*
*************************************************************************/
inline
void ScsiCommImpl (void)
{
if(ScsiCbwValid())
{
Csw.dCSWDataResidue = Cbw.dCBWDataTransferLength;
Csw.dCSWTag = Cbw.dCBWTag;
Lun = Cbw.bCBWLUN;
switch (Cbw.CBWCB[0])
{
case ScsiTestUnitReady:
ScsiTestUnitReadyImp();
return;
case ScsiRequestSense:
ScsiRequestSenseImp();
return;
case ScsiInquiry:
ScsiInquiryImp();
return;
case ScsiModeSelect6:
ScsiModeSelect6Imp();
return;
case ScsiModeSense6:
ScsiModeSense6Imp();
return;
case ScsiMediaStartStop:
ScsiMediaStartStopImp();
return;
case ScsiMediaRemoval:
ScsiMediaRemovalImp();
return;
case ScsiReadFormatCapcity:
ScsiReadFormatCapcityImp();
return;
case ScsiReadCapacity10:
ScsiReadCapacity10Imp();
return;
case ScsiRead10:
ScsiRead10Imp();
return;
case ScsiWrite10:
ScsiWrite10Imp();
return;
case ScsiFerify10:
ScsiVerify10Imp();
return;
default:
ScsiCmdError(ScsiUnknowCommand,
(Cbw.bmCBWFlags.Dir == BotDataFormDevToHost)?ScsiStallIn:ScsiStallOut);
}
return;
}
// CBW Not valid or not meaningful
BotInEpStall();
BotOutEpStall();
}
/*************************************************************************
* Function Name: ScsiCbwValid
* Parameters: none
*
* Return: Boolean
*
* Description: CBW valid and meaningful check
*
*************************************************************************/
inline
Boolean ScsiCbwValid(void)
{
ScsiCmdField_t ScsiCmdField;
if ((Cbw.dCBWSignature != CbwSignature) ||
(Cbw.bCBWLUN >= SCSI_LUN_NUMB) ||
BotStatus.BotStatus)
{
return(FALSE);
}
ScsiCmdField.Cmd = Cbw.CBWCB[0];
switch (ScsiCmdField.GroupCode)
{
case 0:
if(Cbw.bCBWCBLength >= 6)
return(TRUE);
break;
case 1:
case 2:
if(Cbw.bCBWCBLength >= 10)
return(TRUE);
break;
case 3:
return(TRUE);
case 4:
if(Cbw.bCBWCBLength >= 16)
return(TRUE);
break;
case 5:
if(Cbw.bCBWCBLength >= 12)
return(TRUE);
}
return(FALSE);
}
/*************************************************************************
* Function Name: ScsiTestUnitReadyImp
* Parameters: none
*
* Return: none
*
* Description: TEST UNIT READY command implement
*
*************************************************************************/
inline
void ScsiTestUnitReadyImp (void)
{
if(Cbw.dCBWDataTransferLength == 0)
{
ScsiDrv[Lun].Message[0] = LunTestUntilReadyReqMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
}
else
{
ScsiCmdError(ScsiFatalError,0);
}
}
/*************************************************************************
* Function Name: ScsiTestUntilReadyData
* Parameters: Int32U MediaReady
*
* Return: void
*
* Description: Prepare Test until ready data for sending
*
*************************************************************************/
void ScsiTestUntilReadyData (Int32U MediaReady)
{
if(ScsiDrv[Lun].UnitSSStatus == UnitEjected)
{
if(MediaReady != ScsiMediaChanged)
{
ScsiCmdStatus(ScsiMediaNotPresent);
BotSendStatus();
return;
}
ScsiDrv[Lun].UnitSSStatus = UnitStarted;
}
ScsiCmdStatus((ScsiStatusCode_t)MediaReady);
BotSendStatus();
}
/*************************************************************************
* Function Name: ScsiRequestSenseImp
* Parameters: none
*
* Return: Boolean
*
* Description: REQUEST SENSE command implement
*
*************************************************************************/
inline
void ScsiRequestSenseImp (void)
{
pSpc3RequestSense_t pRequestSense = (pSpc3RequestSense_t)Cbw.CBWCB;
pSpc3RequestSenseResponse_t pRequestSenseResponse;
if ((Cbw.bmCBWFlags.Dir == BotDataFormDevToHost) &&
(Cbw.dCBWDataTransferLength >= pRequestSense->AllocationLenght))
{
pRequestSenseResponse = (pSpc3RequestSenseResponse_t)&Cbw;
// clear buffer
memset(&Cbw,0,sizeof(Spc3RequestSenseResponse_t));
if ((pRequestSense->Control.Control == 0) && !pRequestSense->DESC)
{
pRequestSenseResponse->ResponceCode = 0x70;
pRequestSenseResponse->Valid = TRUE;
switch (ScsiDrv[Lun].Status)
{
case ScsiMediamNotReady:
pRequestSenseResponse->Ascq = LogicalUnitNotReadyCauseNotReportable >> 8;
pRequestSenseResponse->Asc = LogicalUnitNotReadyCauseNotReportable;
pRequestSenseResponse->SenseKey = NotReady;
break;
case ScsiInvalidCbd:
pRequestSenseResponse->Ascq = InvalidFieldInCdb >> 8;
pRequestSenseResponse->Asc = InvalidFieldInCdb;
pRequestSenseResponse->SenseKey = IllegalRequest;
break;
case ScsiUnknowCommand:
pRequestSenseResponse->Ascq = InvalidCommandOperationCode >> 8;
pRequestSenseResponse->Asc = InvalidCommandOperationCode;
pRequestSenseResponse->SenseKey = IllegalRequest;
break;
case ScsiMediaNotPresent:
pRequestSenseResponse->Ascq = MediumNotPresent >> 8;
pRequestSenseResponse->Asc = MediumNotPresent;
pRequestSenseResponse->SenseKey = NotReady;
break;
case ScsiMiscompare:
pRequestSenseResponse->Ascq = MiscompareDuringVerifyOperation >> 8;
pRequestSenseResponse->Asc = MiscompareDuringVerifyOperation;
pRequestSenseResponse->SenseKey = Miscompare;
break;
case ScsiMediaChanged:
pRequestSenseResponse->Ascq = NotReadyToReadyChangeMediumMayHaveChanged >> 8;
pRequestSenseResponse->Asc = NotReadyToReadyChangeMediumMayHaveChanged;
pRequestSenseResponse->SenseKey = UnitAttention;
break;
default:
pRequestSenseResponse->Ascq = NoAdditionalSenseInformation >> 8;
pRequestSenseResponse->Asc = NoAdditionalSenseInformation;
pRequestSenseResponse->SenseKey = NoSense;
break;
}
pRequestSenseResponse->AddSenseKeyLength = sizeof(Spc3RequestSenseResponse_t) - 8;
// Clear condition code info
ScsiDrv[Lun].Status = ScsiCommandNoKey;
// Send Status after data packet
BotSendDataInit((Int8U *)pRequestSenseResponse,
MIN(pRequestSense->AllocationLenght,sizeof(Spc3RequestSenseResponse_t)),
TRUE);
return;
}
else
{
ScsiCmdStatus(ScsiInvalidCbd);
}
}
else
{
ScsiCmdStatus(ScsiFatalError);
}
BotStatus.BotStatus = TRUE;
BotInEpStall();
}
/*************************************************************************
* Function Name: ScsiModeSelect6Imp
* Parameters: none
*
* Return: none
*
* Description: MODE SELECT command implement
*
*************************************************************************/
inline
void ScsiModeSelect6Imp (void)
{
pSpc3ModeSelect6_t pModeSelect = (pSpc3ModeSelect6_t)Cbw.CBWCB;
if ((Cbw.bmCBWFlags.Dir == BotDataFormHostToDev) &&
(Cbw.dCBWDataTransferLength >= pModeSelect->ParameterListLenght))
{
ScsiCmdStatus(ScsiInvalidCbd);
}
else
{
ScsiCmdStatus(ScsiFatalError);
BotInEpStall();
}
BotOutEpStall();
BotSendStatus();
}
/*************************************************************************
* Function Name: ScsiModeSense6Imp
* Parameters: none
*
* Return: none
*
* Description: MODE SENSE command implement
*
*************************************************************************/
inline
void ScsiModeSense6Imp (void)
{
pSpc3ModeSense6_t pModeSense = (pSpc3ModeSense6_t)Cbw.CBWCB;
if ((Cbw.bmCBWFlags.Dir == BotDataFormDevToHost) &&
(Cbw.dCBWDataTransferLength >= pModeSense->AllocationLenght))
{
if ((pModeSense->PageCode == 0x3F) && (pModeSense->PC == 0) &&
(pModeSense->SubPageCode == 0x00))
{
// Clear condition code info
ScsiDrv[Lun].Status = ScsiCommandNoKey;
ScsiDrv[Lun].Message[0] = LunModeSense6ReqMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
return;
}
else
{
ScsiCmdStatus(ScsiInvalidCbd);
}
}
else
{
ScsiCmdStatus(ScsiFatalError);
}
BotStatus.BotStatus = TRUE;
BotInEpStall();
}
/*************************************************************************
* Function Name: ScsiModeSenseData
* Parameters: Int32U WriteProtect
*
* Return: none
*
* Description: Prepare MODE SENSE data for sending
*
*************************************************************************/
void ScsiModeSenseData (Int32U WriteProtect)
{
pSpc3ModeSense6Response_t pModeSense = (pSpc3ModeSense6Response_t)&Cbw;
// clear buffer
memset(pModeSense,0,sizeof(Spc3ModeSense6Response_t));
pModeSense->ModeDataLength = sizeof(Spc3ModeSense6Response_t)-1;
pModeSense->WP = WriteProtect;
BotSendDataInit((Int8U *)pModeSense,
MIN(Csw.dCSWDataResidue,sizeof(Spc3ModeSense6Response_t)),
TRUE);
}
/*************************************************************************
* Function Name: ScsiInquiryImp
* Parameters: none
*
* Return: none
*
* Description: INQUIRY command implement
*
*************************************************************************/
inline
void ScsiInquiryImp (void)
{
pSpc3Inquiry_t pInquiry = (pSpc3Inquiry_t)Cbw.CBWCB;
Int32U AllocationLenght =
((Int32U)pInquiry->AllocationLenght[0]<<8) + pInquiry->AllocationLenght[1];
if ((Cbw.bmCBWFlags.Dir == BotDataFormDevToHost) &&
(Cbw.dCBWDataTransferLength >= AllocationLenght))
{
if ((!pInquiry->EVPD) && (pInquiry->PageCode == 0))
{
ScsiDrv[Lun].Message[0] = LunInquiryReqMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
return;
}
else
{
ScsiCmdStatus(ScsiInvalidCbd);
}
}
else
{
ScsiCmdStatus(ScsiFatalError);
}
BotStatus.BotStatus = TRUE;
BotInEpStall();
}
/*************************************************************************
* Function Name: ScsiInquiryData
* Parameters: const pInt8U pData, Int32U Size
*
* Return: none
*
* Description: Prepare INQUIRY data for sending
*
*************************************************************************/
void ScsiInquiryData (const pInt8U pData, Int32U Size)
{
BotSendDataInit(pData,MIN(Csw.dCSWDataResidue,Size),TRUE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -