📄 periph.c
字号:
// switch to PIO0
else
{
mymemmovexx(&GPIF_WAVE_DATA, (BYTE xdata *) WaveDataPioUDMA, 8 + 4);
mymemmovexx(&(GPIF_WAVE_DATA) + 32, (BYTE xdata *) WaveDataPioUDMA+32, 8 + 4);
}
}
}
}
// Our personal "firmware update" command
if (EP2FIFOBUF[0xf] == 0xfb && !(EP2FIFOBUF[CBW_FLAGS] & CBW_FLAGS_DIR_BIT))
{
// relinquish control of the bulk buffer occupied by the CBW
EP2BCL = 0x80;
// Write the entire EEPROM
EEPROMWrite(dataTransferLenLSW);
sendUSBS(USBS_PASSED);
}
else if (directionIn || !dataTransferLen)
{
currentState = RECEIVED_IN_CMD;
if (bScsi)
sendUSBS(generalSCSIInCommand());
else
sendUSBS(generalIDEInCommand());
}
else
{
currentState = RECEIVED_OUT_CMD;
if (bScsi)
sendUSBS(generalSCSIOutCommand());
else
sendUSBS(generalIDEOutCommand());
}
currentState = WAIT_FOR_CBW;
}
void sendUSBS(BYTE passOrFail)
{
bit done = 0;
// generalIDEx/generalSCSIx command returns here with passOrFail status bit
// which is re-cast as the error byte of CSW
while (!done)
{
if( (!(EP8CS & bmEPFULL)) && (!(EP8CS & bmEPSTALL))) // Wait for an available buffer
{
// Eliminate any data in the OUT endpoint or FIFO
// This can happen in the Ho > Dn and Ho > Do cases.
ResetAndArmEp2();
// If we're in phase error, STALL the OUT endpoint to make sure the host resets us (and the drive)
if (passOrFail == USBS_PHASE_ERROR)
{
EP2CS = bmEPSTALL;
phaseErrorState = 1;
}
// Fill the buffer & send the data back to the host
AUTOPTRL2 = LSB(EP8FIFOBUF);
XAUTODAT2 = 'U'; // Believe it or not, this is pretty efficient!
XAUTODAT2 = 'S';
XAUTODAT2 = 'B';
XAUTODAT2 = 'S';
XAUTODAT2 = MSB(cbwTagLow);
XAUTODAT2 = LSB(cbwTagLow);
XAUTODAT2 = MSB(cbwTagHi);
XAUTODAT2 = LSB(cbwTagHi);
// have to store LSB first
XAUTODAT2 = ((BYTE *)&dataTransferLen)[3]; // "Residue"
XAUTODAT2 = ((BYTE *)&dataTransferLen)[2]; // "Residue"
XAUTODAT2 = ((BYTE *)&dataTransferLen)[1]; // "Residue"
XAUTODAT2 = ((BYTE *)&dataTransferLen)[0]; // "Residue"
XAUTODAT2 = passOrFail; // Status
EP8BCH = 0;
EP8BCL = 13;
done = 1;
}
}
// Stall the IN endpoint if we're in phase error state.
if (phaseErrorState)
{
while( !(EP8CS & bmEPEMPTY) )
;
EP8CS = bmEPSTALL;
}
}
void failedIn()
{
// Stall if the host is still expecting data. Make sure
// endpoint is empty before doing the stall.
if (dataTransferLen)
{
if (!bShortPacketSent && (SHORT_PACKET_BEFORE_STALL))
{
while( !(EP8CS & bmEPEMPTY) )
;
EP8BCH = 0; // Terminate with NULL packet, then STALL. This
EP8BCL = 0; // addresses an issue with the current EHCI driver (1/02)
}
while( !(EP8CS & bmEPEMPTY) )
;
EP8CS = bmEPSTALL; // TPM
}
}
bit waitForBusyBit()
{
BYTE driveStatus;
do
{
driveStatus = readATAPI_STATUS_REG();
}
while((driveStatus & (ATAPI_STATUS_BUSY_BIT))); // Do-while
// Some drives clear the busy bit asynchronously. Read the reg one more time to be sure.
driveStatus = readATAPI_STATUS_REG();
if ((driveStatus & ATAPI_STATUS_ERROR_BIT))
return(USBS_FAILED);
else
return(USBS_PASSED);
}
void mymemmovexx(BYTE xdata * dest, BYTE xdata * src, WORD len)
{
while (len--)
{
*dest++ = *src++;
}
}
void mymemmove(BYTE data * dest, BYTE data * src, BYTE len)
{
while (len--)
{
*dest++ = *src++;
}
}
// Wait for interrupt from the drive.
// Clears the interrupt source on the drive, the INT0 is level triggered, so it clears automagically .
//
// Returns:
// USBS_FAILED -- Timeout
bit waitForIntrq(BYTE timeoutEnable)
{
WORD timeoutCtr = PROCESS_CBW_TIMEOUT_RELOAD;
while (timeoutCtr)
{
#if REVC_4611_BOARD
WAKEUPCS = bmWU | bmDPEN; // Disable wakeup from the INTRQ pin. Only wake on D+
if (!(WAKEUPCS & 0x40))
break;
#else
if (IOA & 1)
break;
#endif
timeoutCtr -= timeoutEnable;
}
if (!timeoutCtr)
return(USBS_FAILED);
return(USBS_PASSED);
}
//-----------------------------------------------------------------------------
// USB Interrupt Handlers
// The following functions are called by the USB interrupt jump table.
//-----------------------------------------------------------------------------
// Setup Data Available Interrupt Handler
void ISR_Sudav(void) interrupt 0
{
EZUSB_IRQ_CLEAR();
INT2CLR = bmSUDAV; // Clear SUDAV IRQ
SetupCommand();
}
void ISR_Ures(void) interrupt 0
{
// whenever we get a USB reset, we should revert to full speed mode
pConfigDscr = pFullSpeedConfigDscr;
((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
pOtherConfigDscr = pHighSpeedConfigDscr;
((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;
wPacketSize = FS_BULK_PACKET_SIZE;
EP8FIFOPFH = 0x80;
EP8FIFOPFL = 0x60;
EP8AUTOINLENH = MSB(wPacketSize);
EP8AUTOINLENL = LSB(wPacketSize);
FIFORESET = 8;
ResetAndArmEp2();
// clear the stall and busy bits that may be set
EP2CS = 0; // set EP2OUT to empty and clear stall
EP8CS = 0; // set EP8OUT to empty and clear stall
// Initialize USB variables to make chapter 9 happy
AlternateSetting = Configuration = 0;
EZUSB_IRQ_CLEAR();
INT2CLR = bmURES; // Clear URES IRQ
if (currentState != UNCONFIGURED)
{
EA = 0;
// force a soft reset after the iret.
softReset();
}
}
void ISR_Susp(void) interrupt 0
{
Sleep = 1;
EZUSB_IRQ_CLEAR();
INT2CLR = bmSUSP;
}
void ISR_Highspeed(void) interrupt 0
{
if (EZUSB_HIGHSPEED())
{
pConfigDscr = pHighSpeedConfigDscr;
((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
pOtherConfigDscr = pFullSpeedConfigDscr;
((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;
wPacketSize = HS_BULK_PACKET_SIZE;
EP8FIFOPFH = 0x89;
EP8FIFOPFL = 0x90;
}
EP8AUTOINLENH = MSB(wPacketSize);
EP8AUTOINLENL = LSB(wPacketSize);
EZUSB_IRQ_CLEAR();
INT2CLR = bmHSGRANT;
}
#define FW_STRETCH_VALUE_5 5
void ResetAndArmEp2()
{
// adjust stretch to allow for synchronization delay. We are about
// to do several back to back writes to registers that require a
// synchroniztion delay. Increasing stretch allows us to meet
// the delay requirement. See "Synchroniztion Delay" in the Technical
// 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;
}
BYTE checkCBW()
{
// Check for "USBC"
if ( *((DWORD xdata *)EP2FIFOBUF) != *((DWORD xdata *) usbcString))
{
return(USBS_FAILED);
}
else
{
if (EP2BC != 31)
// Error -- Stall the endpoint
return(USBS_FAILED);
}
return(USBS_PASSED);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -