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

📄 atacb.c

📁 cy68013a USB2.0 highspeed mass storage source code
💻 C
字号:
//-----------------------------------------------------------------------------
//   File:      atacb.c
//   Contents:   ATA CB functionality like ISD-300
//
//   indent 3.  NO TABS!
//
//   Copyright (c) 2003 Cypress Semiconductor
//
// $Workfile: atacb.c $
// $Date: 6/02/05 2:34p $
// $Revision: 4 $
//-----------------------------------------------------------------------------
#include "fx2.h"
#include "fx2regs.h"
#include "gpif.h"
#include "atapi.h"
#include "globals.h"

#if ATACB_ENABLE
//#define BmATACBActionSelect         EP2FIFOBUF[CBW_DATA_START+2]
#define BmATACBRegisterSelect       EP2FIFOBUF[CBW_DATA_START+3]
//#define bATACBTransferBlockCount    EP2FIFOBUF[CBW_DATA_START+4]
#define ATACB_OUT_ATAPI_ALT_STATUS_REG  EP2FIFOBUF[CBW_DATA_START+5]
#define ATACB_OUT_ATAPI_ERROR_REG       EP2FIFOBUF[CBW_DATA_START+6]
#define ATACB_OUT_ATA_SECTOR_COUNT_REG  EP2FIFOBUF[CBW_DATA_START+7]
#define ATACB_OUT_ATA_LBA_LSB_REG       EP2FIFOBUF[CBW_DATA_START+8]
#define ATACB_OUT_ATA_LBA_2SB_REG       EP2FIFOBUF[CBW_DATA_START+0x9]
#define ATACB_OUT_ATA_LBA_MSB_REG       EP2FIFOBUF[CBW_DATA_START+0xa]
#define ATACB_OUT_ATA_DRIVESEL_REG      EP2FIFOBUF[CBW_DATA_START+0xb]
#define ATACB_OUT_ATA_COMMAND_REG       EP2FIFOBUF[CBW_DATA_START+0xc]

#define ATACB_IN_ATAPI_ALT_STATUS_REG  EP6FIFOBUF[0]
#define ATACB_IN_ATAPI_ERROR_REG       EP6FIFOBUF[1]
#define ATACB_IN_ATA_SECTOR_COUNT_REG  EP6FIFOBUF[2]
#define ATACB_IN_ATA_LBA_LSB_REG       EP6FIFOBUF[3]
#define ATACB_IN_ATA_LBA_2SB_REG       EP6FIFOBUF[0x4]
#define ATACB_IN_ATA_LBA_MSB_REG       EP6FIFOBUF[0x5]
#define ATACB_IN_ATA_DRIVESEL_REG      EP6FIFOBUF[0x6]
#define ATACB_IN_ATA_COMMAND_REG       EP6FIFOBUF[0x7]

