📄 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
* 3. Date : November 23, 2006
* Author : Stanimir Bonev
* Description : Modify
* Adapt for STR912
*
* $Revision: 16170 $
**************************************************************************/
#define SCSI_GOBALS
#include "scsi.h"
#pragma data_alignment=4
const Int8U LunMax = SCSI_LUN_NUMB-1;
#pragma data_alignment=4
__no_init Cbw_t Cbw;
#pragma data_alignment=4
__no_init Csw_t Csw;
ScsiDrvObj_t ScsiDrv [SCSI_LUN_NUMB];
Int32U Lun = 0;
BotState_t BotState;
BotStatus_t BotStatus;
Boolean RdyMessEna;
volatile ScsiEpStrl_t ScsiInEp, ScsiOutEp;
/*************************************************************************
* 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,EP_BULK_DOUB_BUF,EP_SLOT1);
USB_UserFuncRegistering(NULL,BulkInEp);
USB_RealizeEp((USB_Endpoint_t)BulkOutEp,0,EP_BULK_DOUB_BUF,EP_SLOT2);
USB_UserFuncRegistering(NULL,BulkOutEp);
}
}
else
{
// Realize Class EPs
USB_UserFuncRegistering(BotInEP ,BulkInEp);
USB_RealizeEp((USB_Endpoint_t)BulkInEp ,BulkInEpMaxSize,EP_BULK_DOUB_BUF,EP_SLOT1);
USB_UserFuncRegistering(BotOutEP,BulkOutEp);
USB_RealizeEp((USB_Endpoint_t)BulkOutEp,BulkOutEpMaxSize,EP_BULK_DOUB_BUF,EP_SLOT2);
// Reset Interface
UsbBotRstInterface();
}
return(NULL);
}
/*************************************************************************
* Function Name: UsbBotRstInterface
* Parameters: none
*
* Return: none
*
* Description: USB Bulk-only transport interface reset
*
*************************************************************************/
void UsbBotRstInterface (void)
{
RdyMessEna = FALSE;
//BOT Init
BotState = BotWaitCbw;
Lun = 0;
// Clear all flags
BotStatus.Flags = 0;
ScsiInEp.Size = 0;
// Init receiving of CBW
ScsiOutEp.Size = sizeof(Cbw_t);
ScsiOutEp.pData = (pInt8U)&Cbw;
Csw.dCSWSignature = CswSignature;
// Imlement data from EP buffers (if they are filled)
BotOutEP((void *)UsbDataOutPacket);
}
/*************************************************************************
* 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 *pArg)
{
Int32U CurrSize;
if((Int32U)pArg == UsbDataOutPacket)
{
CurrSize = ScsiOutEp.Size;
if(CurrSize)
{
USB_EpRead((USB_Endpoint_t)BulkOutEp,
ScsiOutEp.pData,
&CurrSize);
ScsiOutEp.Size -= CurrSize;
if((ScsiOutEp.Size == 0) ||
((CurrSize != 0) && (CurrSize < BulkOutEpMaxSize)))
{
// When all data was received or when short packet was received
switch (BotState)
{
case BotWaitCbw: // Implement command request
BotStatus.Flags = 0;
ScsiCommImpl();
return(NULL);
case BotEpDataOut: // The buffer is full
ScsiDrv[Lun].Message[0] = LunDataReadyMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
return(NULL);
}
}
else
{
// The buffer is not filled yet
USB_EpValidate((USB_Endpoint_t)BulkOutEp,TRUE);
ScsiOutEp.pData += CurrSize;
return(NULL);
}
}
else
{
// data was received but buffer isn't assign yet.
return(NULL);
}
}
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 *pArg)
{
Int32U CurrSize;
if((Int32U)pArg == UsbDataInPacket)
{
CurrSize = ScsiInEp.Size;
if(CurrSize)
{
// The buffer isn't drained
USB_EpWrite((USB_Endpoint_t)BulkInEp,ScsiInEp.pData,&CurrSize);
ScsiInEp.Size -= CurrSize;
ScsiInEp.pData += CurrSize;
RdyMessEna = TRUE;
return(NULL);
}
else
{
// The buffer is empty
switch (BotState)
{
case BotEpDataIn:
if(BotStatus.DataComplete)
{
if (Csw.dCSWDataResidue && !BotStatus.ShortPacket)
{
// The host expect more data
BotStatus.ShortPacket = FALSE;
CurrSize = 0;
RdyMessEna = TRUE;
USB_EpWrite((USB_Endpoint_t)BulkInEp,NULL,&CurrSize);
}
else
{
BotSendStatus();
}
return(NULL);
}
if(RdyMessEna)
{
RdyMessEna = FALSE;
ScsiDrv[Lun].Message[0] = LunDataReadyMsg;
pScsiMessage[Lun] = ScsiDrv[Lun].Message;
}
return(NULL);
case BotSendCsw:
// Status packet was received from a host
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: BotWrite
* Parameters: pInt8U pData ,Int32U Size
*
* Return: none
*
* Description: Send data by BulkInEp
*
*************************************************************************/
static
void BotWrite(pInt8U pData ,Int32U Size)
{
volatile Int32U CurrSize;
CurrSize = Size;
RdyMessEna = FALSE;
USB_EpWrite((USB_Endpoint_t)BulkInEp,pData,(pInt32U)&CurrSize);
// Update buffer pointer and remaining data size
ScsiInEp.pData = pData + CurrSize;
ScsiInEp.Size = Size - CurrSize;
}
/*************************************************************************
* 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)
{
Int32U Save;
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;
}
Save = __get_interrupt_state();
__disable_interrupt();
// Set BOT EP state
BotState = BotEpDataOut;
// Update DataResidue
Csw.dCSWDataResidue -= DataSize;
// Init receive of data form BOT OUT EP
ScsiOutEp.pData = pData;
ScsiOutEp.Size = DataSize;
BotOutEP((void *)UsbDataOutPacket);
__set_interrupt_state(Save);
return BotPass;
}
/*************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -