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

📄 periph.c

📁 cy68013a USB2.0 highspeed mass storage source code
💻 C
📖 第 1 页 / 共 3 页
字号:
   // Reference Manual for more information
   // Set the stretch to 5
   CKCON = (CKCON&(~bmSTRETCH)) | 5;

   FIFORESET = 2;

   // we're quad-buffered, so we need to arm EP2 four times
   EP2BCL = 0x80;
   EP2BCL = 0x80;
   EP2BCL = 0x80;
   EP2BCL = 0x80;

   // Reset the stretch to 0
   CKCON = (CKCON&(~bmSTRETCH)) | FW_STRETCH_VALUE;
}

// check for tri-state signal on WAKEUP pin
// If the tri-state pin is set, disconnect and sleep until we have control of the bus again.
// if the pin is not set, 
void checkATAEnable()
{
      WAKEUPCS = 0x45;
      if ((WAKEUPCS & 0x40) || (!bNewAt2pinout && !VBUS_PRESENT))     // check VBUS and old part's VBUS detector
         {
         #if STANDBY_IMMEDIATE
         WORD i;
         #endif

         // Disconnect
         USBCS |= bmDISCON;
  
         // Standby Immediate means that we MUST drive the bus in all modes.
         // Turn it on even though we may have the tristate flag set too.
         // Once we're driving the bus and disconnected, we're done.  Return so that the 
         // background sleep code can send the standby command.
         #if STANDBY_IMMEDIATE
            driveATABus();
   
            //////////////////////////////////////////////////
            // Special purpose power-saving code.
            //
            // Expected conditions:  
            //     Self-powered, no bus-sharing, single IDE device
            //
            // This code will wait 500ms 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 < 100; i++)
               {
               EZUSB_Delay(1);
               if ((USBIRQ & bmSOF) && !VBUS_PRESENT)
                   break;
               }
   
            if (!((USBIRQ & bmSOF) && !VBUS_PRESENT))
               {
               standbyImmediate();
               }
   
            while (!VBUS_PRESENT)
               ;
      
            // Now that we're done waiting for WAKEUP# exclusively, make sure we wake up on D+ too!
            WAKEUPCS = 0x45;
      
            EZUSB_Delay(30);       // Switch debounce time -- It's okay to use EZUSB_Delay here because we will never return to any version that we may have interrupted.
            softReset();
  
         #else

            abortGPIF();
      
            // Reset the FIFOs
            FIFORESET = 6;
            ResetAndArmEp2();
   
            if (bATA_EN || (!bNewAt2pinout && (WAKEUPCS & 0x40)))
               triStateATABus();
      
            // Just sit here until we are re-enabled.
            EA = 0;  // In case we have higher priority interrupts
            EZUSB_Delay(30);       // Switch debounce time -- It's okay to use EZUSB_Delay here because we will never return to any version that we may have interrupted.
      
            // New pinout - Now that we're just waiting for WAKEUP# to go high, set polarity to active high, enable ONLY that wakeup source and sleep
            // Old pinout - WAKEUP = ATA_EN, PA6 = VBUS_PRESENT.  If we're here due to WAKEUP, go to sleep.  If not we must stay awake.
            if (bNewAt2pinout || (WAKEUPCS & 0x40))
               {
               WAKEUPCS = bmWU | bmWUPOL | bmWUEN;  // 0x51
               EZUSB_Susp();                        // Place processor in idle mode.
               }
            else
               {
               while (!VBUS_PRESENT)
                  ;
               }
      
            // Some designs use this signal to swap drives.  Force drive ID on restart.
            if (bSEARCH_ATA_ON_WAKEUP)
               deviceCount = 0x80;
   
            // Now that we're done waiting for WAKEUP# exclusively, make sure we wake up on D+ too!
            WAKEUPCS = 0x45;
      
            EZUSB_Delay(30);       // Switch debounce time -- It's okay to use EZUSB_Delay here because we will never return to any version that we may have interrupted.
            softReset();
         #endif
         }
      else
         // Turn on the bus for non-bus-powered drives here.  Bus-powered drives will be turned on 
         // in the background after the bus is turned on.
         if (!VBUS_POWERED)
            {
            driveATABus();
            if (deviceCount == 1 || deviceCount == 2)
               USBCS &= ~bmDISCON;  // Connect to USB if we've completed drive ID.
            }

}


