📄 scsi.c
字号:
/*************************************************************************
*
* Used with ICCARM and AARM.
*
* (c) Copyright IAR Systems 2005
*
* File name : scsi.c
* Description : USB Mass storage device bulk-only transport and
* SCSI SPC, SBC, MMC commands set
*
* History :
* 1. Date : September 8, 2005
* Author : Stanimir Bonev
* Description : Create
* 2. Date : January 27, 2006
* Author : Stanimir Bonev
* Description : Modify
* Add Unit Start/Stop command implement
*
* $Revision: 1.5 $
**************************************************************************/
#define SCSI_GOBALS
#include "scsi.h"
#pragma segment="USB_DMA_RAM"
#pragma data_alignment=4
const Int8U LunMax = SCSI_LUN_NUMB-1;
#pragma location="USB_DMA_RAM"
#pragma data_alignment=4
__no_init Cbw_t Cbw;
#pragma location="USB_DMA_RAM"
#pragma data_alignment=4
__no_init Csw_t Csw;
ScsiDrvObj ScsiDrv [SCSI_LUN_NUMB];
Int32U Lun = 0;
volatile BotState_t BotState;
volatile BotStatus_t BotStatus;
/*************************************************************************
* Function Name: ScsiInit
* Parameters: none
*
* Return: none
*
* Description: Init SCSI
*
*************************************************************************/
void ScsiInit (void)
{
UsbClassBotInit();
// SCSI Drive Objects init
for (Int32U i = 0; i < SCSI_LUN_NUMB; ++i)
{
ScsiDrv[i].Status = ScsiCommandNoKey;
ScsiDrv[i].UnitSSStatus = UnitStarted;
// Send init LUN message
ScsiDrv[i].Message[0] = LunInitMsg;
pScsiMessage[i] = ScsiDrv[i].Message;
}
}
/*************************************************************************
* Function Name: UsbClassBotInit
* Parameters: none
*
* Return: none
*
* Description: USB Bulk-only transport init
*
*************************************************************************/
void UsbClassBotInit (void)
{
UsbBotRstInterface();
// Registering Configure callback function
USB_UserFuncRegistering(UsbClassBotRequest,UsbUserClass);
// Registering Unstall callback function
USB_UserFuncRegistering(BotUnstallCallBack,UsbUserEpUnStall);
}
/*************************************************************************
* Function Name: UsbClassBotConfigure
* Parameters: void * pArg
*
* Return: void *
*
* Description: USB Class storage configure
*
*************************************************************************/
void * UsbClassBotConfigure (void * pArg)
{
if((Int32U)pArg == 0)
{
if(UsbCoreReq(UsbCoreReqConfiquration) != 0)
{
// Reset Interface
UsbBotRstInterface();
// disable all class EPs
USB_RealizeEp((USB_Endpoint_t)BulkInEp ,0,0,FALSE);
USB_UserFuncRegistering(NULL,BulkInEp);
USB_RealizeEp((USB_Endpoint_t)BulkOutEp,0,0,FALSE);
USB_UserFuncRegistering(NULL,BulkOutEp);
}
}
else
{
// Realize Class EPs
USB_UserFuncRegistering(BotInEP ,BulkInEp);
USB_RealizeEp((USB_Endpoint_t)BulkInEp ,0,BulkInEpMaxSize, FALSE);
USB_UserFuncRegistering(BotOutEP,BulkOutEp);
USB_RealizeEp((USB_Endpoint_t)BulkOutEp,0,BulkOutEpMaxSize,FALSE);
// Reset Interface
UsbBotRstInterface();
}
return(NULL);
}
/*************************************************************************
* Function Name: UsbBotRstInterface
* Parameters: none
*
* Return: none
*
* Description: USB Bulk-only transport interface reset
*
*************************************************************************/
void UsbBotRstInterface (void)
{
//BOT Init
BotState = BotWaitCbw;
Lun = 0;
// Clear all flags
BotStatus.Flags = 0;
// Init DMA transfer of CBW
USB_DmaInitTransfer((USB_Endpoint_t)BulkOutEp,
DMA_BOT_OUT_DES,
(pInt32U)&Cbw,
BulkOutEpMaxSize,
sizeof(Cbw_t),NULL,FALSE);
Csw.dCSWSignature = CswSignature;
}
/*************************************************************************
* Function Name: BotInEpStall
* Parameters: none
*
* Return: none
*
* Description: Stall BOT In EP
*
*************************************************************************/
void BotInEpStall (void)
{
USB_SetStallEP((USB_Endpoint_t)BulkInEp,TRUE);
}
/*************************************************************************
* Function Name: BotOutEpStall
* Parameters: none
*
* Return: none
*
* Description: Stall BOT Out EP
*
*************************************************************************/
void BotOutEpStall (void)
{
USB_SetStallEP((USB_Endpoint_t)BulkOutEp,TRUE);
}
/*************************************************************************
* Function Name: UsbClassBotRequest
* Parameters: void * pArg
*
* Return: void *
*
* Description: Implement USB Class storage requests
*
*************************************************************************/
static void * UsbClassBotRequest (void * pArg)
{
UsbEpCtrl_t * UsbEp = (UsbEpCtrl_t *) pArg;
UsbSetupPacket_t *pData = (UsbSetupPacket_t *)UsbEp->pData;
switch (pData->bRequest)
{
case UsbBotInterfaceGetMaxLun: // return number of LUN
if ((pData->wValue.Word == 0) &&
(pData->wLength.Word == 1))
{
UsbEp->pData = (Int8U *)&LunMax;
UsbEp->Counter = 1;
return((void*)UsbPass);
}
break;
case MassStorageClassReqReset: // reset BOT interface
if ((pData->wValue.Word == 0) &&
(pData->wLength.Word == 0))
{
UsbBotRstInterface();
UsbEp->Counter = 0;
return((void*)UsbPass);
}
break;
}
return((void *)UsbFault);
}
/*************************************************************************
* Function Name: BotOutEP
* Parameters: void * pArg
*
* Return: void *
*
* Description: USB BOT Out EP handler
*
*************************************************************************/
void * BotOutEP (void *Arg)
{
pUSB_DmaDesc_t pUSB_DmaDesc = USB_DmaGetDesc(DMA_BOT_OUT_DES);
if((Int32U)Arg == UsbDmaPacket)
{
switch (BotState)
{
case BotWaitCbw:
if (pUSB_DmaDesc->DdState == UsbDmaNormalCompletion)
{
BotStatus.Flags = 0;
ScsiCommImpl();
return(NULL);
}
break;
case BotEpDataOut:
if (pUSB_DmaDesc->DdState == UsbDmaNormalCompletion)
{
ScsiDrv[Lun].Message[0] = LunDataReadyMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
return(NULL);
}
// Phase error
BotStatus.PhaseError = TRUE;
break;
}
}
ScsiDrv[Lun].Message[0] = LunResetReqMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
BotOutEpStall();
BotInEpStall();
// Something is wrong
UsbBotRstInterface();
return(NULL);
}
/*************************************************************************
* Function Name: BotInEP
* Parameters: void * pArg
*
* Return: void *
*
* Description: USB BOT In EP handler
*
*************************************************************************/
void * BotInEP (void *Arg)
{
Int32U DmaStatus = USB_DmaGetDesc(DMA_BOT_IN_DES)->DdState;
if((Int32U)Arg == UsbDmaPacket)
{
switch (BotState)
{
case BotEpDataIn:
if (DmaStatus == UsbDmaNormalCompletion)
{
if(BotStatus.DataComplete)
{
if (Csw.dCSWDataResidue && !BotStatus.ShortPacket)
{
// The host expect more data
BotStatus.ShortPacket = FALSE;
USB_DmaInitTransfer((USB_Endpoint_t)BulkInEp,
DMA_BOT_IN_DES,
(pInt32U)4,
0,
0,
NULL,
FALSE);
}
else
{
BotSendStatus();
}
return(NULL);
}
ScsiDrv[Lun].Message[0] = LunDataReadyMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
return(NULL);
}
BotStatus.PhaseError =\
BotStatus.BotStatus = TRUE;
ScsiDrv[Lun].Message[0] = LunResetReqMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
BotInEpStall();
return(NULL);
case BotSendCsw:
UsbBotRstInterface();
return(NULL);
case BotWaitCbw:
return(NULL);
}
}
ScsiDrv[Lun].Message[0] = LunResetReqMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
BotOutEpStall();
BotInEpStall();
// Something is wrong
UsbBotRstInterface();
return(NULL);
}
/*************************************************************************
* Function Name: BotUnstallCallBack
* Parameters: void * pArg
*
* Return: void *
*
* Description: Unstall callback function
*
*************************************************************************/
static
void * BotUnstallCallBack (void * pArg)
{
if((Int32U) pArg == BulkOutEp)
{
if (!BotStatus.BotStatus)
{
UsbBotRstInterface();
}
}
else if ((Int32U) pArg == BulkInEp)
{
if (BotStatus.BotStatus)
{
// Send a status after unstall the IN EP
BotSendStatus();
}
else
{
UsbBotRstInterface();
}
}
return(NULL);
}
/*************************************************************************
* Function Name: BotReceiveDataInit
* Parameters: pInt8U pData, Int32U DataSize, Boolean DataComplete
*
* Return: BotToUserStatus_t
*
* Description: Init Receive
*
*************************************************************************/
BotToUserStatus_t BotReceiveDataInit (pInt8U pData, Int32U DataSize, Boolean DataComplete)
{
if (DataSize > Csw.dCSWDataResidue)
{
// When user tries to receive more data from that host expect
return(BotError);
}
else if (!DataComplete && (DataSize % BulkInEpMaxSize))
{
// when user tries to receive not alignment data to
// the EP max size and DataComplete flag isn't set
return(BotNotAlignment);
}
Int32U save = __get_interrupt_state();
__disable_interrupt();
// Set BOT EP state
BotState = BotEpDataOut;
// Update DataResidue
Csw.dCSWDataResidue -= DataSize;
// Init DMA Transfer form BOT OUT EP
USB_DmaInitTransfer((USB_Endpoint_t)BulkOutEp,
DMA_BOT_OUT_DES,
(pInt32U)pData,
BulkOutEpMaxSize,
DataSize,
NULL,
FALSE);
__set_interrupt_state(save);
return BotPass;
}
/*************************************************************************
* Function Name: BotSendDataInit
* Parameters: const pInt8U pData, Int32U DataSize, Boolean DataComplete
*
* Return: BotToUserStatus_t
*
* Description: Init Transmit
*
*************************************************************************/
BotToUserStatus_t BotSendDataInit (const pInt8U pData, Int32U DataSize, Boolean DataComplete)
{
if (DataSize > Csw.dCSWDataResidue)
{
// When user tries to send more data from that host expect
BotStatus.PhaseError = TRUE;
DataSize = 0;
return BotError;
}
else if (DataSize % BulkInEpMaxSize)
{
BotStatus.ShortPacket = TRUE;
if(!DataComplete)
{
// Data size Alignment error
return BotNotAlignment;
}
}
Int32U save = __get_interrupt_state();
__disable_interrupt();
// Set BOT EP state
BotState = BotEpDataIn;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -