//-----------------------------------------------------------------------------
// 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 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
//-----------------------------------------------------------------------------
// Code
//-----------------------------------------------------------------------------
// Task dispatcher
// Send descriptor without using autopointer. The autopointer gets confused in several
// situations, one of which is a host request len > 0x2000.
//
// This routine also allows the descriptors to be shared between full and high speed by
// changing the endpoint sizes of EP2 and EP6 on the fly.
//
static void sendDescriptorL(BYTE code*dscr,BYTE len) {
BYTE l,j;
AUTOPTR1H = MSB(dscr);
AUTOPTR1L = LSB(dscr);
if (!SETUPDAT[7] && len>SETUPDAT[6]) len=SETUPDAT[6];
// endpoint 0 FIFO size is always 64, so limit each block
do{
l=len; if (l>64) l=64;
for (j=0; j<l;j++) EP0BUF[j]=XAUTODAT1; // possibly zero bytes
EP0BCL = l;
len-=l;
while (EP0CS&0x02) j=1; // wait while EP0OUT is busy; j=1: Fake optimizer of Keil C
}while (l==64); // repeat when packet was full
}
static void sendDescriptor(BYTE code*dscr) {
BYTE len=dscr[0];
if (dscr[1] == 0x02 || dscr[1] == 0x07) len = dscr[2]; // Config or Otherspeed descriptor: Take entire length (<256)
sendDescriptorL(dscr,len);
}
// Add a GPIO on PA3 in 56 pin package with new pinout when we're not bus powered
// Note that this routine DOES NOT exist in AT2LP
void checkGPIOonPA3()
{
if (!bBIG_PACKAGE && !VBUS_POWERED && bNewAt2pinout)
{
if (mx2_config_data.GpioOE & 0x80 )
OEA |= 1 << 3;
else
OEA &= ~(1 << 3);
PA3 = (mx2_config_data.GpioData & 0x80) >> 7;
}
}
// Device request parser
static void onSetup(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
BYTE bmRequestType=SETUPDAT[0];
BYTE bRequest=SETUPDAT[1];
BYTE wValueL=SETUPDAT[2];
BYTE wValueH=SETUPDAT[3];
BYTE wIndexL=SETUPDAT[4];
WORD wLength=SETUPDAT[6] | (SETUPDAT[7]<<8);
EP0BCH = 0; // Default to MSB of the length is 0
switch (bmRequestType) {
case 0x80: // In, Standard, Device
switch (bRequest) {
case 0x00: // *** Get Status (Device)
EP0BUF[0] = VBUSPWRD ? 0 : 1; // Bit 0 -- 1 = self-power, 0 = bus power
goto okay2; // Bit 1 -- remote wakeup enabled (0 for us)
case 0x06: // *** Get Descriptor
switch(wValueH) {
case 0x01: sendDescriptor(DeviceDscr); goto okay; // Device
case 0x06: // Device Qualifier
// if high-speed is disabled, we are supposed to STALL this request
if (!CT1) {sendDescriptor(DeviceQualDscr); goto okay;} // high-speed is enabled, return the device qualifier
break;
case 0x02: // Configuration
case 0x07: // Other Speed Configuration
((BYTE xdata*) FullSpeedConfigDscr)[1] = wValueH;
if (bBIG_PACKAGE) {
if (VBUSPWRD) {
((BYTE xdata*)FullSpeedConfigDscr)[7] &= ~(1 <<6); // Bit 6 -- 1 = self-power, 0 = bus power
((BYTE xdata*)FullSpeedConfigDscr)[8] = 500/2;
}else{
((BYTE xdata*)FullSpeedConfigDscr)[7] |= 1 <<6; // Bit 6 -- 1 = self-power, 0 = bus power
((BYTE xdata*)FullSpeedConfigDscr)[8] = 0;
}
}
{BYTE eplenL=64, eplenH=0;
if ((EZUSB_HIGHSPEED() && wValueH == 0x02) // GD_CONFIGURATION
|| (!EZUSB_HIGHSPEED() && wValueH != 0x02)) { // GD_OTHER_SPEED_CONFIGURATION
eplenL=0; eplenH=2;
}
((BYTE xdata*)FullSpeedConfigDscr)[9+9+4] = eplenL;
((BYTE xdata*)FullSpeedConfigDscr)[9+9+5] = eplenH;
((BYTE xdata*)FullSpeedConfigDscr)[9+9+7+4] = eplenL;
((BYTE xdata*)FullSpeedConfigDscr)[9+9+7+5] = eplenH;
}
sendDescriptor(FullSpeedConfigDscr); goto okay;
case 0x03: // String
switch (wValueL) {
case 0: sendDescriptor(StringDscr0); goto okay;
case 1: sendDescriptor(StringDscr1); goto okay;
case 2: sendDescriptor(StringDscr2); goto okay;
case 3: sendDescriptor(StringDscr3); goto okay;
}break;
}break;
case 0x08: // *** Get Configuration
EP0BUF[0] = Configuration;
goto okay1;
}break;
case 0xA1: // In, Class, Interface
switch (wIndexL) {
case 0x00: // Interface 0 = Mass Storage
switch (bRequest) {
case 0xFE: // SC_GET_MAX_LUN
if (wLength==1) { // Our interface number is hard coded (0) in DSCR.A51
if (b2LUN_SET_BY_EEPROM) EP0BUF[0] = 1;
else if (b1LUN_SET_BY_EEPROM) EP0BUF[0] = 0;
else EP0BUF[0] = deviceCount-1;
goto okay1;
}break;
}break;
#if CSM_SUPPORT
case 0x01:
switch (bRequest) {
case 0x01: // SC_GET_CHANNEL_SETTINGS
EP0BUF[0] = 1;
goto okay1;
case 0x06: // Get Descriptor
switch (wValueH) {
case 0x22: sendDescriptor(CSMIntrfcDscr); goto okay; //GD_CHANNEL_DESCRIPTOR
case 0x23: sendDescriptor(CSMIntrfcDscr); goto okay; //GD_CSM_DESCRIPTOR
case 0x24: sendDescriptor(CSMIntrfcDscr); goto okay; //GD_CSMV_DESCRIPTOR
}break;
case 0x21: // GD_CS_GENERAL_DESCRIPTOR
sendDescriptor(CSMGeneralDscr);
goto okay;
case 0x80: // SC_GET_UNIQUE_ID
sendDescriptorL(CSMSerial,IDE_ID_SERIAL_LEN);
goto okay;
}break;
#endif
#if HID_SUPPORT
case 0x02:
switch (bRequest) {
case 0x06: // Get Descriptor
switch (wValueH) {
case 0x21: sendDescriptor(HIDDscr); goto okay; // Get-Descriptor: HID
case 0x22: sendDescriptorL(HIDReportDscr,HIDReportDscrLen); goto okay; // Get-Descriptor: Report
}break;
}break
#endif
}break;
case 0x81: // In, Standard, Interface
switch (bRequest) {
case 0x00: // *** Get Status (Interface)
EP0BUF[0] = 0;
goto okay2;
case 0x0A: // *** Get Interface
EP0BUF[0] = AlternateSetting;
goto okay1;
}break;
case 0x01: // Out, Standard, Interface
switch (bRequest) {
case 0x0B: // *** Set Interface
// From USB 2.0 spec 9.4.5
// The Halt feature is reset to zero after either a SetConfiguration() or SetInterface() request even if the
// requested configuration or interface is the same as the current configuration or interface.
EP2CS = 0; // Clear stall bit
EP6CS = 0;
EP1INCS = 0;
// Clear Data Toggles.
TOGCTL = 0x2; // Reset data toggle for EP2
TOGCTL = 0x22;
TOGCTL = 0x16; // Reset data toggle for EP6
TOGCTL = 0x36;
TOGCTL = 0x11; // Reset data toggle for EP1
TOGCTL = 0x31;
AlternateSetting = wValueL;
goto okay;
}break;
case 0x00: // Out, Standard, Device
switch (bRequest) {
case 0x03: // *** Set Feature
switch (wValueL) {
case 0x02: goto okay;
// 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;
case 0x09: // *** Set Configuration
// From USB 2.0 spec 9.4.5
// The Halt feature is reset to zero after either a SetConfiguration() or SetInterface() request even if the
// requested configuration or interface is the same as the current configuration or interface.
EP2CS = 0; // Clear stall bit
EP6CS = 0;
EP1INCS = 0;
Configuration = wValueL;
// compliance code
if (!Configuration && VBUS_POWERED) powerOff();
goto okay;
}break;
case 0x82: // In, Standard, Endpoint
switch (bRequest) {
case 0x00: // *** Get Status (Endpoint)
switch (wIndexL) {
case 0x02: EP0BUF[0] = EP2CS & 0x01; goto okay2;
case 0x86: EP0BUF[0] = EP6CS & 0x01; goto okay2;
case 0x81: EP0BUF[0] = EP1INCS & 0x01; goto okay2;
case 0x00: EP0BUF[0] = 0; goto okay2;
}break;
}break;
case 0x02: // Out, Standard, Endpoint
switch (bRequest) {
case 0x01: // *** Clear Feature (Endpoint)
switch (wValueL) {
case 0x00: // ** STALL
switch (wIndexL) {
// do not clear endpoint STALLs if we received an invalid CBW.
// The BOT MSC Spec says we must stay STALL'd until we get reset
case 0x2:
ResetAndArmEp2();
TOGCTL = 0x2;
TOGCTL = 0x22; // reset data toggle
EP2CS = 0; // Clear stall bit
goto okay;
case 0x86:
TOGCTL = 0x16;
TOGCTL = 0x36; // reset data toggle
EP6CS = 0; // Clear stall bit
goto okay;
case 0x81:
TOGCTL = 0x11;
TOGCTL = 0x31; // reset data toggle
EP1INCS = 0; // Clear stall bit
goto okay;
}break;
}break;
case 0x03: // *** Set Feature (Endpoint)
switch (wValueL) {
case 0x00: // ** STALL
switch (wIndexL) {
case 0x02: EP2CS = 0x01; goto okay; // Set stall bit
case 0x86: EP6CS = 0x01; goto okay;
case 0x81: EP1INCS = 0x01; goto okay;
}break;
}break;
}break;
case 0x21: // Out, Class, Interface
switch (wIndexL) {
case 0x00: // Interface 0 = Mass Storage
switch (bRequest) {
case 0xFF: // SC_MASS_STORAGE_RESET (wValueL==0)
// Verify that the command is actually a MS reset command sent to the proper interface
if (!wLength) { // 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 = 0x01; // Clear SUDAV IRQ
phaseErrorState = 0;
// force a soft reset after the iret.
EA = 0;
softReset();
goto okay;
}break;
}break;
#if CSM_SUPPORT
case 0x01: // Interface 1 = CSM
switch(bRequest) {
case 0x02: // SC_SET_CHANNEL_SETTINGS
goto okay;
}break;
#endif
#if HID_SUPPORT
case 0x02:
switch(bRequest) {
case 0x09: // HID_SET_REPORT
EP0BCH = 0;
EP0BCL = 0; // Clear bytecount to allow new data in; also stops NAKing
while(EP0CS & bmEPBUSY); // wait for the report
report[0] = EP0BUF[0];
report[1] = EP0BUF[1];
receivedReport_Flag = TRUE;
goto okay;
case 0x0A: // HID_SET_IDLE
goto okay;
}break;
#endif
}break;
case 040: // Out, Vendor, Device
switch (bRequest) {
case 0x01: // Load (write) config data
if (!wValueL || wValueL==2) { // 0 = Write config bytes, 2 = Write EEPROM AND config bytes
EP0BCH = 0;
EP0BCL = 0; // Clear bytecount to allow new data in; also stops NAKing
while (EP0CS & 0x01);
if (wIndexL < sizeof(MX2_CONFIG_DATA))
mymemmovexx((BYTE xdata*)&mx2_config_data + wIndexL, EP0BUF, min(sizeof(MX2_CONFIG_DATA)-wIndexL, wLength));
if (wIndexL + wLength >= sizeof(MX2_CONFIG_DATA))
mymemmovexx(halfKBuffer, EP0BUF, EP0BCL-max(0,sizeof(MX2_CONFIG_DATA)-wIndexL));
if (wValueL==2) { // Write EEPROM too
BYTE i;
for (i=0; i< EP0BCL; i+= EEPROM_PAGE_SIZE)
EEPROMWriteBlock(wIndexL+i+CONFIG_SPACE_START, EP0BUF+i, min(EEPROM_PAGE_SIZE, EP0BCL-i));
}
wLength -= EP0BCL;
wIndexL += EP0BCL;
EP0BCL = 0;
while (wLength) {
while (EP0CS & 0x01);
mymemmovexx(halfKBuffer + wIndexL - sizeof(MX2_CONFIG_DATA), EP0BUF, EP0BCL);
if (wValueL==2) { // Write EEPROM too
BYTE i;
for (i=0; i< EP0BCL; i+=EEPROM_PAGE_SIZE)
EEPROMWriteBlock(wIndexL+i+CONFIG_SPACE_START, EP0BUF+i, EEPROM_PAGE_SIZE);
}
wLength -= EP0BCL;
wIndexL += EP0BCL;
EP0BCL = 0;
}
IOEShadow = (mx2_config_data.GpioData << 2) | (IOEShadow & 3);
IOE = IOEShadow;
OEE = mx2_config_data.GpioOE << 2 | (OEE & 3);
checkGPIOonPA3();
goto okay;
}break;
}break;
case 0xC0: // In, Vendor, Device
switch (bRequest) {
case 0x02: // Read config data
if (wValueL==2) { // Read EEPROM
while (wLength) {
BYTE l=64; if (wLength<64) l=wLength;
while (EP0CS & 0x01);
EEPROMRead(wIndexL+CONFIG_SPACE_START, l, (BYTE xdata *) EP0BUF);
EP0BCL = l;
wLength -= l;
wIndexL += l;
}
goto okay;
}else{
BYTE l=64; if (wLength<64) l=wLength;
if (wIndexL < sizeof(MX2_CONFIG_DATA))
mymemmovexx(EP0BUF, (BYTE xdata *) &mx2_config_data + wIndexL, min(sizeof(MX2_CONFIG_DATA)-wIndexL, wLength));
if (wIndexL >= sizeof(MX2_CONFIG_DATA))
mymemmovexx(EP0BUF, halfKBuffer + wIndexL, l);
else // transfer is split between the two sections
mymemmovexx(EP0BUF + max(sizeof(MX2_CONFIG_DATA)-wIndexL, 0),
halfKBuffer,
64-max(0,sizeof(MX2_CONFIG_DATA)-wIndexL));
EP0BCL = l;
wLength -= l;
wIndexL += l;
while (wLength) {
while (EP0CS&0x01);
l=64; if (wLength<64) l=wLength;
mymemmovexx(EP0BUF, halfKBuffer + wIndexL - sizeof(MX2_CONFIG_DATA),l);
EP0BCL = l;
wLength -= l;
wIndexL += l;
}
}goto okay;
}break;
}// switch (bmRequestType)
EP0CS = 0x01; // stall EP0;
return;
okay2:
EP0BUF[1] = 0;
EP0BCL = 2;
goto okay;
okay1:
EP0BCL = 1;
okay:
EP0CS = 0x80; // Acknowledge handshake phase of device request
}
// Wake-up interrupt handler
void resume_isr(void) interrupt WKUP_VECT
{
EZUSB_CLEAR_RSMIRQ();
}
static void onUres(void) {
// whenever we get a USB reset, we should revert to full speed mode
wPacketSize = FS_BULK_PACKET_SIZE;
EP6FIFOPFH = 0x80;
EP6FIFOPFL = 0x60;
EP6AUTOINLENH = MSB(wPacketSize);
EP6AUTOINLENL = LSB(wPacketSize);
abortGPIF();
FIFORESET = 6;
ResetAndArmEp2();
// clear the stall and busy bits that may be set
EP2CS = 0; // set EP2OUT to empty and clear stall
EP6CS = 0; // set EP6OUT to empty and clear stall
// Initialize USB variables to make chapter 9 happy
AlternateSetting = Configuration = 0;
if (currentState != UNCONFIGURED) {
EA = 0;
// force a soft reset after the iret.
softReset();
}
}
static void onHighspeed(void) {
if (USBCS&0x80) { // HiSpeed?
WORD CT4Count = 272;
// Look for CT4.3 (JK activity) inactive for 500us
// This loop was hand-counted to be 22/12 = 1.8us long, so 272 iterations are 500us
// With the CT2 check, this loop is 31/12 = 193 iterations are 500us
while(CT2 != 0xd && --CT4Count) {
if (CT4 & 8) CT4Count = 193;
}
if (CT2 == 0xc) { // If we timed out in state C, bump the state machine to state D
CT1 = 2;
SYNCDELAY;
CT2 = 0xd;
SYNCDELAY;
CT1 = 0;
}
wPacketSize = HS_BULK_PACKET_SIZE;
EP6FIFOPFH = 0x99; // Allow the FIFO to hold 3 full packets + 0x190 bytes.
EP6FIFOPFL = 0x90;
}
EP6AUTOINLENH = MSB(wPacketSize);
EP6AUTOINLENL = LSB(wPacketSize);
}
void main(void) {
BYTE usbirq;
MPAGE=0xE6; // let compiler access xdata registers at 0xE6xx via R0 or R1
USBCS=0x02; // set the renum bit so that firmware handles SETUP transfers.
// 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();
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 = 0x80;
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 = 0x02; // 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 = 0x02;
if (!mfgMode) ATAInit();
// Reconnect to USB. This line has no effect in a system that's already connected.
USBCS = 0x02;
CKCON = CKCON&0xF8; // 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 = 0x06;
USBIRQ = 0x02;
EZUSB_Delay(3);
if (USBIRQ & 0x02) Sleep = 0;
}
// FIFORESET = 0; // turn off nakall
// Task Dispatcher
for(;;) { // 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 = 0x06; // NOSYNOF and RENUM
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 = 0xC5;
if (WAKEUPCS & 0x40) WAKEUPCS = WAKEUPCS = 0xD5;
#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 = 0xC7; // No CF, wake on low
else WAKEUPCS = 0xE7; // CF there, wake on high
}else WAKEUPCS = 0xC5;
#endif
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 = (BYTE)(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();
} // endif (sleep)
// Poll for USB activity
usbirq=USBIRQ=USBIRQ; // clear and save all requests
if (usbirq&0x08) { // 3 ms USB inactivity seen
Sleep = TRUE;
}
if (usbirq&0x20) { // Switch to high-speed done?
onHighspeed();
}
if (usbirq&0x10) { // USB RESET seen
onUres();
}
if (usbirq&0x01) { // SUDAV = EP0 Setup Data Available
onSetup();
}
TD_Poll();
} // End while-forever loop
}
| Detected encoding: ASCII (7 bit) | 2
|