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

📄 ide.c

📁 cy68013a USB2.0 highspeed mass storage source code
💻 C
📖 第 1 页 / 共 4 页
字号:
               if (!bATA_ENABLED)
                  {
                  hardwareReset();
                  EZUSB_Delay(90);
                  }
               }
            EZUSB_Delay(30);

            ATAPIIdDevice();        // Identify the device
            initDriveAfterReset();  // Set up the device

            // move the drive identification stuff to LUN0.  Compact flash is always LUN0.
            LunBits[0] = ActiveLunBits;
            mymemmove((BYTE *)&DeviceConfigData[0],(BYTE *)&ActiveLunConfigData, sizeof(DEVICE_CONFIG_DATA));
            sensePtr = senseMediaChanged;
            noFlashMedia = 0;
            return (0);       // 0 will force the code through the error path.
            }
         return (1);
         }
      }
   else
      return(1);
}

WORD stuffLBAandSector()      // Stuff the LBA registers
{
   WORD sectorcount;

   writeATA_DRIVESEL_REG();
   waitForBusyBit();

   // First stuff the length register (number of sectors to read)
   if (wCmdSectorCount & 0xff00)
   {
      if (bExtAddrSupport)
         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 = wCmdSectorCount;
      if (bExtAddrSupport)
         writePIO8(ATA_SECTOR_COUNT_REG, 0);      // for extended addressing
      writePIO8(ATA_SECTOR_COUNT_REG, sectorcount);       // divide len into blocks
   }

   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 | ((BYTE)bMasterSlave << 4));
      }

   dwLBA += sectorcount;
   return sectorcount;
}


static void IDEPrepareForXfer()
{
   writeATA_DRIVESEL_REG();
   waitForBusyBit();
      // 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];

   ((BYTE *) &wCmdSectorCount)[0] = EP2FIFOBUF[CBW_DATA_START+7];
   ((BYTE *) &wCmdSectorCount)[1] = EP2FIFOBUF[CBW_DATA_START+8];

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

static BYTE loadSensePtrFromErrorRegister(bit readWrite)
{  
   BYTE error;

   error = readPIO8(ATAPI_ERROR_REG);
   if (!error)
      sensePtr = senseOk;
   else if (error & 0x80)       // CRC
      sensePtr = senseCRCError;
   else if (error & 0x02)  // No media present
      sensePtr = senseNoMedia;
   else if (error & 0x20)  // Media changed
      sensePtr = senseMediaChanged;
   else if (error & 0x10)  // Addr out of range 
      sensePtr = senseAddrNotFound;
   else if (error & 0x40)  // Uncorrectable read error / Write Protect
      {
      if (readWrite)
         sensePtr = senseReadError;
      else 
         sensePtr = senseWriteProtected;
      }
   else if (error & 0x08)  // Media change requested -- No good translation for this one.
      sensePtr = senseInvalidOpcode;
   else if (error & 0x04)  // Command not supported or CRC error or request out of range
      {
      if (readWrite)
         sensePtr = senseReadError;
      else 
         sensePtr = senseWriteFault;
      }
   else
      sensePtr = senseInvalidOpcode;

   return(error);
}

void EP2Manual()
{
   // cancel AUTO OUT mode, put IFCLK back to normal
   IFCONFIG = IFCONFIG_DEFAULT;
   EP2FIFOCFG = bmZEROLENIN | bmWORDWIDE;
}
void fastReadStart()
{
   // bump the LBA to what we think it will be
//   dwLBA += *((WORD *) &prevCmd[7]);

   // now put the bumped LBA in our previous CBW buffer for later comparison
   *((unsigned long *) &prevCmd[2]) = dwLBA;

   // get our saved transfer length from the previous transfer
   dataTransferLen = prevDataTransferLen;

   wCmdSectorCount = gSectorcount;        // Retrieve stored value from last command
   gSectorcount = stuffLBAandSector();

   initUdmaRead();

}

bit fastReadComplete()
{
   bit error;

   // this is basically from idereadcommand()
   while (dataTransferLen)
   {
//      initUdmaRead();
      error = 0;
      if (bExtAddrSupport)
         writePIO8(ATA_COMMAND_REG, ATA_COMMAND_DMAREAD_RETRY_EXT);
      else
         writePIO8(ATA_COMMAND_REG, ATA_COMMAND_DMAREAD_RETRY);
      prepUDMA(MSB(gSectorcount),LSB(gSectorcount),0);
      readUDMA();     // Words = sectors * 256
   
 
      // If there's anything left in the count regs, we've got a problem.  
      // We will have to STALL in the IN endpoint to stop the host.
      if (GPIFTCMSW || GPIFTCLSW)
      {
         if ((GPIFTCLSW & 0xff))      // Check for short packet already sent
            bShortPacketSent = 1;
         EP6Manual();
         failedIn();
         error = 1;        // Set an error flag here, but don't return yet.  Still have to load an error code.
      }

      if (readATAPI_STATUS_REG() & ATAPI_STATUS_ERROR_BIT) 
      {
         loadSensePtrFromErrorRegister(1);
         // No need to do failedIn() -- Already checked above to see that all data has been xferred.
         EP6Manual();
         return(USBS_FAILED);
      }
      // If the xfer failed but the drive didn't detect an error, ask the host to retry by setting a CRC error
      else if (error)
      {
         sensePtr = senseCRCError;
         EP6Manual();
         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 (gSectorcount == 0x100)
      {
         dataTransferLenMSW -= 2;
         gSectorcount = stuffLBAandSector();
      }
      else
         dataTransferLen = 0;
   }//while (dataTransferLen)

   attemptFastRead = 1;
   EP6Manual();
   return(USBS_PASSED);
}

void fastWriteStart()
{
   // now put the bumped LBA in our previous CBW buffer for later comparison
   *((unsigned long *) &prevCmd[2]) = dwLBA;

   // get our saved transfer length and sector count from the previous transfer
   dataTransferLen = prevDataTransferLen;
   wCmdSectorCount = gSectorcount; 

   gSectorcount = stuffLBAandSector();
}

bit fastWriteComplete()
{
   // We cannot do this until we process the CBW!  Don't move it into fastReadStart
   initUdmaWrite();

   // 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)
   {
      // Wait for drive non-busy before starting xfer
      while (readATAPI_ALT_STATUS_REG() & ATAPI_STATUS_BUSY_BIT)
         ;

      // Execute the write command
      if (bExtAddrSupport)
         writePIO8(ATA_COMMAND_REG, ATA_COMMAND_DMAWRITE_RETRY_EXT);
      else
         writePIO8(ATA_COMMAND_REG, ATA_COMMAND_DMAWRITE_RETRY);

      attemptFastWrite = 1;

      if (gSectorcount == 0x100)
         prepUDMA(0x1,00,00);     // 64k Transfers = 128K
      else
         prepUDMA(MSB(gSectorcount),LSB(gSectorcount),0);
      writeUDMA();

      if ((GPIFTCMSW || GPIFTCLSW))
      {
         stallEP2OUT();
         attemptFastWrite = 0;
         goto stopOnShortPacket;
      }
      
      // Check status to clear interrupt.
      if (readATAPI_STATUS_REG() & ATAPI_STATUS_ERROR_BIT) 
      {
         goto stopOnShortPacket;
      }
      else
      {
         // Two choices -- Either we're limited to 0x100 sectors, or limited to dataTransferLen.
         if (gSectorcount == 0x100)
         {
            dataTransferLenMSW -= 2;
            gSectorcount = stuffLBAandSector();
         }
         else
            {
            dataTransferLen = 0;    // This will terminate the loop anyway.  The break; just makes it faster
            break;
            }
      }
   } // While (dataTransferLen)
    
stopOnShortPacket:
   EP2Manual();
   if (readATAPI_STATUS_REG() & ATAPI_STATUS_ERROR_BIT)
      {
      loadSensePtrFromErrorRegister(0);
      attemptFastWrite = 0;
      return(USBS_FAILED);
      }
   else
      return(USBS_PASSED);
}


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


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

   return;
}   

void writeATA_DRIVESEL_REG()
{
   writePIO8(ATA_DRIVESEL_REG, 0xe0 | ((BYTE)bMasterSlave << 4));
}

#if DEVICE_TYPE_IS_IDE || ATACB_ENABLE
void EP6Manual()
{
   // switch the EP back to manual mode
   EP6FIFOCFG = bmZEROLENIN | bmWORDWIDE;
   WRITEDELAY();
   IFCONFIG = IFCONFIG_DEFAULT;
}

////////////////////////////////////////////////////////////////
//
// loadEP6BC()
// 
// Sends a short (less than one packet) response back to the host.  If the host asked for 0
// length data, don't send anything.  
//
/////////////////////////////////////////////////////////////////
void loadEP6BC(WORD dataLen)
{
   WORD packetLen;
   bit   bPaddedPacket = 0;

   // If the host asked for 0 data, give him 0 data!
   if (!dataTransferLenLSW)
      return;

   packetLen = min(dataTransferLen, dataLen);
   if (packetLen || (SHORT_PACKET_BEFORE_STALL))
   {
      // pad the really short responses
      if (dataTransferLen <= wPacketSize)
         {
         bPaddedPacket = 1;
         EP6BCH = MSB(dataTransferLenLSW);
         EP6BCL = LSB(dataTransferLenLSW);
         }
      else         
         {
         EP6BCH = MSB(packetLen);
         EP6BCL = LSB(packetLen);
         }
      dataTransferLen -= packetLen;
   }
   if (packetLen & (wPacketSize - 1))
      bShortPacketSent = 1;

   if (!bPaddedPacket)
      failedIn();    // This doesn't set status, just STALLs the IN endpoint if needed.      
}
#endif

BYTE flushCache()
{
   writeATA_DRIVESEL_REG();
   sensePtr = senseOk;
   checkForMedia(1);
   if (sensePtr != senseOk)
      return(USBS_FAILED);
   
   waitForBusyBit();
   writePIO8(ATA_COMMAND_REG, ATA_COMMAND_FLUSH_CACHE);  
   waitForBusyBit();
   return (USBS_PASSED);
}

#if STANDBY_IMMEDIATE
// Added for power saving on HDD devices in systems WITHOUT CF
// Only writes to the current LUN.  Multiple LUNs not supported.
void standbyImmediate()
{
   if (driveIsInStandby)
      return;
   driveIsInStandby = 1;
   writeATA_DRIVESEL_REG();
   
   waitForBusyBit();
   writePIO8(ATA_COMMAND_REG, ATA_COMMAND_STANDBY_IMMEDIATE);  
   waitForBusyBit();
}
#endif

⌨️ 快捷键说明

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