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

📄 fw.c

📁 cypress的usb接ata源代码
💻 C
字号:
//-----------------------------------------------------------------------------
//   File:      fw.c
//   Contents:   Firmware frameworks task dispatcher and device request parser
//            source.
//
// indent 3.  NO TABS!
//
//   Copyright (c) 2001 Cypress Semiconductor
//
// $Archive: /USB/atapifx2/software/fw.c $
// $Date: 1/15/02 10:12a $
// $Revision: 45 $
//-----------------------------------------------------------------------------
#include "fx2.h"
#include "fx2regs.h"
#include "gpif.h"
#include "atapi.h"

//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
#define DELAY_COUNT   0x9248*8L      // Delay for 8 sec at 24Mhz, 4 sec at 48
// USB constants
// Class specific setup commands
#define SC_BOMS_RESET           (0x21)      // Hard/soft depends on wValue field 0 = hard

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
BOOL      Rwuen;
BOOL      Selfpwr;
volatile BOOL   Sleep;                  // Sleep mode enable flag
BYTE   AlternateSetting;   // Alternate settings
BYTE   Configuration;      // Current configuration


//WORD   pDeviceDscr;   // Pointer to Device Descriptor; Descriptors may be moved
//WORD   pDeviceQualDscr;
//WORD   pHighSpeedConfigDscr;
//WORD   pFullSpeedConfigDscr;   
WORD   pConfigDscr;
WORD   pOtherConfigDscr;   
//WORD   pStringDscr;

BYTE intrfcSubClass;

//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
void SetupCommand(void);
void TD_Init(void);
void TD_Poll(void);
//BOOL TD_Suspend(void);
//BOOL TD_Resume(void);
void DisconAndWaitForVbus();

WORD wPacketSize;


//-----------------------------------------------------------------------------
// Code
//-----------------------------------------------------------------------------

// Task dispatcher

void main(void)
{
   BYTE     i;

   // Init globals
   MaxPIO = 0;                // reset MaxPIO value
   Sleep = FALSE;             // Reset suspend flag
   Rwuen = FALSE;             // Disable remote wakeup
   Selfpwr = FALSE;           // Disable self powered

   // if we are hung up in a GPIF transfer, abort it.  How could this happen?  If
   // we ended up here after a USB Reset or a MSC Reset, it is possible that the
   // GPIF is hung waiting for a transfer that will never complete.
   abortGPIF(); // TPM: Unconditionally abort

   TD_Init();

   // The following section of code is used to relocate the descriptor table from
   // ROM to RAM.  It is done here because we are done with the halfKBuffer at this point.
   // Although it looks wierd, the only way to get the proper values for the offsets
   // is to tell the compiler that we want the address of the variable, not the variable itself.
   mymemmovexx(halfKBuffer, (char xdata *) &DeviceDscr, (WORD)&DscrEndOffset);
//   pDeviceDscr = (WORD)(halfKBuffer + (WORD)&DeviceDscrOffset);
//   pDeviceQualDscr = (WORD)(halfKBuffer + (WORD)&DeviceQualDscrOffset);
//   pHighSpeedConfigDscr = (WORD)(halfKBuffer + (WORD)&HighSpeedConfigDscrOffset);
//   pFullSpeedConfigDscr = (WORD)(halfKBuffer + (WORD)&FullSpeedConfigDscrOffset);
//   pStringDscr = (WORD)(halfKBuffer + (WORD)&StringDscrOffset);

   halfKBuffer[(WORD) &IntrfcSubClassHighSpeedOffset] = 
      halfKBuffer[(WORD) &IntrfcSubClassFullSpeedOffset] = intrfcSubClass;


   for (i = 0; i < ATAPI_INQUIRY_SERIAL_LEN *2; i++)
      halfKBuffer[i+(WORD)&SerialNumberOffset] = localSerialNumber[i];
  
   EZUSB_IRQ_ENABLE();            // Enable USB interrupt (INT2)
   EZUSB_ENABLE_RSMIRQ();            // Wake-up interrupt

   INTSETUP |= (bmAV2EN);     // Enable INT 2 autovectoring

   USBIE |= bmSUDAV | bmSUSP | bmURES | bmHSGRANT;   // Enable selected interrupts
   EA = 1;                  // Enable 8051 interrupts

   // Renumerate if necessary.  Do this by checking the renum bit.  If it
   // is already set, there is no need to renumerate.  The renum bit will
   // already be set if this firmware was loaded from an eeprom or if we
   // have already been through this code once and we are here again
   // because of a USB Reset.
   if(!(USBCS & bmRENUM))
   {
       EZUSB_Discon(TRUE);   // renumerate
   }

#ifdef VBUS_DETECT
   // check for the presence of VBus and re-connect.  If we loaded from eeprom
   // we are disconnected and need to connect.  If we just renumerated this
   // is not necessary but doesn't hurt anything.  VBus on the Rev *B 4611 boards
   // is tied to port A.6.
   if (IOA & bmBIT6)
   {
      USBCS &=~bmDISCON;
   }
   else
   {
      DisconAndWaitForVbus();
   }
#else
   // unconditionally re-connect.  If we loaded from eeprom we are
   // disconnected and need to connect.  If we just renumerated this
   // is not necessary but doesn't hurt anything
   USBCS &=~bmDISCON;
#endif

   CKCON = (CKCON&(~bmSTRETCH)) | FW_STRETCH_VALUE; // Set stretch to 0 (after renumeration)

   // complete the handshake phase of any pending SETUP transfer.
   // The only time this should happen is after a MSC Reset.  We want
   // to go through all of the EP init code before handshaking the status
   // phase of the MSC Reset.
   EP0CS |= bmHSNAK;

   // Task Dispatcher
   while(TRUE)                     // Main Loop
   {
#ifdef VBUS_DETECT
      // we need to constantly monitor VBus (tied to Port A.6) and disconnect if
      // it isn't there.  This is to avoid driving D+ (a spec violation) when the
      // host isn't there.
      if (!(IOA & bmBIT6))
         DisconAndWaitForVbus();
#endif

      TD_Poll();
   }
}

