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

📄 periph.c

📁 cypress的usb接ata源代码
💻 C
📖 第 1 页 / 共 2 页
字号:


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 + -