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

📄 periph.c

📁 cy68013a USB2.0 highspeed mass storage source code
💻 C
📖 第 1 页 / 共 3 页
字号:
#pragma NOIV               // Do not generate interrupt vectors
//-----------------------------------------------------------------------------
//   File:      periph.c
//   Contents:   Hooks required to implement USB peripheral function.
//
//   Copyright (c) 1997-2003 Cypress Semiconductor, Inc. All rights reserved
//
// $Archive: /USB/atapifx2/CY4611B/periph.c $
// $Date: 6/30/05 10:48a $
// $Revision: 9 $
//-----------------------------------------------------------------------------
#include "fx2.h"
#include "fx2regs.h"
#include "gpif.h"
#include "atapi.h"
#include "globals.h"

extern BOOL   Sleep;
extern BOOL   Rwuen;

void clearResetLine();

//-----------------------------------------------------------------------------
// Task Dispatcher hooks
//   The following hooks are called by the task dispatcher.
//-----------------------------------------------------------------------------

void TD_Init(void)             // Called once at startup
{
   bit bError;

   // set our first_time flag.  This is set to the timer start bit.  The timer start
   // bit will only be set if we have already been here before.
   bFirstTime = !TR0;

   phaseErrorState = 0;
   bScsiRegsPreloaded = 0;
   attemptFastScsi = 0;

   // Enable both autoptrs.  ONLY use AUTOPTR2 for writing small amounts of data to EP6buf.  NEVER load
   // AUTOPTR1H again.
   AUTOPTRSETUP = 0x7;
   AUTOPTRH2 = MSB(EP6FIFOBUF);

   
   // Only do the copy the first time we run because we modify the descriptor version in HalfKBuffer.
   // We know it's the first time if the timer isn't running yet.
   // There are three possible startup conditions:
   // -- AT2 classic EEPROM present.  Turns off many new features, including EP1
   // -- AT2LP EEPROM present.  As defined in the datasheet
   // -- Bad signature found.  Assumed to be an unprogrammed EEPROM.  Skip drive ID and wait for mfg mode command.
   if (bFirstTime)
   {        
      bError = 1;

      eepromAddr = EEPROM_ADDR;
      bError = EEPROMRead(CONFIG_SPACE_START,sizeof(MX2_CONFIG_DATA), (BYTE xdata *) &mx2_config_data);
         
      miscConfig = mx2_config_data.MiscConfig;
      miscConfig2 = mx2_config_data.MiscConfig2;
      // Secret bit for 400Khz EEPROM read)
      if (bATA_UDMA_ENABLE)
         {
         bATA_UDMA_ENABLE = 0;
         I2CTL |= bm400KHZ;
         }
      miscConfig |= mx2_config_data.UdmaConfig & 0xc0;
      pinConfig = mx2_config_data.PinConfig;
      mymemmovexx(halfKBuffer, (char xdata *) &DeviceDscr, (BYTE)&DscrEndOffset);
      sensePtrs[0] = sensePtrs[1] = sensePtr = senseMediaChanged;

      if (bError)
         eepromAddr = 0x52;      // Config for dev board if error is detected.

      // Missing signature:  Read the dscr.a51 file for the VID/PID.  Enter mfg mode.
      if (!(mx2_config_data.Signature == MX2_EEPROM_SIGNATURE || mx2_config_data.Signature == AT2LP_EEPROM_SIGNATURE))
         {
         // relocate USB descriptors to RAM
         // load the deecriptors from the rom.
         mymemmovexx(halfKBuffer, (char xdata *) &DeviceDscr, (WORD)&DscrEndOffset);

         setDefaultConfig();

         enterMfgMode();
         }  
      else 
      {
         mfgMode = 0;
   
         // relocate USB descriptors to RAM
         // load the deecriptors from the eeprom.
         // the descriptor data starts at offset 16 in the eeprom
         EEPROMRead(CONFIG_SPACE_START+sizeof(MX2_CONFIG_DATA),BUFFER_SIZE,halfKBuffer);

         // Almost all of the AT2LP bits are RESERVED=0 in the AT2 EEPROM.  Set the non-reserved ones here.
         if (mx2_config_data.Signature == MX2_EEPROM_SIGNATURE)
            {
            bATA_ENABLED                 = 1;
            bNewAt2pinout = 0;
            }
         else
            {
            bNewAt2pinout = 1;
            IOEShadow |= mx2_config_data.GpioData << 2;
            IOE = IOEShadow;
            OEE |= mx2_config_data.GpioOE << 2;
            checkGPIOonPA3();
            }

         ////////////////////////////////////////////////////////////////////////////////
         // Check for RESET shorted to DD7 to signal mfg mode.  This allows devices
         // to be reprogrammed without a drive attached.  If the firsttime flag is set,
         // the GPIF isn't set up yet, so we can treat DD7 like a normal pin.
         //
         // Check procedure:
         // 1)  Check for VBUS -- No VBUS = no check
         // 2)  Float the reset line.  If it floats high, abort.
         // 3)  Reset is now low.  Drive DD7 high.  If RESET is now high, enter mfg mode.
         WAKEUPCS = 0x45;
         if (!(WAKEUPCS & 0x40))     // check VBUS and old part's VBUS detector
            {
            OEA &= ~ATAPI_RESET_BIT;
            if (!ATAPI_RESET_)
               {
               OEB = 0x80;
               PB7 = 0x80;
               if (ATAPI_RESET_)
                  enterMfgMode();
               OEB = 0x0;
               }
            OEA |= ATAPI_RESET_BIT;
            }
      }
   }

   // init state/reset variables
   currentState = UNCONFIGURED;

   // 0x80 is used as a flag value to tell us that we still need to complete drive ID.
//   if (bFirstTime || !deviceCount)
//      {
//      deviceCount = 0x80;
//      LunBits[0] = LunBits[1] = ActiveLunBits = 0;    // zeroes out bCompactFlash, bScsi, bExtAddrSupport
//      }

   attemptFastRead = attemptFastWrite = 0;

   // In order to properly support HID and CSM, we have to parse part of the descriptors.
   // If there is more than one descriptor, some offsets are pulled from the descriptors.
   HIDIntrfcDscrOffset = CSMIntrfcDscrOffset = 0;
   if (bNewAt2pinout)
      {
   
      #define INTRFC_OFFSET 4
         {
         xdata BYTE *ptr;
         
         for (ptr = halfKBuffer+ (BYTE) &FullSpeedConfigDscrOffset; 
            MSB(ptr) == MSB(halfKBuffer) && *ptr != 0; ptr += *ptr)
            {
            if (ptr[1] == DSCR_INTRFC)
               {
               if (ptr[5] == 3)  // HID class code
                  HIDIntrfcDscrOffset = LSB(ptr);
               else if (ptr[5] == 0xd)
                  CSMIntrfcDscrOffset = LSB(ptr);
               }
            // Existing EEPROMs may contain 0x88 for EP8IN instead of 0x86 for EP6IN.  Fix it on the fly.
            else if (ptr[1] == DSCR_ENDPNT && ptr[2] == 0x88)
               ptr[2] = 0x86;
             }
         }
      }
   else  // for old AT2 pinout, must modify the descriptor from EP8IN to EP6IN
      {
      if (halfKBuffer[(BYTE) &FullSpeedConfigDscrOffset+ DSCR_CONFIG_LEN + DSCR_INTRFC_LEN + 2] == 0x88)
          halfKBuffer[(BYTE) &FullSpeedConfigDscrOffset+ DSCR_CONFIG_LEN + DSCR_INTRFC_LEN + 2] = 0x86;
      if (halfKBuffer[(BYTE) &FullSpeedConfigDscrOffset+ DSCR_CONFIG_LEN + DSCR_INTRFC_LEN + DSCR_ENDPNT_LEN + 2] == 0x88)
          halfKBuffer[(BYTE) &FullSpeedConfigDscrOffset+ DSCR_CONFIG_LEN + DSCR_INTRFC_LEN + DSCR_ENDPNT_LEN + 2] = 0x86;
      }


   initUSB();                 // configure output ports and endpoint params
   mymemmovexx(&GPIF_WAVE_DATA, (BYTE xdata *) WaveDataPioUDMA, 128);          // load wave forms in memory

   // Set up timer 0 to act as the timeout counter.
   // The default setting for the debugger uses timer 1
   TMOD = 0x21;      // Timer 1 set up for debugger (just in case).  Timer 0 is 16 bit counter
   CKCON = 0x10;     // Same setting as debugger for T1, T0 is CPU/12 (4Mhz input)
   ET0 = 1;          // Enable timer interrupt (needed to do software count of 61hz overflows)
   TR0 = 1;
}

void TD_Poll(void)             // Called repeatedly while the device is idle
{
   WORD    count = 0;

   // check EP2 EMPTY(busy) bit in EP2468STAT (SFR), core set's this bit when FIFO is empty
   if(!(EP2468STAT & bmEP2EMPTY))   
      {
      // Check for "USBC"
      if (checkCBW() == USBS_PASSED)
         {
         // Good packet, forward to the device.
         processCBW();  
         }
      else
         {
         // if we receive an invalid CBW, STALL both bulk endpoints and remain that
         // way until reset recovery (MSC BOT 6.6.1)
         EP2CS = EP6CS = bmEPSTALL;
         phaseErrorState = 1;
         }
      }
   #if DEVICE_TYPE_IS_IDE
   checkForMedia(0);
   #endif
}


//-----------------------------------------------------------------------------
// Support functions for specific device
//-----------------------------------------------------------------------------

void initUSB(void)
{
   DBUG &= ~0x01;  // Turn off phase-picker power savings. (DBUG at 0xE6F8)
   PORTACFG = 0;

   OUTATAPI = ATAPI_IDLE_VALUE; 
   nLOWPWR  = 0;           // active low -- Indicates active (0) vs suspend (tri-state)
   IOEShadow = nPWR500 | ATAPUEN;
   IOE = IOEShadow;         // active low -- Start with power OFF
   OEC = PORTC_OE;
   if(VBUS_POWERED)
      {
      OEE |= (PORTE_OE_SUSPEND);
      triStateATABus();
      }
   else
      OEE |= PORTE_OE;
      

   // Enable INT4 to latch the GPIOs
   EXIF &= ~bmIE4;      // Clear any pending interrupts
   EIEX4 = 1;             // Enable INT4 interrupts
                        // INTSETUP is configured elsewhere.

// if we are trying to operate in bus powered mode, we want to defer setting the 
// CPU clock speed or configuring the GPIF until we have been configured.  This
// is to keep our current under 100mA.
   IFCONFIG = IFCONFIG_DEFAULT;
   CPUCS = bmCLKSPD1 | bmCLKINV; // set clock to 48MHz.  clock output disabled. inverted.
//   FIFOPINPOLAR = 0x00;    // ff pin is active low -- This is the default

//   PINFLAGSAB = 0x00;    // FLAGA PF for FIFO selected by FIFOADR[1..0] -- 0 is the default
   PINFLAGSCD = 0x00;    // FLAGB FF for FIFO selected by FIFOADR[1..0]

   // GPIF and CTL configuration
   checkATAEnable();    // Sets GPIFIDLECTL, OEA
   GPIFIDLECS = 0;      // tristate data bus during idle interval
   GPIFREADYCFG = 0x20;    // Turn on TCXpire as a ready source
   GPIFTCB3 = 0;        // Set this ONCE, not every time.  No xfers longer than 24 bits.

   FLOWEQ0CTL = 0x00;      // UDMA init that's the same for both read and write
   FLOWSTBEDGE = 0x03;     // 
   GPIFHOLDAMOUNT = 0x01;  // 


   GPIFWFSELECT = GPIFWFSELECT_DEFAULT;

   // Endpoint initialization
   EP2CFG = 0xA0;           // ep2 is valid BULK OUT 512 quad buffered
   EP2FIFOCFG = 0x05;       // WORDWIDE=1M MANUAL
   EP2FIFOPFH = 0x00;       // PF=0 when BC > PF -> Decis=0 (1 byte in FIFO)
   EP2FIFOPFL = 0x00;       // PF and BC refer to the current pkt -> PKTSTAT=0
//   EP2GPIFPFSTOP = 0;       // Do not stop on PF -- This is the default

   EP6CFG = 0xE0;          // ep6 is valid BULK IN 512 double buffered
   EP6FIFOCFG = 0x05;      // set EP6:  0x05=MANUAL, 0x0D=AUTOIN

   EP1INCFG = 0x80 | 0x30;    // EP1IN is valid INTERRUPT in

   // mark all unused endpoints invalid - setting each reg to 0x22 instead of just clearing
   // the valid bit to save code space.  0x22 basically sets all of these endpoints to 
   // not valid, bulk, double 512 buffered.
   EP1OUTCFG = EP4CFG = EP8CFG = 0x22;

   // disbable Auto Arm
   REVCTL = bmNOAUTOARM;

   // arm the OUT endpoint.  By default OUT endpoints come up unarmed.
   ResetAndArmEp2();

   // reset the EP6 FIFO.  If we are here as the result of a USB reset or MSC
   // Reset Recovery, EP6 may need to be cleaned up.
   FIFORESET = 0x06;

   if (!IN_MASS_STORAGE_CLASS_RESET)
      AlternateSetting = Configuration = 0;
}