BYTE checkCBW()
{
   // Check for "USBC"
   if (EP2FIFOBUF[0] != 'U' ||
       EP2FIFOBUF[1] != 'S' ||
       EP2FIFOBUF[2] != 'B' ||
       EP2FIFOBUF[3] != 'C')
      {
      return(USBS_FAILED);
      }
   else
      {
      if (EP2BC != 31)
          // Error -- Stall the endpoint
         return(USBS_FAILED);
      }
   return(USBS_PASSED);
}

BYTE processConfigCBCommand() 
{
   BYTE addr = EP2FIFOBUF[CONFIG_CB_EEPROM_ADDR_LSB];
   BYTE ConfigCBSubCommand = EP2FIFOBUF[CONFIG_CB_SUBCOMMAND_OFFSET];

   switch (ConfigCBSubCommand)
      {
      case CONFIG_CB_SUBCOMMAND_EEPROM_RW:
         {
         WORD len;

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

         if (!directionIn)
            {
            if (EEPROMWrite(dataTransferLenLSW, CONFIG_SPACE_START))
               {
               stallEP2OUT();
               return(USBS_FAILED);
               }
            }
         else
            {
            while (dataTransferLenLSW)
               {
               len = min(dataTransferLenLSW,wPacketSize);

               // wait for an available EP buffer
               while (EP6CS & bmEPFULL)
                  ;
               if(EEPROMRead(addr+CONFIG_SPACE_START,len,EP6FIFOBUF))
                  {
                  failedIn();
                  return(USBS_FAILED);
                  }
               EP6BCH = MSB(len);
               EP6BCL = LSB(len);
               dataTransferLenLSW -= len;
               addr += wPacketSize;
               }
            }
         return(USBS_PASSED);
         }
      case CONFIG_CB_SUBCOMMAND_MFG:
         {
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;

         /**************************************************************************
         Byte	Bit(s)	Test / 3-State Control Register Name
         0	    0	       Reserved
         0	    3:1	DA[2:0]
         0	    5:4	CS#[1:0]
         0	    6	VBUS
         0	    7	ARESET#
   
         1	    0	NDIOW
         1	    1	NDIOR
         1	    2	NDMACK
         1	    3 IORDY
         1      4 DMARQ
         1      5 ATA_EN
         1      6 MFG_SEL
         1	    7	DD[15:0] 3-State  Active hi 3-state buffer enable for ATA data bus.
   
         2	    7:0	DD[7:0]
         3	    7:0	DD[15:8]
         4	    7:0	Reserved
         5	    7:0	Reserved
         6	    7:0	Reserved
         **************************************************************************/
         if (directionIn)
            {
            OEA = 0x00;       // Allow us to read the pins, not drive 'em.
            waitForInBuffer();
            AUTOPTRL2 = LSB(EP6FIFOBUF);
            XAUTODAT2 = IOA;     // Byte 0
            XAUTODAT2 = (GPIFIDLECTL & 0x7)     // Bits 0-2 
               | ((GPIFREADYSTAT & 0x3) << 3)   // Bits 3-4
               | ((WAKEUPCS & 0x40) >> 1)       // Bit 5
               | ((BYTE)mfgMode << 6)           // Bit 6
               | (OEB & 0x80);                  // Bit 7
            XAUTODAT2 = IOB;
            XAUTODAT2 = IOD;
            EP6BCH = 0;
            EP6BCL = dataTransferLenLSW;
            }
         else
            {
            // Wait for host to send data
            while(EP2CS & bmEPEMPTY)       
                ;
      
            IOA = EP2FIFOBUF[0];
            OEA = PORTA_OE;            // PORTA is all output except PA.6(VBUS) and PA.0 (IRQ)
            PORTACFG = 0;          // Turn off alternate function
            GPIFIDLECTL = 0x70 | (EP2FIFOBUF[1] & 0x7);
   
            IFCONFIG &= ~3;   // Turn off GPIF control of ports B and D.
   
            if (EP2FIFOBUF[1] & 0x80)
               {
               IOB = EP2FIFOBUF[2];
               IOD = EP2FIFOBUF[3];
               OEB = 0xff;
               OED = 0xff;
               }
            else
               {
               OEB = 0;
               OED = 0;
               }
   
            // Give up the buffer
            EP2BCL = 0x80; 
            }
         dataTransferLen = 0;
         return(USBS_PASSED);
         }
      // ATACB
      #if ATACB_ENABLE
      case CONFIG_CB_COMMAND:
         {
         return(processATACB());
         }
      #endif
      default:
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;

         if (dataTransferLen)
            {
            if (directionIn)
               failedIn();
            else
               stallEP2OUT();
            }

         return (USBS_FAILED);
      }   
}

void enterMfgMode()
{
   // Default hardware setup
   bATA_UDMA_ENABLE             = 1;
   bATAPI_UDMA_ENABLE           = 1;
   bWAIT_FOR_BUSY_BIT           = 0;
   bENABLE_WRITE_CACHE_MODE_PAGE= 0;

   bCOMPLIANCE_MODE             = 0;
   bSHORT_PACKET_BEFORE_STALL   = 1;
   bSRST_ENABLE                 = 1;
   bSKIP_PIN_RESET              = 1;

   bBUTTON_PINOUT               = 0;
   bATA_ENABLED                 = 1;
   bBIG_PACKAGE                 = 1;
   bATA_EN                      = 1;

   bNewAt2pinout                = 1;
   bHS_INDICATOR                = 0;
   bDRVPWRVLD_POLARITY          = 0;
   bDRVPWRVLD_ENABLE            = 0;      // CF!
   setDefaultConfig();

   mymemmovexx(halfKBuffer, (char xdata *) &DeviceDscr, (WORD)&DscrEndOffset);
   halfKBuffer[(BYTE) &IntrfcClassFullSpeedOffset] = 0xff;
   halfKBuffer[2 + halfKBuffer[(BYTE) &SerialNumberIndexOffset]*2-16] = 'M';
   bDRVPWRVLD_ENABLE = 0;     // Turn off CF
   ATA_ENABLED = 0;           // Turn off ATA
   mfgMode = 1;               // We can also go into mfg mode if RESET# is pulled low.  This is checked in initUSB after the ports have been configured.
}

void setDefaultConfig()
{
   // Default hardware setup
//   bATA_UDMA_ENABLE             = 1;
//   bATAPI_UDMA_ENABLE           = 1;
//   bWAIT_FOR_BUSY_BIT           = 0;
//   bENABLE_WRITE_CACHE_MODE_PAGE= 0;
//
//   bCOMPLIANCE_MODE             = 0;
//   bSHORT_PACKET_BEFORE_STALL   = 1;
//   bSRST_ENABLE                 = 1;
//   bSKIP_PIN_RESET              = 1;

//   bBUTTON_PINOUT               = 0;
//   bATA_ENABLED                 = 1;
//   bBIG_PACKAGE                 = 1;
//   bATA_EN                      = 1;

//   bNewAt2pinout                = 1;
//   bHS_INDICATOR                = 0;
//   bDRVPWRVLD_POLARITY          = 0;
//   bDRVPWRVLD_ENABLE            = 0;      // CF!


   // Default config
   mx2_config_data.Signature = AT2LP_EEPROM_SIGNATURE;
   mx2_config_data.ApmValue = 0;
   mx2_config_data.AtaInitTimeout = 0x80;
   mx2_config_data.UdmaConfig = 0xD4;
   mx2_config_data.PioConfig = 0x7;
   mx2_config_data.AtaCommand = CONFIG_CB_COMMAND;
   mx2_config_data.Lun0String = mx2_config_data.Lun1String = 0;
   mx2_config_data.GpioData = 0;
   mx2_config_data.GpioOE = 0;
   mx2_config_data.delayAfterReset = 0;   // 20ms chunks.  0 = 50 for backward compatibility.
   mx2_config_data.MiscConfig2 = 0;        
   miscConfig2 = 0;
}

void triStateATABus()
{
   
   // Data bus is already tristated between read/writes
   // Tri-state port A
   // Tristate GPIF CTL lines 
   GPIFCTLCFG = 0x80;   // 
   GPIFIDLECTL = 0;
   OEA = 0;
   OEC = PORTC_OE_SUSPEND;
   IOEShadow |= nPWR500;    // Turn off the CF power
   IOE = IOEShadow;
   OEE = PORTE_OE_SUSPEND | (mx2_config_data.GpioOE << 2);
}

void driveATABus()
{
   GPIFCTLCFG = 0x0;   // 
   GPIFIDLECTL = 0x77;  // x111x111 - CTL3 not enabled
                        // ||||||||_CTL0 = 1 during idle
                        // |||||||__CTL1 = 1 during idle
                        // ||||||___CTL2 = 1 during idle
                        // ||||_____CTL0 output enable
                        // |||______CTL1 output enable
                        // ||_______CTL2 output enable

   OEA = PORTA_OE;
   OEC = PORTC_OE;
   OEE = PORTE_OE | (mx2_config_data.GpioOE << 2);
   checkGPIOonPA3();
}

// When we are bus-powered, we have to tri-state the ATA bus 
// when we are powered off.  Otherwise power will leak
// through the ATA bus signals an mess up the startup.
void powerOff()
{
   IOEShadow |= nPWR500;    // Turn off the CF power
   IOE = IOEShadow;
   
   // If we're a bus-powered device, the ATA bus mus be floated during suspend.
   if(VBUS_POWERED)
      triStateATABus();
}

void powerOn()
{
   if (Configuration == 1)
      // "PWR500 will only be asserted if VBUSPWRD is asserted (or when we don't have a VBUSPWRD input)"
      if (VBUS_POWERED)
         {
         if (CF_DETECT_ || ejected || !bDRVPWRVLD_ENABLE)
            return;

         IOEShadow &= ~nPWR500;      // Turn on the CF power
         IOE = IOEShadow;
         driveATABus();        // Only manipulate the bus drivers if we're bus-powered.
         EZUSB_Delay(DELAY_AFTER_POWERUP);            // Wait for device to power up
         hardwareReset();
         EZUSB_Delay(90);            // Mitsumi CR-4808TE(CYSD007) is a good test for this number.
         }
}

// Get the sector count and prevCmd fields set up for the next command.
void fastSCSIStart()
{
   // Update the sector based on the command group (see spc 4.3.3 and 4.3.4)
   if ((prevCmd[0] & 0xe0) == 0xa0)    // 12 byte command
      *((unsigned long *) &prevCmd[2]) += *((unsigned long *) &prevCmd[6]);
   else if ((prevCmd[0] & 0xe0) == 0x20)    // 10 byte commands (0xa0, 0xb0)
      *((unsigned long *) &prevCmd[2]) += *((unsigned int *) &prevCmd[7]);
   else if ((prevCmd[0] & 0xe0) == 0x40)    // 10 byte commands (0xc0, 0xd0)
      *((unsigned long *) &prevCmd[2]) += *((unsigned int *) &prevCmd[7]);

   // get our saved transfer length and sector count from the previous transfer
   dataTransferLen = prevDataTransferLen;
}

⌨️ 快捷键说明

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