#ifdef VBUS_DETECT
// This function monitors VBus from the host and stays disconnected until VBus is
// is present.  VBus is tied to Port A.6 on the new FX2 ATAPI tailgate boards.
// (4611 Rev *B)
void DisconAndWaitForVbus()
{
   USBCS |= bmDISCON;
   while (!(IOA & bmBIT6));
   USBCS &= ~bmDISCON;
}
#endif
   

// Device request parser
void SetupCommand(void)
{
   void   *dscr_ptr;

   switch(SETUPDAT[1])
   {
      case SC_GET_DESCRIPTOR:                      // *** Get Descriptor
         switch(SETUPDAT[3])         
            {
               case GD_DEVICE:                     // Device
                  SUDPTRH = MSB(pDeviceDscr);
                  SUDPTRL = LSB(pDeviceDscr);
                  break;
               case GD_DEVICE_QUALIFIER:            // Device Qualifier
                  SUDPTRH = MSB(pDeviceQualDscr);
                  SUDPTRL = LSB(pDeviceQualDscr);
                  break;
               case GD_CONFIGURATION:              // Configuration
                  SUDPTRH = MSB(pConfigDscr);
                  SUDPTRL = LSB(pConfigDscr);
                  break;
               case GD_OTHER_SPEED_CONFIGURATION:  // Other Speed Configuration
                  // fx2bug - need to support multi other configs
                  SUDPTRH = MSB(pOtherConfigDscr);
                  SUDPTRL = LSB(pOtherConfigDscr);
                  break;
               case GD_STRING:            // String
                  if(dscr_ptr = (void *)EZUSB_GetStringDscr(SETUPDAT[2]))
                  {
                     SUDPTRH = MSB(dscr_ptr);
                     SUDPTRL = LSB(dscr_ptr);
                  }
                  else 
                     EZUSB_STALL_EP0();   // Stall End Point 0
                  break;
               default:                   // Invalid request
                  EZUSB_STALL_EP0();      // Stall End Point 0
            }  // switch
         break;
      case SC_GET_INTERFACE:                  // *** Get Interface
         EP0BUF[0] = AlternateSetting;
         EP0BCH = 0;
         EP0BCL = 1;
         break;
      case SC_SET_INTERFACE:                  // *** Set Interface
         AlternateSetting = SETUPDAT[2];
         break;
      case SC_SET_CONFIGURATION:               // *** Set Configuration
      // BUGBUG -- Add delay for the CATC
         Configuration = SETUPDAT[2];
         break;
      case SC_GET_CONFIGURATION:               // *** Get Configuration
         EP0BUF[0] = Configuration;
         EP0BCH = 0;
         EP0BCL = 1;
         break;
      case SC_GET_STATUS:                 // *** Get Status
            switch(SETUPDAT[0])
            {
               case GS_DEVICE:            // Device
                  EP0BUF[0] = ((BYTE)Rwuen << 1) | (BYTE)Selfpwr;
                  EP0BUF[1] = 0;
                  EP0BCH = 0;
                  EP0BCL = 2;
                  break;
               case GS_INTERFACE:         // Interface
                  EP0BUF[0] = 0;
                  EP0BUF[1] = 0;
                  EP0BCH = 0;
                  EP0BCL = 2;
                  break;
               case GS_ENDPOINT:         // End Point
                  if (SETUPDAT[4] == 0x2)
                  {
                     EP0BUF[0] = (EP2CS & bmEPSTALL);
                  }
                  else if (SETUPDAT[4] == 0x88)
                  {
                     EP0BUF[0] = (EP8CS & bmEPSTALL);
                  }
                  else
                  {
                     EZUSB_STALL_EP0();   // Stall End Point 0
                     break;
                  }

                  EP0BUF[1] = 0;
                  EP0BCH = 0;
                  EP0BCL = 2;
                  break;
               default:                   // Invalid Command
                  EZUSB_STALL_EP0();      // Stall End Point 0
            }
         break;
      case SC_CLEAR_FEATURE:                  // *** Clear Feature
            switch(SETUPDAT[0])
            {
               case FT_DEVICE:            // Device
                  if(SETUPDAT[2] == 1)
                     Rwuen = FALSE;       // Disable Remote Wakeup
                  else
                     EZUSB_STALL_EP0();   // Stall End Point 0
                  break;
               case FT_ENDPOINT:          // End Point
                  if(SETUPDAT[2] == 0)
                  {
                     if (SETUPDAT[4] == 0x2)
                     {
                        ResetAndArmEp2();
                        TOGCTL = 0x2;
                        TOGCTL = 0x22;       // reset data toggle
                        EP2CS = 0;           // Clear stall bit
                     }
                     else if (SETUPDAT[4] == 0x88)
                        {
                        TOGCTL = 0x18;
                        TOGCTL = 0x38;       // reset data toggle
                        EP8CS = 0;           // Clear stall bit
                        }
                     else
                        EZUSB_STALL_EP0();   // Stall End Point 0
                     }
                  else
                     EZUSB_STALL_EP0();      // Stall End Point 0
                  break;
            }  
         break;
      case SC_SET_FEATURE:                  // *** Set Feature
            switch(SETUPDAT[0])
            {
               case FT_DEVICE:            // Device
                  if(SETUPDAT[2] == 1)
                     Rwuen = TRUE;        // Enable Remote Wakeup
                  else if(SETUPDAT[2] == 2)
                     // Set Feature Test Mode.  The core handles this request.  However, it is
                     // necessary for the firmware to complete the handshake phase of the
                     // control transfer before the chip will enter test mode.  It is also
                     // necessary for FX2 to be physically disconnected (D+ and D-)
                     // from the host before it will enter test mode.
                     break;
                  else
                     EZUSB_STALL_EP0();   // Stall End Point 0
                  break;
               case FT_ENDPOINT:          // End Point
                  if(SETUPDAT[2] == 0)
                     {
                     if (SETUPDAT[4] == 0x2)
                        EP2CS = bmEPSTALL;         // Set stall bit
                     else if (SETUPDAT[4] == 0x88)
                        EP8CS = bmEPSTALL;         // Set stall bit
                     else
                        EZUSB_STALL_EP0();   // Stall End Point 0
                     }
                  else
                     EZUSB_STALL_EP0();   // Stall End Point 0
                  break;
            }  
         break;

      // This is a first attempt at completing a mass storage reset.  It is not yet tested.
      case SC_MASS_STORAGE_RESET:
         // Verify that the command is actually a MS reset command sent to the proper interface
         if (SETUPDAT[0] == 0x21 && SETUPDAT[4] == 0)  // Our interface number is hard coded (0) in DSCR.A51
         {
            // All we really need to do in response to a MSC Reset is restart using
            // a soft reset (jump to 0x00).  This will re-initialize the drive and
            // endpoints.
            EZUSB_IRQ_CLEAR();
            INT2CLR = bmSUDAV;         // Clear SUDAV IRQ

            // force a soft reset after the iret.
            EA = 0;
            softReset();
         }
         else
            EZUSB_STALL_EP0();   // Stall End Point 0
         break;

      default:                            // *** Invalid Command
            EZUSB_STALL_EP0();            // Stall End Point 0
   }

   // Acknowledge handshake phase of device request
   // Required for rev C does not effect rev B
    EP0CS |= bmHSNAK;
}

// Wake-up interrupt handler
void resume_isr(void) interrupt WKUP_VECT
{
   EZUSB_CLEAR_RSMIRQ();
}

STRINGDSCR xdata *   EZUSB_GetStringDscr(BYTE StrIdx)
{
   extern BYTE code StringDscr0;
   extern BYTE code StringDscr1;
   extern BYTE code StringDscr2;
   extern BYTE code StringDscr3;

   switch (StrIdx)
   {
      case 0:
         return((STRINGDSCR xdata *)&StringDscr0);
      case 1:
         return((STRINGDSCR xdata *)&StringDscr1);
      case 2:
         return((STRINGDSCR xdata *)&StringDscr2);
      case 3:
         return((STRINGDSCR xdata *)&StringDscr3);
      default:
         return(0);
   }
}

⌨️ 快捷键说明

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