// Stalls EP2OUT endpoint.
//
// This routine automatically handles several problematic OUT STALL cases.
//
// 1)  The host is still PINGing us on the OUT endpoint, we set the stall bit and he reads it.  (Normal case)
// 2)  We want to STALL the endpoint, but the host is done sending all of the data from the command.
//       In this case, we cannot tell the host about the STALL.
// 3)  The host is in the process of sending an OUT packet when we get here.
// 
void stallEP2OUT()
{

   if (!dataTransferLen)
      return;

   FIFORESET = bmNAKALL;         // NACK all xfers from the host.
   // Wait one packet time -- 50uS at full-speed, 10us at high-speed
   {
      BYTE count;
      BYTE i;
   
      if (EZUSB_HIGHSPEED())
         count = 10;
      else
         count = 50;
      for (; count; count--)
         i = halfKBuffer[0];      
   }

   {
      // Check to see if stall is needed.  If it is, STALL the endpoint.
      // If we have already received all of the data for the command, STALLing the endpoint
      // will only cause the NEXT command to fail.
      WORD x;
   
      if (EP2468STAT & bmEP2EMPTY)
         x = EP2FIFOBCL + (EP2FIFOBCH << 8);
      else
         x = EP2FIFOBCL + (EP2FIFOBCH << 8) + EP2BC;
   
      if (dataTransferLen > x)     
         {
         EP2CS |= bmEPSTALL;
         }
   }
   
   FIFORESET = 0;         // Clear the NAKALL bit.
}   

// This function pulls common information out of the CBW
void processCBWHeader()
{
   currentState = RECEIVED_CBW;     // This will prevent us from processing CBWs in the ISR.

   // Save the tag for use in the response
   cbwTagLow = *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG));
   cbwTagHi =  *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG+2));

   // Get the length (convert from little endian)
   *(((BYTE *) &dataTransferLen)+3) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[0];  // "Residue"
   *(((BYTE *) &dataTransferLen)+2) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[1];  // "Residue"
   *(((BYTE *) &dataTransferLen)+1) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[2];  // "Residue"
   *(((BYTE *) &dataTransferLen)+0) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[3];  // "Residue"

   directionIn = EP2FIFOBUF[CBW_FLAGS] & 0x80;
}

void processCBW()
{
   BYTE CbwLun;

   CbwLun = EP2FIFOBUF[CBW_LUN];

   #if DEVICE_TYPE_IS_IDE
   if (attemptFastRead)
   {
      if (CbwLun == currentLunNum  && !(mymemcmpa(prevCmd,&EP2FIFOBUF[0x0F],10+1)))
      {
         BYTE status;

         attemptFastRead = 0;
         status = fastReadComplete();
         // Save the tag for use in the response
         cbwTagLow = *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG));
         cbwTagHi =  *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG+2));

         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         sendUSBS(status);
         currentState = WAIT_FOR_CBW;
         return;
      }
      else
      {
         // switch the EP back to manual mode and drop through to normal processing
         EP6Manual();
         attemptFastRead = 0;
      }
   }
   else if (attemptFastWrite)
   {
      if (CbwLun == currentLunNum  && !(mymemcmpa(prevCmd,&EP2FIFOBUF[0x0F],10+1)))
      {
         BYTE status;

         attemptFastWrite = 0;

         // Save the tag for use in the response
         cbwTagLow = *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG));
         cbwTagHi =  *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG+2));

         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     

         status = fastWriteComplete();
         sendUSBS(status);
         currentState = WAIT_FOR_CBW;
         return;
      }
      else
      {
         // switch the EP back to manual mode and drop through to normal processing
         EP2Manual();
         attemptFastWrite = 0;
      }
   }
   else 
   #endif // DEVICE_TYPE_IS_IDE
      if (attemptFastScsi)
      {
      attemptFastScsi = 0;

⌨️ 快捷键说明

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