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

📄 scsi.c

📁 NXP LPC系列AMR7的开发程序源码(LCD
💻 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
 *
 *    $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 + -