📄 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. Data : September 8, 2005
* Author : Stanimir Bonev
* Description : Create
* 2. Data : January 27, 2006
* Author : Stanimir Bonev
* Description : Modify
* Add Unit Start/Stop command implement
*
* $Revision: 1.3.2.1 $
**************************************************************************/
#define SCSI_GOBALS
#include "scsi.h"
#pragma segment="DMA_RAM"
#pragma data_alignment=4
const Int8U LunMax = SCSI_LUN_NUMB-1;
#pragma location="DMA_RAM"
#pragma data_alignment=4
__no_init Cbw_t Cbw;
#pragma location="DMA_RAM"
#pragma data_alignment=4
__no_init Csw_t Csw;
ScsiDrvObj ScsiDrv [SCSI_LUN_NUMB];
Int32U Lun = 0;
BotState_t BotState;
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();
UsbCoreUserFuncRegistered(UsbClassBotRequest,UsbUserClass);
}
/*************************************************************************
* 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_RealizeEndPoint((USB_Endpoint_t)BulkInEp ,1,0,FALSE);
USB_RealizeEndPoint((USB_Endpoint_t)BulkOutEp,0,0,FALSE);
USB_UserFuncRegistered(NULL,BulkInEp);
USB_UserFuncRegistered(NULL,BulkOutEp);
}
}
else
{
// Realize Class EPs
USB_RealizeEndPoint((USB_Endpoint_t)BulkInEp ,1,BulkInEpMaxSize, FALSE);
USB_RealizeEndPoint((USB_Endpoint_t)BulkOutEp,0,BulkOutEpMaxSize,FALSE);
USB_UserFuncRegistered(BotInEP ,BulkInEp);
USB_UserFuncRegistered(BotOutEP,BulkOutEp);
// 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:
if ((pData->wValue.Word == 0) &&
(pData->wLength.Word == 1))
{
UsbEp->pData = (Int8U *)&LunMax;
UsbEp->Counter = 1;
UsbEp0SetupWrite();
}
else
{
UsbEp->EpStatus.Status = UsbEpStall;
}
break;
case MassStorageClassReqReset:
if ((pData->wValue.Word == 0) &&
(pData->wLength.Word == 0))
{
UsbBotRstInterface();
USB_EpWrite(CTRL_ENP_IN,NULL,0);
UsbEp->EpStatus.Status = UsbEpStatusIn;
}
else
{
UsbEp->EpStatus.Status = UsbEpStall;
}
break;
default:
UsbEp->EpStatus.Status = UsbEpStall;
}
return NULL;
}
/*************************************************************************
* Function Name: BotOutEP
* Parameters: void * pArg
*
* Return: void *
*
* Description: USB BOT Out EP hadler
*
*************************************************************************/
void * BotOutEP (void *Arg)
{
pUSB_DmaDesc_t pUSB_DmaDesc = USB_DmaGetDesc(DMA_BOT_OUT_DES);
switch((Int32U)Arg)
{
case UsbEpUnstall:
if (BotStatus.BotStatus)
{
return(NULL);
}
UsbBotRstInterface();
return(NULL);
case UsbEpStall:
return(NULL);
case UsbDmaPacket:
break;
default:
// Error
BotState = BotFatalError;
break;
}
switch (BotState)
{
case BotWaitCbw:
if (pUSB_DmaDesc->DdState == UsbDmaNormalCompletion)
{
BotStatus.Flags = 0;
ScsiCommImpl();
break;
}
// Error
BotOutEpStall();
UsbBotRstInterface();
break;
case BotEpDataOut:
if (pUSB_DmaDesc->DdState == UsbDmaNormalCompletion)
{
ScsiDrv[Lun].Message[0] = LunDataReadyMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
break;
}
// Phase error
BotStatus.PhaseError = TRUE;
ScsiDrv[Lun].Message[0] = LunResetReqMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
BotOutEpStall();
BotSendStatus();
break;
// Fatal error
default:
ScsiDrv[Lun].Message[0] = LunResetReqMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
BotOutEpStall();
BotInEpStall();
// Somting is wrong
UsbBotRstInterface();
break;
}
return NULL;
}
/*************************************************************************
* Function Name: BotInEP
* Parameters: void * pArg
*
* Return: void *
*
* Description: USB BOT In EP hadler
*
*************************************************************************/
void * BotInEP (void *Arg)
{
Int32U DmaStatus = USB_DmaGetDesc(DMA_BOT_IN_DES)->DdState;
switch((Int32U)Arg)
{
case UsbEpUnstall:
if (BotStatus.BotStatus)
{
BotSendStatus();
return(NULL);
}
UsbBotRstInterface();
return(NULL);
case UsbEpStall:
return(NULL);
case UsbDmaPacket:
break;
default:
// Error
BotState = BotFatalError;
break;
}
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();
break;
case BotSendCsw:
UsbBotRstInterface();
break;
default:
ScsiDrv[Lun].Message[0] = LunResetReqMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
BotOutEpStall();
BotInEpStall();
// Somting is wrong
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)
{
// Error
return BotError;
}
else if (!DataComplete && (DataSize % BulkInEpMaxSize))
{
// Data size Alignment error
return BotNotAlignment;
}
Int32U cpu_sr = disable_interrupts();
// 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);
restore_interrupts(cpu_sr);
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)
{
// Error
BotStatus.PhaseError = TRUE;
DataSize = 0;
return BotError;
}
else if (DataSize % BulkInEpMaxSize)
{
BotStatus.ShortPacket = TRUE;
if(!DataComplete)
{
// Data size Alignment error
return BotNotAlignment;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -