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

📄 fw.c

📁 cy68013a USB2.0 highspeed mass storage source code
💻 C
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
//   File:      fw.c
//   Contents:   Firmware frameworks task dispatcher and device request parser
//            source.
//
// indent 3.  NO TABS!
//
//   Copyright (c) 2001-2004 Cypress Semiconductor
//
// $Workfile: fw.c $
// $Date: 6/26/05 1:57p $
// $Revision: 10 $
//-----------------------------------------------------------------------------
#include "fx2.h"
#include "fx2regs.h"
#include "gpif.h"
#include "atapi.h"
#include "globals.h"

#define GD_CS_GENERAL_DESCRIPTOR 0x21
#define GD_CHANNEL_DESCRIPTOR 0x22
#define GD_CSM_DESCRIPTOR 0x23
#define GD_CSMV_DESCRIPTOR 0x24

#define SC_GET_CHANNEL_SETTINGS 1
#define SC_SET_CHANNEL_SETTINGS 2

#define SC_GET_UNIQUE_ID 0x80

//-----------------------------------------------------------------------------
// 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

//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
void SetupCommand(void);
void TD_Init(void);
void TD_Poll(void);

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

// Task dispatcher

void main(void)
{
   // set the renum bit so that firmware handles SETUP transfers.
   USBCS |= bmRENUM;

   // 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

   EZUSB_ENABLE_RSMIRQ();            // Wake-up interrupt

   TD_Init();      

   EZUSB_IRQ_ENABLE();            // Enable USB interrupt (INT2)

   INTSETUP = bmAV2EN;     // Enable INT 2 autovectoring

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

   Sleep = 0;
   driveIsInStandby = 0;

   noFlashMedia = 1;
   ejected = 0;
   udmaErrorCount = 0;
   oldButtons = 0xff;

   // 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.
   if (IN_MASS_STORAGE_CLASS_RESET)
      EP0CS |= bmHSNAK;
   EA = 1;                  // Enable 8051 interrupts
   TR0 = 1;                 // Make sure that the timer ISR runs at once.  This will take care of the ATA_ENABLE line

   // Reconnect to USB if we have our MAX_LUN or if we need a SET_CONFIGURATION msg
   if (VBUS_POWERED || b1LUN_SET_BY_EEPROM || b2LUN_SET_BY_EEPROM)
      {
      USBCS &=~bmDISCON;            // Reconnect to USB.  This line has no effect in a system that's already connected.
      }

   // Enable interrupts and wait here until we receive a SET_CONFIGURATION message.
   // why?
   // because we can not identify bus-powered drives until we can turn on nPWR500.
   // We no longer pull the serial number from the drive.  We will not get a GET_MAX_LUN
   // command until after the drives are turned on.

   // Okay to connect here IF we're not planning to update the number of LUNs
   if (!(bFirstTime || deviceCount == 0x80))
      USBCS &=~bmDISCON;

   if (!mfgMode)
      ATAInit();
   // Reconnect to USB.  This line has no effect in a system that's already connected.
   USBCS &=~bmDISCON;

   USBIE = bmSUDAV | bmSUSP | bmURES | bmHSGRANT;   // Enable SETUP interrupts
   CKCON = (CKCON&(~bmSTRETCH)) | FW_STRETCH_VALUE; // Set stretch to 0 (after renumeration)

   // Check for spurious sleep flag.  We will often detect SUSPEND during startup but it's probably over now.
   if (Sleep)
      {
      USBCS |= bmNOSYNSOF;
      USBIRQ |= bmSOF;
      EZUSB_Delay(3);
      if (USBIRQ & bmSOF)
         Sleep = 0;
      }         

//   FIFORESET = 0;    // turn off nakall
   // Task Dispatcher
   while(TRUE)                     // Main Loop
   {
      ////////////////////////////////////////////////////////////////////
      // There are four sleep states in a removable-drive system, three
      // in a non-removable system.
      //
      // 1. Unplugged -- Reached whenever ATA_EN/VBUS is low.  D+ is not pulled up.
      //       This state is coded in checkATAEnable(), reached via the ISR or from this routine.
      //       This state wakes only on WAKEUP# 0-->1, so WAKEUPCS = bmWU | bmWUPOL | bmWUEN
      //       The code passes through softReset at the end of this state.
      // 2. Active -- D+ is pulled up.  This is the main code path.
      // 3. Sleeping -- CPU is shut down waiting for D+ to go active.  In the removable drive (CF) case,
      //       WU2 can also wake the device so that card swaps during suspend can be detected.
      // 4. Card swap -- If we are awakened by WU2, set the noFlashMedia flag so we will report new media 
      //       the next time that we detect a CF.  This detection takes place in TD_Poll()
      ////////////////////////////////////////////////////////////////////
#if STANDBY_IMMEDIATE
      WAKEUPCS = 0x45;
      if (Sleep || (WAKEUPCS & 0x40) || (!bNewAt2pinout && !VBUS_PRESENT))     // check VBUS and old part's VBUS detector
      {
         WORD i;
         Sleep = FALSE;

         //////////////////////////////////////////////////
         // Special purpose power-saving code.
         //
         // Expected conditions:  
         //     Self-powered, no bus-sharing, single IDE device
         //
         // This code will wait 100ms before turning off the drive.
         // This is to debounce any short sleep conditions that occur, like the 
         // ~75ms sleep period that many hosts do during startup.
         //////////////////////////////////////////////////
         USBCS |= bmNOSYNSOF;
         USBIRQ |= bmSOF;
         for (i = 0; i < 500; i++)
            {
            EZUSB_Delay(1);
            if (USBIRQ & bmSOF)
                break;
            }

         if (!(USBIRQ & bmSOF))
            standbyImmediate();
#else
      if (Sleep)
      {
         Sleep = FALSE;

         if (!bScsi)
             flushCache();
#endif

         // Before going to sleep, check the tri-state pin one last time.
         // This will also catch the case where we were woken up by the tri-state pin and must go back to sleep.
         EZUSB_Delay(10);      // Make sure VBUS has time to go away before checking it.
         checkATAEnable();
         OEC = PORTC_OE_SUSPEND;
         OEE = PORTE_OE_SUSPEND | (mx2_config_data.GpioOE << 2);

         powerOff();

         // Drive the data bus low.  This code is only called in suspend, not in the other power-off cases.
         if (VBUS_POWERED)
            {
            IFCONFIG &= ~3;   // Turn off GPIF control of ports B and D.
            IOB = IOD = IOA = 0;
            OEB = OED = 0xff;
            OEA = 0xf7;
            GPIFCTLCFG = 0x80;   // 
            GPIFIDLECTL = 0x70;  // x111x000 - CTL3 not enabled.  Drive the CTL lines LOW
            }
         
         #if STANDBY_IMMEDIATE
         // Standby_Immediate case kills all of the stuff done in check_ata_enable so that 
         // it can turn off the drive in this background loop.  This means that WAKEUP# could
         // be high or low here in the STANDBY_IMMEDIATE case
         WAKEUPCS = bmWU2 | bmWU                      | bmDPEN | bmWUEN;
         if (WAKEUPCS & bmWU)
            WAKEUPCS = WAKEUPCS = bmWU2 | bmWU | bmWUPOL         | bmDPEN | bmWUEN;
         #else
         // Wake up on D+ traffic, WAKEUP 1-->0.
         // If there is a CF, wake up on CF insertion too.
         if (bDRVPWRVLD_ENABLE)
            {
            if (CF_DETECT_)
               WAKEUPCS = bmWU2 | bmWU | bmWU2EN |            bmDPEN | bmWUEN;      // No CF, wake on low
            else
               WAKEUPCS = bmWU2 | bmWU | bmWU2EN | bmWU2POL | bmDPEN | bmWUEN;      // CF there, wake on high
            }
         else
            WAKEUPCS = bmWU2 | bmWU                      | bmDPEN | bmWUEN;
         #endif

         // Make sure that we don't get a USB reset interrupt before we can enable everything
         USBIE = 0;

         EZUSB_Susp();         // Place processor in idle mode.

         // If we were woken up by a CF insertion, go back to sleep after one loop.
         if (WAKEUPCS & bmWU2)
            Sleep = TRUE;

         // Undo "drive data bus low" code above.
         if (VBUS_POWERED)
            {
            OEA = PORTA_OE;
            OUTATAPI = ATAPI_IDLE_VALUE;
            IFCONFIG = IFCONFIG_DEFAULT;    
            GPIFCTLCFG = 0x80;   // 
            GPIFIDLECTL = 0x77;  // x111x000 - CTL3 not enabled.  Drive the CTL lines LOW
            }

         OEC = PORTC_OE;
         OEE = PORTE_OE | (mx2_config_data.GpioOE << 2);

         powerOn();
         // Re-enable USB reset interrupt 
         USBIE = bmSUDAV | bmSUSP | bmURES | bmHSGRANT;   // Enable SETUP interrupts
      }  // endif (sleep)

      TD_Poll();     
   }  // End while-forever loop
}


// Standard requests are 
#define STANDARD(x)  (x | (SETUP_STANDARD_REQUEST<<8))  
#define CLASS(x) (x | (SETUP_CLASS_REQUEST << 8))
#define VENDOR(x) (x | (SETUP_VENDOR_REQUEST << 8))

// We can cheat on all of these parameters.  All of our supported commands only use the LSB.
#define wValue  setupdat2
#define wIndex  setupdat4
#define wLength setupdat67

// Device request parser
void SetupCommand(void)
{
   // Making these items static doesn't hurt the stack compilation because this is an ISR.
   // It also removes them from the stack compilation, allowing them to be fit into gaps in the data space
   static BYTE setupdat0;
   static BYTE setupdat2;
   static BYTE setupdat4;
   static WORD setupdat67;
   BYTE i;
   setupdat0 = SETUPDAT[0];
   setupdat2 = SETUPDAT[2];
   setupdat4 = SETUPDAT[4];
   setupdat67 = SETUPDAT[6] | (SETUPDAT[7] << 8);
   EP0BCH = 0;                                     // Default to MSB of the length is 0
   SUDPTRH = MSB(halfKBuffer);                     // Default to descriptor table

   if ((setupdat0 & SETUP_MASK) == SETUP_STANDARD_REQUEST)
      {
      switch(SETUPDAT[1])
         {
         case SC_GET_DESCRIPTOR:                      // *** Get Descriptor

⌨️ 快捷键说明

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