⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi.c

📁 最新版IAR FOR ARM(EWARM)5.11中的代码例子
💻 C
📖 第 1 页 / 共 3 页
字号:
/*************************************************************************
 *
 *    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 + -