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

📄 ide.c

📁 cy68013a USB2.0 highspeed mass storage source code
💻 C
📖 第 1 页 / 共 4 页
字号:
         else      // STOP_START_UNIT:
            {
            if (options & 0xf0)
               {
               if ((options & 0xf0) > 0x10 &&
                   (options & 0xf0) < 0x70)
                     writePIO8(ATA_COMMAND_REG, ATA_COMMAND_STANDBY_IMMEDIATE);
               }
            else if ((options & 3) == 2)
               {
               if (bCompactFlash)
                  ejected = 1;
               else
                  writePIO8(ATA_COMMAND_REG, ATA_COMMAND_MEDIA_EJECT);
               }
            }
         waitForBusyBit();

         if (readATAPI_STATUS_REG() & ATAPI_STATUS_ERROR_BIT)
            {
            BYTE error = loadSensePtrFromErrorRegister(1);
            if (error & 4)  // command not supported -- Non removable media, return PASS
               {
               sensePtr = senseOk;
               return(USBS_PASSED);
               }
            else if ((error & 2) && (options & 3) == 2)
               sensePtr = senseCantEject;
            return(USBS_FAILED);
            }
         else
            return(USBS_PASSED);
         break;
         }

      case MODE_SENSE_06:
      case MODE_SENSE_10:
      {               
         BYTE pagenum;
         
         pagenum = EP2FIFOBUF[CBW_DATA_START+2] & 0x3F; // identify page (see p.141 SCSI 2ed.)
   
         EP2BCL = 0x80; // relinquish control of the bulk buffer occupied by the CBW
         
         waitForInBuffer();
         
         if((pagenum != 0x05) && (pagenum != 0x3F)
             && (pagenum != 0x01) && (pagenum != 0x08) && (pagenum != 0x1B))
         { // only respond to requests for certain pages (the mandatory ones plus page 5)
            sensePtr = senseInvalidFieldInCDB;
            failedIn();
            return(USBS_FAILED);
         }
   
         // If one of the supported pages is requested, return the 8 byte Mode Parameter Header
         // plus a single 12 byte page. Only the Mode Data length (LSB) is significant in the
         // Mode Parameter Header. It has a Vendor Specific Medium Type Code in byte 2, and
         // a 1 bit WP Write Protect bit in byte 3 that are not initialized here.
         // Pages 0x01, and 0x08 do not have significant data - they are spoofed.
         // Page 0x1B has a TLUN field in byte 3 that is initialized to 1 (as per ISD).
         // Page 0x05 does contain information that is needed to boot to HDD and CDROM.
         // Page 0x3F, All Pages, is also responded to.
         // The supported pages are (see INF-8070_1_3.pdf p37 Table 25):
         //   case 0x01:                          // Read-Write Error Recovery Page
         //   case 0x08:                          // Caching Page
         //   case 0x05:                          // Flexible Disk Page: needed to boot from USB
         //   case 0x1B:                          // Removable Block Access Capabilities Page
         //   case 0x3F:                          // All (4) Pages
         
         // The format used is:
         //    Mode parameter header (4 or 8 bytes)
         //    Block descriptors (not supported)
         //    Mode page
         EP6FIFOBUF[0] = 0x00;
         mymemmovexx(EP6FIFOBUF+1, EP6FIFOBUF, 200-1); // clear buffer - <200 bytes in all responses

         if (cmd == MODE_SENSE_10)
            {
            AUTOPTRL2 = LSB(EP6FIFOBUF) + 8;     // The rest of the header is zeroes.  Start the pages at byte 8.     
            }
         else
            {
            AUTOPTRL2 = LSB(EP6FIFOBUF) + 4;          
            }

         if((pagenum == 0x05) || (pagenum == 0x3F))
            {  
            XAUTODAT2 = 5;               // fill out the page num - fields are all 0x0
            XAUTODAT2 = 12-2;            // set individual Page Length -- return 12 for all commands

            if(EZUSB_HIGHSPEED())
               {
               XAUTODAT2 = 0xFF;         // HS Transfer Rate (MSB) (field limited to 65Mb/Sec)
               XAUTODAT2 = 0xFF;         // HS Transfer Rate (LSB)
               }
            else
               {
               XAUTODAT2 = 0x2E;         // FS Transfer Rate (MSB) (12Mb/Sec) 
               XAUTODAT2 = 0xE0;         // FS Transfer Rate (LSB)
               }
            XAUTODAT2 = ActiveLunConfigData.NumHeads;        // #Heads
            XAUTODAT2 = ActiveLunConfigData.NumSectPerTrack; // #SectorsPerTrack
            XAUTODAT2 = (ATA_SECTOR_SIZE >>  8) & 0xff; // Data Bytes per sector (truncated)
            XAUTODAT2 = (ATA_SECTOR_SIZE >>  0) & 0xff; // Data Bytes per sector
            XAUTODAT2 = ActiveLunConfigData.NumCylindersMSB; // #Cyl MSB
            XAUTODAT2 = ActiveLunConfigData.NumCylindersLSB; // #Cyl LSB
            XAUTODAT2 = 0;
            XAUTODAT2 = 0;
            }
         if(pagenum == 0x1B || pagenum == 0x3f)
            {
            XAUTODAT2 = 0x1b;            // fill out the page num
            XAUTODAT2 = 12-2;            // set individual Page Length -- return 12 for all commands
            XAUTODAT2 = 0;
            XAUTODAT2 = 0x01;            // set TLUN = 1 for page 0x1B
            AUTOPTRL2 += 8;              // 8 zeroes too.
            }
         if(pagenum == 0x1 || pagenum == 0x3f)
            {
            XAUTODAT2 = 0x1;             // fill out the page num
            XAUTODAT2 = 12-2;            // set individual Page Length -- return 12 for all commands
            AUTOPTRL2 += 10;              // 10 zeroes too.
            }

         if (bENABLE_WRITE_CACHE_MODE_PAGE)
            if(pagenum == 0x8 || pagenum == 0x3f)
               {
               XAUTODAT2 = 0x8;             // fill out the page num
               XAUTODAT2 = 0x14-2;          // set individual Page Length -- 0x14
               XAUTODAT2 = bWriteCacheDisabled ? 0 : 4;           // Report write cache enabled or disabled.
               AUTOPTRL2 += 13-3;           // Skip to the # of cache segments area (byte 13, we've done 3 so far)
               XAUTODAT2 = 0x10;            // 10 Cache segments
               XAUTODAT2 = 0x10;            // 4K (this is fake data!)
               XAUTODAT2 = 0x00;
               AUTOPTRL2 += 4;              // Skip the last 4 bytes
               }

         if (cmd == MODE_SENSE_10)
            EP6FIFOBUF[1] = AUTOPTRL2-2;
         else
            EP6FIFOBUF[0] = AUTOPTRL2-1;

         loadEP6BC(AUTOPTRL2);
         sensePtr = senseOk;
         return(USBS_PASSED);
      } // end case

      ////////////////////////////////////////////////////////////////
      // Check for phase error -- Write in a read wrapper
      case WRITE_10:
      case WRITE_AND_VERIFY_10:
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         
         sensePtr = senseInvalidOpcode;
         failedIn();
         return(USBS_PHASE_ERROR);

      default:
      {
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         
         sensePtr = senseInvalidOpcode;
         failedIn();
         return(USBS_FAILED);
      }
   }
}   

BYTE generalIDEOutCommand()
{
   BYTE cmd;
   
   cmd = EP2FIFOBUF[0xf];  
   
   switch (cmd)
   {
      case WRITE_06:
      case WRITE_10:
      case WRITE_AND_VERIFY_10:
      {
         sensePtr = senseOk;
         checkForMedia(1);
         if (sensePtr == senseOk)
            {
            return(ideWriteCommand(cmd));
            }
         else
         {
            // relinquish control of the bulk buffer occupied by the CBW
            EP2BCL = 0x80;
            stallEP2OUT();

            return(USBS_FAILED);
         }
      }
      case SYNCHRONIZE_CACHE:
      {
         return(flushCache());
      }
      ///////////////////////////////////////////////////////////
      // Spoofed commands
      case MODE_SELECT_06:    // Note that these are in BOTH the read and write areas in case they are sent with no data
         // Add kludge for Mac Jaguar OS.  Wait for extra OUT packets to show up so we process them properly.
         EZUSB_Delay(5);
      case MODE_SELECT_10:
      {
         bit bShortPacketReceived = 0;

         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;   
  
         // Only process one mode select -- Write caching
         // When we're done, discard the data just like any other mode select.
         if (dataTransferLen)
            {
            BYTE offset;

            while(EP2CS & bmEPEMPTY)
               ;

            // Skip past block descriptor to get to the page.
            if (cmd == MODE_SELECT_06)
               offset = 4+EP2FIFOBUF[3];
            else
               offset = 8+EP2FIFOBUF[7];

            // If the page is 8, use it.
            if (EP2FIFOBUF[offset] == 8)
               {
               bWriteCacheDisabled = (~EP2FIFOBUF[offset+2]) & 4;
               setFeatures(bWriteCacheDisabled ? 
                  SET_FEATURES_WRITE_CACHE_DISABLE : SET_FEATURES_WRITE_CACHE_ENABLE, 0);
               }
            }

      // Toss away all of the data received with the command
         while (dataTransferLen && !bShortPacketReceived)
            {
            if(!(EP2CS & bmEPEMPTY))   
               {
               dataTransferLen -= min(EP2BC, dataTransferLen);
               if (EP2BC != wPacketSize)
                  bShortPacketReceived = 1;   
               EP2BCL = 0x80;
               }
            }
         
      // This command is allowed to have data.         
         sensePtr = senseOk;
         checkForMedia(1);
         
         if (sensePtr == senseOk)
            return(USBS_PASSED);
         else
            return(USBS_FAILED);
      }

      //////////////////////////////////////////////////////////////////////
      // Check for phase error -- Read command in a write wrapper
      case INQUIRY:
      case READ_06:
      case READ_10:
      case READ_FORMAT_CAPACITIES:
      case READ_CAPACITY:
      case REQUEST_SENSE:
      case MODE_SENSE_06:
      case MODE_SENSE_10:
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         
         stallEP2OUT();
         sensePtr = senseInvalidOpcode;         
         return(USBS_PHASE_ERROR);
    
      default:
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         
         stallEP2OUT();
         sensePtr = senseInvalidOpcode;         
         return(USBS_FAILED);
         break;
   }
}   





static BYTE ideReadCommand(BYTE command)
{   
   BYTE driveStatus;
   WORD sectorcount; 
   WORD wordCtr;

   if (command == VERIFY_10)
      {
      // Stuff dataTranferLen with 00 (sector count << 1) 00
      dataTransferLenLSB = 0;
      dataTransferLen23W = (EP2FIFOBUF[CBW_DATA_START+7] << (8+1)) + (EP2FIFOBUF[CBW_DATA_START+8] << 1);
      dataTransferLenMSB = 0;
      }

   // Prepare for fast read 
   mymemmoveix(prevCmd,&EP2FIFOBUF[0x0F],10);   
   prevDataTransferLen = dataTransferLen;

   switch (command)
      {
      case READ_06:   
         {
         ((BYTE *) &dwLBA)[0] = 0;
         ((BYTE *) &dwLBA)[1] = EP2FIFOBUF[CBW_DATA_START+1] & 0x1f;
         ((BYTE *) &dwLBA)[2] = EP2FIFOBUF[CBW_DATA_START+2];
         ((BYTE *) &dwLBA)[3] = EP2FIFOBUF[CBW_DATA_START+3];

         wCmdSectorCount = EP2FIFOBUF[CBW_DATA_START+4];
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         break;
         }
      default:
         IDEPrepareForXfer();
      }

   if (wCmdSectorCount > dataTransferLen23W/2)
      {
      failedIn();
      return (USBS_PHASE_ERROR);
      }

   gSectorcount = wCmdSectorCount;     // Save the cmdSectorCount for use in fast reads

   // This loop breaks up the 32 bit length into 8 bits * sectors.
   // For example, a read of 0x10000 turns into 0x80 sectors.
   while (dataTransferLen && wCmdSectorCount)
   {
      sectorcount = stuffLBAandSector();
        
      if (!ActiveLunConfigData.udmaMode || (command == VERIFY_10) || (dataTransferLenLSW & 0x1ff)    // UDMA cannot handle sub-sector sized reads
         )
      {
         // Execute the read command
         if (bExtAddrSupport)
            {
            if ((command == VERIFY_10))
               writePIO8(ATA_COMMAND_REG, ATA_COMMAND_VERIFY_10_EXT);
            else
               writePIO8(ATA_COMMAND_REG, ATA_COMMAND_READ_10_EXT);
            }
         else
            {
            if ((command == VERIFY_10))
               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.  The verify code path doesn't get any further than this IF statement.
         if ((command == VERIFY_10))     
         {
            if(waitForBusyBit() == USBS_FAILED)
               {
               loadSensePtrFromErrorRegister(1);
               dataTransferLen = 0;    // This command has no data but this loop uses dataTransferLen as a counter.
               return(USBS_FAILED);
               }
            else
               {
               if (sectorcount == 0x100)
                  {
                  dataTransferLenMSW -= 2;
                  wCmdSectorCount -= 0x100;
                  }
               else
                  dataTransferLen = 0;
               continue;
               }
         }

         // Wait for drive non-busy before starting xfer
         while (readATAPI_ALT_STATUS_REG() & ATAPI_STATUS_BUSY_BIT)
            ;

⌨️ 快捷键说明

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