BYTE BmATACBActionSelect;
//-----------------------------------------------------------------------------
// Structure of the command:
// 0-1 -- signature (0x2424)
//   2 -- BmATACBActionSelect
//   3 -- BmATACBRegisterSelect
//   4 -- bATACBTransferBlockCount
// 5-12-- bATACBTaskFileWriteData 
//-----------------------------------------------------------------------------
BYTE processATACB()
{
   BYTE bATACBTransferBlockCount = EP2FIFOBUF[CBW_DATA_START+4];
   BmATACBActionSelect = EP2FIFOBUF[CBW_DATA_START+2];

   // Are we reading the registers?
   if (BmATACBActionSelect & 1)
      {
      BYTE i;
      AUTOPTRL2 = LSB(EP6FIFOBUF);

      // Clear out the EP buffer
      for (i = 8; i; i--)
         XAUTODAT2 = 0;

      writeATA_DRIVESEL_REG();

      if (!(BmATACBActionSelect & 4))          // Check for pollAltStatOverride bit
         waitForBusyBit();
      if (BmATACBRegisterSelect & 0x01)
         ATACB_IN_ATAPI_ALT_STATUS_REG = readPIO8(ATAPI_ALT_STATUS_REG);         
      if (BmATACBRegisterSelect & 0x02)
         ATACB_IN_ATAPI_ERROR_REG =  readPIO8(ATAPI_ERROR_REG);
      if (BmATACBRegisterSelect & 0x04)
         ATACB_IN_ATA_SECTOR_COUNT_REG =  readPIO8(ATA_SECTOR_COUNT_REG);
      if (BmATACBRegisterSelect & 0x08)
         ATACB_IN_ATA_LBA_LSB_REG =  readPIO8(ATA_LBA_LSB_REG);
      if (BmATACBRegisterSelect & 0x10)
         ATACB_IN_ATA_LBA_2SB_REG =  readPIO8(ATA_LBA_2SB_REG);
      if (BmATACBRegisterSelect & 0x20)
         ATACB_IN_ATA_LBA_MSB_REG =  readPIO8(ATA_LBA_MSB_REG);
      if (BmATACBRegisterSelect & 0x40)
         ATACB_IN_ATA_DRIVESEL_REG =  readPIO8(ATA_DRIVESEL_REG);
      if (BmATACBRegisterSelect & 0x80)
         ATACB_IN_ATA_COMMAND_REG =  readPIO8(ATA_COMMAND_REG);

      // Done with the OUT buffer.
      EP2BCL = 0x80;     

      // Send the data to the host
      loadEP6BC(8);

      return (USBS_PASSED);
      }
   // Executing the command
   else
      {
      if (!(BmATACBActionSelect & 0x02))  // DeviceSelectionOverride
         writePIO8(ATA_DRIVESEL_REG, 0xe0 | ((BYTE)bMasterSlave << 4));

      ATACBcheckStatus();           // The ATACBcheckStatus routine waits for BSY

      if (BmATACBRegisterSelect & 0x01)
         writePIO8(ATAPI_ALT_STATUS_REG, ATACB_OUT_ATAPI_ALT_STATUS_REG);         
      if (BmATACBRegisterSelect & 0x02)
         writePIO8(ATAPI_ERROR_REG, ATACB_OUT_ATAPI_ERROR_REG);
      if (BmATACBRegisterSelect & 0x04)
         writePIO8(ATA_SECTOR_COUNT_REG, ATACB_OUT_ATA_SECTOR_COUNT_REG);
      if (BmATACBRegisterSelect & 0x08)
         writePIO8(ATA_LBA_LSB_REG, ATACB_OUT_ATA_LBA_LSB_REG);
      if (BmATACBRegisterSelect & 0x10)
         writePIO8(ATA_LBA_2SB_REG, ATACB_OUT_ATA_LBA_2SB_REG);
      if (BmATACBRegisterSelect & 0x20)
         writePIO8(ATA_LBA_MSB_REG, ATACB_OUT_ATA_LBA_MSB_REG);
      if (BmATACBRegisterSelect & 0x40)
         {
         if (BmATACBActionSelect & 0x20)  // DEVOverride
            writePIO8(ATA_DRIVESEL_REG, ATACB_OUT_ATA_DRIVESEL_REG);
         else
            writePIO8(ATA_DRIVESEL_REG, 0xe0 | ((BYTE)bMasterSlave << 4));
         }
      if (BmATACBRegisterSelect & 0x80)
         writePIO8(ATA_COMMAND_REG, ATACB_OUT_ATA_COMMAND_REG);

      // Give up the command buffer -- Done with BmATACBRegisterSelect
      EP2BCL = 0x80;     
   
      if (directionIn)
         {
         BYTE driveStatus = 0;
         bit error = 0;
         WORD wThisPacketSize;

         while (dataTransferLen)
            {
            //////////////////////////////////////////////////////////
            // Data Transfer phase
            while (dataTransferLen)
               {
               if (BmATACBActionSelect & 0x40)     // UDMACommand
                  {
                  // Break up the transfer into ATACBTransferBlockCount sized chunks.
                  // use wThisPacketSize as the sector counter
                  if (!bATACBTransferBlockCount)
                     wThisPacketSize = 0x100;
                  else
                     wThisPacketSize = bATACBTransferBlockCount;
                  
                  wThisPacketSize = min(wThisPacketSize, dataTransferLen >> 9);
                  initUdmaRead();
                  prepUDMA(MSB(wThisPacketSize),LSB(wThisPacketSize),0);
                  readUDMA();     // Words = sectors * 256
   
                  // switch the EP back to manual mode
                  EP6Manual();

                  // Clear the interrupt by reading the status reg.
                  while ((driveStatus = readATAPI_STATUS_REG()) & ATAPI_STATUS_BUSY_BIT)
                     ;

                  // If there's anything left in the count regs, we've got a problem.  
                  // We will have to STALL in the IN endpoint to stop the host.
                  if (GPIFTCMSW || GPIFTCLSW)
                     {
                     if ((GPIFTCLSW & 0xff))      // Check for short packet already sent
                        bShortPacketSent = 1;
                     EP6Manual();
                     failedIn();
                     if (ATACBcheckStatus() == USBS_FAILED) 
                        return(USBS_FAILED);
                     else
                        return (USBS_PASSED);
                     }
                  dataTransferLen -= wThisPacketSize * 0x200L;
                  }
               else // PIO mode
                  {
                  ATACBcheckStatus();     // The ATACBcheckStatus routine waits for BSY

                  driveStatus = readATAPI_STATUS_REG();                             

                  if (!(driveStatus & ATAPI_STATUS_DRQ_BIT))
                     {
                     goto readDone;
                     }

                  // Check for drive ready
                  if (driveStatus &  ATAPI_STATUS_ERROR_BIT) // The ATACBcheckStatus routine waits for BSY
                     {
                     goto readDone;
                     }
                     
                  // Wait for available IN buffer
                  waitForInBuffer();
                  wThisPacketSize = min(wPacketSize, dataTransferLen);
                  readPIO16(wThisPacketSize);
                  while (!gpifIdle())    // wait for the read to complete before continuing
                     ;

                  // Send the data to the host and decrement dataTransferLen
                  EP6BCH = MSB(wThisPacketSize);
                  WRITEDELAY();
                  EP6BCL = LSB(wThisPacketSize);

                  dataTransferLen -= wThisPacketSize; 
                  }

               if (!(BmATACBActionSelect & 4))          // Check for pollAltStatOverride bit
                  driveStatus = readATAPI_ALT_STATUS_REG();                             
               }
            }
readDone:
            if (dataTransferLen)
               failedIn();

            // Check for drive ready
            if (ATACBcheckStatus() == USBS_FAILED) // The ATACBcheckStatus routine waits for BSY
               {
               readPIO8(ATAPI_ERROR_REG);
               return(USBS_FAILED);
               }

            // Check for phase error (H0 < Di, Hi < Di)
            if (dataTransferLen)
               if (readATAPI_ALT_STATUS_REG() & ATAPI_STATUS_DRQ_BIT)
                  return(USBS_PHASE_ERROR);
         }
            ////////////////////////////////////////////////////////////////////////////////
      else // OUT command
         {
         WORD wThisPacketSize;

         while (dataTransferLen)
            {
            if (BmATACBActionSelect & 0x40)     // UDMACommand
               {
               // Ignore ATACBTransferBlockCount.  Just use the dataTransferLen.
               // use wThisPacketSize as the sector counter
               wThisPacketSize = dataTransferLen >> 9;
               initUdmaWrite();
               prepUDMA(MSB(wThisPacketSize),LSB(wThisPacketSize),0);
               writeUDMA();
      
               if ((GPIFTCMSW || GPIFTCLSW))
                  {
                  stallEP2OUT();
                  // cancel AUTO OUT mode.
                  EP2Manual();

                  if (ATACBcheckStatus() == USBS_FAILED) // The ATACBcheckStatus routine waits for BSY
                     return(USBS_FAILED);
                  else
                     return(USBS_PASSED);
                  }

               dataTransferLen -= wThisPacketSize << 9;
               }
            else  // Data transfer in PIO mode
               {
               WORD savebc;

               if (ATACBcheckStatus() == USBS_FAILED) // The ATACBcheckStatus routine waits for BSY
                  {
                  stallEP2OUT();
                  return(USBS_FAILED);
                  }

               // Wait for host to send data
               while(EP2CS & bmEPEMPTY)       
                  ;
   
               // Wait for the chip to request data.
               if (ATACBcheckStatus() == USBS_FAILED)    // The ATACBcheckStatus routine waits for BSY
                  {
                  readPIO8(ATAPI_ERROR_REG);

                  stallEP2OUT();
                  return(USBS_FAILED);
                  }
   
               savebc = EP2BC;
               EP2BCL = 0;             // Release the endpoint buffer to FIFO
               writePIO16(savebc);
               dataTransferLen -= savebc;

               // Short packet detection
               if (savebc & (wPacketSize - 1))
                  {
                  if (ATACBcheckStatus() == USBS_FAILED) // The ATACBcheckStatus routine waits for BSY
                     {
                     return(USBS_FAILED);
                     }
                  return(USBS_PASSED);
                  }
               }
            }  // While (dataTransferLen) loop

         // cancel AUTO OUT mode.
         EP2Manual();

         // Check for phase error (H0 < Di, Hi < Di)
         if (dataTransferLen)
            if (readATAPI_ALT_STATUS_REG() & ATAPI_STATUS_DRQ_BIT)
               return(USBS_PHASE_ERROR);
         }  // OUT command
      }
   if (ATACBcheckStatus() == USBS_FAILED) // The ATACBcheckStatus routine waits for BSY
      return(USBS_FAILED);
   return(USBS_PASSED);
}

bit ATACBcheckStatus()
{
   if (!(BmATACBActionSelect & 4))          // Check for pollAltStatOverride bit
      {
      if (waitForBusyBit() == USBS_FAILED)
         if (!(BmATACBActionSelect & 0x8))            // DPErrorOverride
            return(USBS_FAILED);
      }

   else if (readATAPI_ALT_STATUS_REG() & ATAPI_STATUS_ERROR_BIT)                             
      if (!(BmATACBActionSelect & 0x8))            // DPErrorOverride
         return(USBS_FAILED);
   return(USBS_PASSED);
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -