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

📄 ide.c

📁 cypress的usb接ata源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
            stallEP2OUT();
         
         return(USBS_FAILED);
         break;
   }
}   



void waitForInBuffer()
{
   while((EP8CS & bmEPFULL));   // Wait for an available buffer from the host

   return;
}   


static bit ideReadCommand(bit verify)
{   
   BYTE driveStatus;
   WORD sectorcount; 
   BYTE i; 
   WORD wordCtr;

   writePIO8(ATA_DRIVESEL_REG, 0xe0);
   if (waitForBusyBit() == USBS_FAILED)
   {
      // Oddly enough, an error bit is okay here.  It means that the LAST command failed, not this one.
      // A new command is required to clear many error conditions.
   }
        
   ((BYTE *) &dwLBA)[0] = EP2FIFOBUF[CBW_DATA_START+2];
   ((BYTE *) &dwLBA)[1] = EP2FIFOBUF[CBW_DATA_START+3];
   ((BYTE *) &dwLBA)[2] = EP2FIFOBUF[CBW_DATA_START+4];
   ((BYTE *) &dwLBA)[3] = EP2FIFOBUF[CBW_DATA_START+5];

   // relinquish control of the bulk buffer occupied by the CBW
   EP2BCL = 0x80;  

   // This loop breaks up the 32 bit length into 8 bits * sectors.
   // For example, a read of 0x10000 turns into 0x80 sectors.
   while (dataTransferLen)
   {
      dwLBAtoLBARegs();

      // First stuff the length register (number of sectors to read)
      if (dataTransferLenMSW & 0xfffe)
      {
         writePIO8(ATA_SECTOR_COUNT_REG, 1);     // if (bExtAddrSupport) we need to stuff the MSB
         writePIO8(ATA_SECTOR_COUNT_REG, 0);     // 0 means 256 blocks of 512 bytes -- Max drive xfer, max TC
         sectorcount = 0x100;
      }
      else
      {
         sectorcount = (dataTransferLenLSW + ATA_SECTOR_SIZE-1)/ATA_SECTOR_SIZE + (dataTransferLenMSW & 1) * 0x80;
         writePIO8(ATA_SECTOR_COUNT_REG, 0);      // for extended addressing
         writePIO8(ATA_SECTOR_COUNT_REG, sectorcount);       // divide len into blocks
      }
        
      dwLBA += sectorcount;
      
      if (!udmaMode || verify || (dataTransferLenLSW & 0x1ff))    // UDMA cannot handle sub-sector sized reads
      {
         // Execute the read command
         if (bExtAddrSupport)
            {
            if (verify)
               writePIO8(ATA_COMMAND_REG, ATA_COMMAND_VERIFY_10_EXT);
            else
               writePIO8(ATA_COMMAND_REG, ATA_COMMAND_READ_10_EXT);
            }
         else
            {
            if (verify)
               writePIO8(ATA_COMMAND_REG, ATA_COMMAND_VERIFY_10);
            else
               writePIO8(ATA_COMMAND_REG, ATA_COMMAND_READ_10);
            }

           
         // The verify command reads from the drive, but doesn't transfer data
         // to us.
         if (verify)     
         {
            if(waitForBusyBit() == USBS_FAILED)
               return(USBS_FAILED);
            else
               continue;
         }
   
         // set up for GPIF transfer - wordwide
         //EP8GPIFTCH = MSB(wPacketSize >> 1);     
         //EP8GPIFTCL = LSB(wPacketSize >> 1);
         
         while (sectorcount--)
         {
            // Wait for the drive to be non-busy and have either data or an error
            while (1)
            {
               driveStatus = readATAPI_STATUS_REG();                             
               if ((driveStatus & (ATAPI_STATUS_BUSY_BIT | ATAPI_STATUS_DRQ_BIT)) == ATAPI_STATUS_DRQ_BIT)
                  break;
               if (driveStatus & (ATAPI_STATUS_BUSY_BIT | ATAPI_STATUS_ERROR_BIT) == ATAPI_STATUS_ERROR_BIT)
                  break;
            }

            // If there's an error, the drive may still want to send us the data.
            if (driveStatus & ATAPI_STATUS_ERROR_BIT)
               {
               readPIO8(ATAPI_ERROR_REG);
               if (driveStatus & ATAPI_STATUS_DRQ_BIT)
                  for (wordCtr = 0; wordCtr < 0x100; wordCtr++)
                     readPIO8(ATAPI_DATA_REG);
               failedIn();
               return(USBS_FAILED);  
               }
            else
            {
               BYTE bLimit;
               WORD wThisPacketSize;

               if (wPacketSize == 0x40)
                  bLimit = 8;
               else 
                  bLimit = 1;
               for (i = 0; i < bLimit && dataTransferLen; i++)
               {
                  waitForInBuffer();

                  wThisPacketSize = min(wPacketSize, dataTransferLen);
                  readPIO16(ATAPI_DATA_REG, wThisPacketSize+1);
                  while (!gpifIdle())     // Wait for xfer to complete
                     ;
                  EP8BCH = MSB(wThisPacketSize);
                  EP8BCL = LSB(wThisPacketSize);
                  dataTransferLen -= wThisPacketSize; 
               }
            }
         }//while (sectorcount--)
      }
      else  // transfer is udma mode
      {
         initUdmaRead();
         if (bExtAddrSupport)
            writePIO8(ATAPI_COMMAND_REG, ATA_COMMAND_DMAREAD_RETRY_EXT);
         else
            writePIO8(ATAPI_COMMAND_REG, ATA_COMMAND_DMAREAD_RETRY);
         readUDMA((DWORD) sectorcount << 8);     // Words = sectors * 256
         driveStatus = readATAPI_STATUS_REG();
         if (driveStatus & ATAPI_STATUS_ERROR_BIT) 
            {
            if (readPIO8(ATAPI_ERROR_REG) & ATAPI_ERROR_ICRC_BIT)
               {
               sensePtr = senseCRCError;
               }
            // No need to do failedIn() -- All data is already xferred.
            return(USBS_FAILED);
            }

         // Two choices -- Either we're limited to 0x100 sectors, or limited to dataTransferLen.
         // BUGBUG -- No capability here to report Hi > Di.
         if (sectorcount == 0x100)
            dataTransferLenMSW -= 2;
         else
            dataTransferLen = 0;
      }
   }//while (dataTransferLen)
   
   return(USBS_PASSED);
}   

static bit ideWriteCommand()
{
   WORD savebc;
   BYTE driveStatus;
   WORD sectorcount; 
   BYTE i; 
    
   writePIO8(ATA_DRIVESEL_REG, 0xe0);
   if (waitForBusyBit() == USBS_FAILED)
   {
      // Oddly enough, an error bit is okay here.  It means that the LAST command failed, not this one.
      // A new command is required to clear many error conditions.
   }
    
   ((BYTE *) &dwLBA)[0] = EP2FIFOBUF[CBW_DATA_START+2];
   ((BYTE *) &dwLBA)[1] = EP2FIFOBUF[CBW_DATA_START+3];
   ((BYTE *) &dwLBA)[2] = EP2FIFOBUF[CBW_DATA_START+4];
   ((BYTE *) &dwLBA)[3] = EP2FIFOBUF[CBW_DATA_START+5];

   // relinquish control of the bulk buffer occupied by the CBW
   EP2BCL = 0x80;     
  
   // If there's no data length, just exit once we've freed the CBW buffer
   if (!dataTransferLen)
      return USBS_PASSED;

   // Send the command to the drive
   // This loop breaks up the 32 bit length into 8 bits * sectors.
   // For example, a read of 0x10000 turns into 0x80 sectors.
   while (dataTransferLen)
   {
      dwLBAtoLBARegs();      // Stuff the LBA registers
      
      // First stuff the length register (number of sectors to write)
      if (dataTransferLenMSW & 0xfffe)
      {
         writePIO8(ATA_SECTOR_COUNT_REG, 0x1);      // 1 for ext addr support 
         writePIO8(ATA_SECTOR_COUNT_REG, 0x0);      // 0 means 256 blocks of 512
         sectorcount = 0x100;
      }
      else
      {
         sectorcount = (dataTransferLenLSW+ATA_SECTOR_SIZE-1)/ATA_SECTOR_SIZE 
            + (dataTransferLenMSW & 1) * 0x80;
         writePIO8(ATA_SECTOR_COUNT_REG, 0);      // 0 for MSB of ext address
         writePIO8(ATA_SECTOR_COUNT_REG, sectorcount);       // divide len into blocks
      }
        
      dwLBA += sectorcount;

      if (udmaMode && !(dataTransferLenLSW & 0x1ff))
      {
         // Execute the write command
         if (bExtAddrSupport)
            writePIO8(ATA_COMMAND_REG, ATA_COMMAND_DMAWRITE_RETRY_EXT);
         else
            writePIO8(ATA_COMMAND_REG, ATA_COMMAND_DMAWRITE_RETRY);
         
         if (sectorcount == 0x100)
            writeUDMA((DWORD)0x10000);     // 64k Transfers = 128K
         else
            writeUDMA((dataTransferLen+1) >> 1);
         
         // Check status to clear interrupt.
         driveStatus = readATAPI_STATUS_REG();
         
         if (driveStatus & ATAPI_STATUS_ERROR_BIT) 
         {
            driveStatus = readPIO8(ATAPI_ERROR_REG);
            if (driveStatus & ATAPI_ERROR_ICRC_BIT)
            {
               sensePtr = senseCRCError;
            }
            return(USBS_FAILED);
         }
         else
         {
            if (sectorcount == 0x100)
               dataTransferLenMSW -= 2;
            else
               dataTransferLen = 0;
         }
      }
      else
      {
         // Execute the write command
         if (bExtAddrSupport)
            writePIO8(ATA_COMMAND_REG, ATA_COMMAND_WRITE_10_EXT);
         else
            writePIO8(ATA_COMMAND_REG, ATA_COMMAND_WRITE_10);
         
         while (sectorcount--)
         {
            BYTE limit;
   
            // Wait for the drive to be non-busy and have either data or an error
            while (1)
            {
               driveStatus = readATAPI_STATUS_REG();                             
               if ((driveStatus & (ATAPI_STATUS_BUSY_BIT | ATAPI_STATUS_DRQ_BIT)) == ATAPI_STATUS_DRQ_BIT)
                  break;
               if (driveStatus & (ATAPI_STATUS_BUSY_BIT | ATAPI_STATUS_ERROR_BIT) == ATAPI_STATUS_ERROR_BIT)
                  break;
            }
               
            // Normal case -- Got a sector.  Send it to the drive (in 8 chunks)
            if (wPacketSize == 0x40)
               limit = 8;
            else
               limit = 1;
   
            for (i = 0; i < limit; i++)
            {
               while(EP2CS & bmEPEMPTY);       // Wait for host to send data
               savebc = (EP2BCH << 8) | EP2BCL;
                   
               // Terminate xfer on receipt of short packet, otherwise drop
               // into streamlined case
               if (savebc < wPacketSize)
               {
                  EP2BCL = 0;
                  writePIO16(ATAPI_DATA_REG, savebc+1);     // Add 1 to allow odd xfers.
                  
                  dataTransferLen -= savebc + i * wPacketSize;
                  goto stopOnShortPacket;
               }
               else
               {
                  EP2BCL = 0;
                  writePIO16(ATAPI_DATA_REG, wPacketSize);
               }
            }
            dataTransferLen -= ATA_SECTOR_SIZE; // Returned a full sector.
         }  // while (sectorcount) 
      } // else (if udma)
   } // While (dataTransferLen)
    
stopOnShortPacket:

   if (driveStatus & ATAPI_STATUS_ERROR_BIT)
      return(USBS_FAILED);
   else
      return(USBS_PASSED);
}


// Don't have the ability to sense media (yet)
static bit checkForMedia()
{
   return(1);
}

void dwLBAtoLBARegs()      // Stuff the LBA registers
{
   writePIO8(ATA_DRIVESEL_REG, 0xe0);

   if (bExtAddrSupport)
      {
      writePIO8(ATA_LBA_LSB_REG,  ((BYTE *) &dwLBA)[0]);    // LBA (31:24)
      writePIO8(ATA_LBA_2SB_REG,  0);                       // LBA (39:32)
      writePIO8(ATA_LBA_MSB_REG,  0);                       // LBA (47:40)
      }

   writePIO8(ATA_LBA_LSB_REG,  ((BYTE *) &dwLBA)[3]);    // LBA (7:0)
   writePIO8(ATA_LBA_2SB_REG,  ((BYTE *) &dwLBA)[2]);    // LBA (15:8)
   writePIO8(ATA_LBA_MSB_REG,  ((BYTE *) &dwLBA)[1]);    // LBA (23:16)

   if (!bExtAddrSupport)
      {      
      writePIO8(ATA_DRIVESEL_REG, ((BYTE *) &dwLBA)[0] | 0xe0);
      }
}



/////////////////////////////////////////////////////////////////////////////////
#endif      // DEVICE_TYPE_IS_IDE
/////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -