📄 fw.c
字号:
//-----------------------------------------------------------------------------
// 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 + -