📄 periph.c
字号:
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
{
// check to see if there is any data in our OUT endpoint. If there is,
// do a fifo reset before sending the CSW. How could this happen? If we
// stalled this CBW, it is possible that the host sent us data after the
// the CBW.
if (!(EP2CS & bmEPEMPTY))
{
ResetAndArmEp2();
}
// Fill the buffer & send the data back to the host
EP8FIFOBUF[0] = 'U'; // Believe it or not, this is pretty efficient!
EP8FIFOBUF[1] = 'S';
EP8FIFOBUF[2] = 'B';
EP8FIFOBUF[3] = 'S';
*((WORD volatile xdata*)(EP8FIFOBUF+CBW_TAG)) = cbwTagLow;
*((WORD volatile xdata*)(EP8FIFOBUF+CBW_TAG+2)) = cbwTagHi;
// have to store LSB first
EP8FIFOBUF[8+0] = ((BYTE *)&dataTransferLen)[3]; // "Residue"
EP8FIFOBUF[8+1] = ((BYTE *)&dataTransferLen)[2]; // "Residue"
EP8FIFOBUF[8+2] = ((BYTE *)&dataTransferLen)[1]; // "Residue"
EP8FIFOBUF[8+3] = ((BYTE *)&dataTransferLen)[0]; // "Residue"
*((BYTE xdata *) (EP8FIFOBUF+12)) = passOrFail; // Status
EP8BCH = 0;
EP8BCL = 13;
done = 1;
}
}
}
void failedIn()
{
// Stall if the host is still expecting data. Make sure
// endpoint is empty before doing the stall.
if (dataTransferLen /*&& !bShortPacketSent*/)
{
while( !(EP8CS & bmEPEMPTY) )
;
//EP8BCH = 0; // Terminate with NULL packet, not STALL.
//EP8BCL = 0;
EP8CS = bmEPSTALL; // TPM
}
}
// Read data from the drive
// Issues repeated calls to readPIO16 to pull in multiple blocks
// of data from the drive
// Returns amount of data reported by drive else returns 0
WORD readPIO16toXdata(char addr, char xdata *inbuffer, WORD count, bit ignoreDriveLen)
{
WORD driveDataLen = 0;
WORD saveDriveDataLen;
BYTE driveStatus;
WORD timeout = PROCESS_CBW_TIMEOUT_RELOAD;
WORD i;
for (driveStatus = 0; !(driveStatus & ATAPI_STATUS_DRQ_BIT) && (timeout-- > 0); )
driveStatus = readATAPI_STATUS_REG();
if (!timeout)
return(count);
if (timeout == 0xffff)
return(0);
if (ignoreDriveLen)
{
count = saveDriveDataLen = ATA_SECTOR_SIZE;
driveDataLen = 0;
}
if (scsi)
{
saveDriveDataLen = driveDataLen = getDriveDataLen();
count = min(count, driveDataLen);
}
else
{
saveDriveDataLen = driveDataLen = ATA_SECTOR_SIZE;
count = min(count, driveDataLen);
driveDataLen -= count;
}
for (i=0; i<count; i+=2)
{
((WORD*)inbuffer)[0] = readWordPIO8(addr);
inbuffer +=2;
}
// while (count)
// {
// readLen = min(count, 0x200); // Read and write routines are limited to one USB buffer size
// readPIO16(addr, EP8FIFOBUF, readLen);
// mymemmovexx(inbuffer, EP8FIFOBUF, readLen);
// count -= readLen;
// inbuffer += readLen;
// }
// For IDE, must empty the buffer after the relavent data has been read.
if (!scsi)
while (driveDataLen)
{
readPIO16(addr, 2);
driveDataLen -= 2;
}
return(saveDriveDataLen);
}
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++;
}
}
// 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()
{
int timeout;
// Make sure the drive has data ready for us
for (timeout = PROCESS_CBW_TIMEOUT_RELOAD;
timeout && IE0;
timeout--)
;
// Clear the interrupt source
readATAPI_STATUS_REG();
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
{
SetupCommand();
EZUSB_IRQ_CLEAR();
INT2CLR = bmSUDAV; // Clear SUDAV IRQ
}
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
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 = TRUE;
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -