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

📄 ide.c

📁 cy68013a USB2.0 highspeed mass storage source code
💻 C
📖 第 1 页 / 共 4 页
字号:
//-----------------------------------------------------------------------------
//  Copyright (c) 1999 Cypress Semiconductor, Inc. All rights reserved
//-----------------------------------------------------------------------------
//
// This file contains the IDE specific portions of the code.  In ATAPI
// or SCSI applications, this file should not be needed.
//
// $Archive: /USB/atapifx2/CY4611B/ide.c $
// $Date: 6/26/05 1:57p $
// $Revision: 7 $
//-----------------------------------------------------------------------------
#include "Fx2.h"
#include "Fx2regs.h"
#include "gpif.h"
#include "scsi.h"
#include "globals.h"

static DWORD dwLBA;     // This is global to help the optimizer
static WORD wCmdSectorCount;     // Sector count from the read or write command
WORD stuffLBAandSector();      // Stuff the LBA registers, returns sectorCount
static void IDEPrepareForXfer();
BYTE loadSensePtrFromErrorRegister(bit readWrite);

char sensePtr;

/////////////////////////////////////////////////////////////////////////////////
#if DEVICE_TYPE_IS_IDE
/////////////////////////////////////////////////////////////////////////////////

// From SCSI spec SPC (SCSI primary commands)
// Byte 0 -- 70 = Current error
// Byte 1 -- Segment number
// Byte 2 -- Sense key (SPC table 107)
//             5 = ILLEGAL REQUEST. Indicates that there was an illegal parameter in the CDB or in the additional parameters supplied as data for some commands
//             B = ABORTED COMMAND. Indicates that the device server aborted the command. The application client may be able to recover by trying the command again.
//             E = MISCOMPARE. Indicates that the source data did not match the data read from the medium.
// Byte 3-6 -- Information (not used)
// Byte 7 -- add'l sense length 
// byte 8-11 -- Command specific information
// byte 12 -- ASC (Add'l sense code)
// byte 13 -- ASQ (Add'l sense qualifier)
//                                                         Key                                                         ASC   ASQ
//                                              0     1     2     3     4     5     6     7     8     9    10    11    12    13    14    15
//const char code senseTemplate[] =          {0x70,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};   

//                                          SK    ASC   ASQ

const char code senseArray[senseWriteProtected+1][3] = 
{{0x0b, 0x08, 0x03},   // senseCRCError               0 // Set on CRC error.  Causes host to retry  
{0x05, 0x24, 0x00},    // senseInvalidFieldInCDB      1// 300 calls this InvalidCommandField   
{0x00, 0x00, 0x00},    // senseOk                     2
{0x02, 0x3a, 0x00},    // senseNoMedia                3
{0x03, 0x03, 0x00},    // senseWriteFault             4
{0x03, 0x11, 0x00},    // senseReadError              5
{0x03, 0x12, 0x00},    // senseAddrNotFound           6
{0x05, 0x20, 0x00},    // senseInvalidOpcode          7
{0x05, 0x21, 0x00},    // senseInvalidLBA             8
{0x05, 0x26, 0x00},    // senseInvalidParameter       9
{0x05, 0x53, 0x02},    // senseCantEject              0xa
{0x06, 0x28, 0x00},    // senseMediaChanged           0xb
{0x06, 0x29, 0x00},    // senseDeviceReset            0xc// Initial value.  Set in ATARESET.c
{0x07, 0x27, 0x00}};   // senseWriteProtected         0xd


  

BYTE generalIDEInCommand()
{
   BYTE cmd;

   bShortPacketSent = 0;
   
   cmd = EP2FIFOBUF[0xf];  

   switch (cmd)
   {
      // Minimum processing for a case in this switch statement:
      case INQUIRY:
      {
         BYTE i;
         
         // clear out the bottom of EP6FIFOBUF.  This is where we are going to build
         // the response to the IDENTIFY command.
         AUTOPTRL2 = LSB(EP6FIFOBUF);
         for (i = SCSI_IDENTIFY_LEN; i; i--)
            XAUTODAT2 = 0;

         // Standard INQUIRY command
         if ((EP2FIFOBUF[CBW_DATA_START+1] & 0x3) == 0x0)
            {   
            waitForInBuffer();
            // CompactFlash uses a lot of local stuff
            if (bCompactFlash)
               {
               AUTOPTRL2 = LSB(EP6FIFOBUF);
   
               // Clear out the EP buffer
               for (i = SCSI_IDENTIFY_LEN; i; i--)
                  XAUTODAT2 = 0;
   
               // Load fields we use
               EP6FIFOBUF[SCSI_INQUIRY_REMOVABLE_BYTE] |= SCSI_INQUIRY_REMOVABLE_BIT;
   
               mymemmovexx(EP6FIFOBUF+SCSI_INQUIRY_MANUFACTURER, (void *)"Cypress Semi", sizeof("Cypress Semi"));
               }
            else
               {
               SendDeviceIdentifyCommand(1);
   
               // No need to disable interrupts here because we are expected to own EP6 at this point.
               FetchDeviceIdentifyIntoEp6();
      
               // copy the IDENTIFY data into the top of EP6FIFOBUF
               mymemmovexx(EP6FIFOBUF+256, EP6FIFOBUF, 256);
      
               // clear out the bottom of EP6FIFOBUF.  This is where we are going to build
               // the response to the IDENTIFY command.
               AUTOPTRL2 = LSB(EP6FIFOBUF);
               for (i = SCSI_IDENTIFY_LEN; i; i--)
                  XAUTODAT2 = 0;
      
               // Place the fields that we need into the SCSI block
               AUTOPTRL2 = LSB(EP6FIFOBUF+SCSI_INQUIRY_MANUFACTURER);
               for (i = 0; i < SCSI_INQUIRY_MANUFACTURER_LEN; i++)
                  {
                  // swap bytes within words.  This is stored backwards!
                  XAUTODAT2 = EP6FIFOBUF[(ATAPI_INQUIRY_MANUFACTURER * 2 + (i ^ 1)) + 256];
                  }
               
               XAUTODAT2 = '0';
               XAUTODAT2 = EP6FIFOBUF[(ATAPI_INQUIRY_REVISION * 2) + 256]+'0';
               XAUTODAT2 = '0';
               XAUTODAT2 = EP6FIFOBUF[(ATAPI_INQUIRY_REVISION * 2 +2) + 256]+'0';
               EP6FIFOBUF[SCSI_INQUIRY_REMOVABLE_BYTE] |= SCSI_INQUIRY_REMOVABLE_BIT & EP6FIFOBUF[(ATAPI_INQUIRY_REMOVABLE_BYTE) + 256];
               }
   
            if (currentLunNum == 0 && mx2_config_data.Lun0String)
               mymemmovexx(EP6FIFOBUF+SCSI_INQUIRY_MANUFACTURER, (BYTE xdata *)pDeviceDscr + (mx2_config_data.Lun0String) - 16, SCSI_IDENTIFY_LEN); 
            else if (currentLunNum == 1 && mx2_config_data.Lun1String)
               mymemmovexx(EP6FIFOBUF+SCSI_INQUIRY_MANUFACTURER, (BYTE xdata *)pDeviceDscr + (mx2_config_data.Lun1String) - 16, SCSI_IDENTIFY_LEN); 
   
            EP6FIFOBUF[SCSI_INQUIRY_REVISION_LEN] = 0x1F;
            loadEP6BC(SCSI_IDENTIFY_LEN);
            }
         // Respond to serial number page -- EVPD = 1 and page 0x80
         //
         // BUG - What should we do in the CF case?  The CF isn't there to give us the serial number.  Use our USB #?  Use the other devices's number?
         else if ((EP2FIFOBUF[CBW_DATA_START+1] & 0x3) == 1 && EP2FIFOBUF[CBW_DATA_START+2] == 0x80)
            {
            sensePtr = senseOk;
            checkForMedia(1);
   
            if (sensePtr != senseOk)
               {
               // relinquish control of the bulk buffer occupied by the CBW
               EP2BCL = 0x80;     
               
               failedIn();         
               return(USBS_FAILED);
               }

            SendDeviceIdentifyCommand(1);
   
            FetchDeviceIdentifyIntoEp6();
   
            // copy the IDENTIFY data into the top of EP6FIFOBUF
            mymemmovexx(EP6FIFOBUF+256, EP6FIFOBUF, 256);
   
            // clear out the bottom of EP6FIFOBUF.  This is where we are going to build
            // the response to the IDENTIFY command.
            AUTOPTRL2 = LSB(EP6FIFOBUF);
            for (i = SCSI_IDENTIFY_LEN; i; i--)
               XAUTODAT2 = 0;
            
            // First byte is the PDT (peripheral device type).  It's already set to 0 above
            AUTOPTRL2 = LSB(EP6FIFOBUF+1);
            XAUTODAT2 = 0x80;              // Page code = 0x80
            XAUTODAT2 = 0;                 // Reserved
            XAUTODAT2 = 8;                 // Thomson requested 8 bytes of data.  The ATA device will return 20 bytes.
            for (i = 0; i < 8; i++)
               XAUTODAT2 = EP6FIFOBUF[256+ATAPI_INQUIRY_SERIAL+i];
            loadEP6BC(12);
            }
         else
            {
            failedIn();
            sensePtr = senseInvalidFieldInCDB;
            EP2BCL = 0x80;     
            return(USBS_FAILED);
            }
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         sensePtr = senseOk;
         return(USBS_PASSED);
      }
      
      case READ_06:
      case READ_10:
      case VERIFY_10:
      {
         sensePtr = senseOk;
         checkForMedia(1);

         if (sensePtr == senseOk)
         {
            return(ideReadCommand(cmd));   
         }
         else
         {
            // relinquish control of the bulk buffer occupied by the CBW
            EP2BCL = 0x80;     
            
            failedIn();         
            return(USBS_FAILED);
         }
      }
                
      case SEEK_10:
      {
         sensePtr = senseOk;
         checkForMedia(1);

         if (sensePtr == senseOk)
            {
            // Cannot just call readcommand because it aborts on no dataTransferLen.
            IDEPrepareForXfer();
            stuffLBAandSector();
            writePIO8(ATA_COMMAND_REG, ATA_COMMAND_SEEK);

            if(waitForBusyBit() == USBS_FAILED)
               {
               loadSensePtrFromErrorRegister(1);
               return(USBS_FAILED);
               }
            else
               return(USBS_PASSED);
            }
         else
            {
	         // relinquish control of the bulk buffer occupied by the CBW
	         EP2BCL = 0x80;     

            failedIn();         
            return(USBS_FAILED);
            }
      }                

      case READ_FORMAT_CAPACITIES:
      case READ_CAPACITY:
      {
         BYTE num_bytes = 8;

         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         
         sensePtr = senseOk;
         checkForMedia(1);
                 
         waitForInBuffer();
         if (sensePtr == senseOk)
         {
            AUTOPTRL2 = LSB(EP6FIFOBUF);
            if(cmd == READ_FORMAT_CAPACITIES) // add 4 byte capacity list header
            {
               XAUTODAT2 = 0x0;
               XAUTODAT2 = 0x0;
               XAUTODAT2 = 0x0;
               XAUTODAT2 = 0x08;
               num_bytes = 12;
            }
            XAUTODAT2 = ((BYTE *) &ActiveLunConfigData.driveCapacity)[0];
            XAUTODAT2 = ((BYTE *) &ActiveLunConfigData.driveCapacity)[1];
            XAUTODAT2 = ((BYTE *) &ActiveLunConfigData.driveCapacity)[2];
            XAUTODAT2 = ((BYTE *) &ActiveLunConfigData.driveCapacity)[3];
            if(cmd == READ_FORMAT_CAPACITIES) 
               XAUTODAT2 = ((ATA_SECTOR_SIZE >> 24) & 0xff) | 2;     // Report media type -- Formatted
            else
               XAUTODAT2 = (ATA_SECTOR_SIZE >> 24) & 0xff;
            XAUTODAT2 = (ATA_SECTOR_SIZE >> 16) & 0xff;
            XAUTODAT2 = (ATA_SECTOR_SIZE >>  8) & 0xff;
            XAUTODAT2 = (ATA_SECTOR_SIZE >>  0) & 0xff;

            loadEP6BC(num_bytes);
            return(USBS_PASSED);
         }
         else
         {
            failedIn();
            return(USBS_FAILED);
         }
      }

      ///////////////////////////////////////////////////////////
      // 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     
      case MODE_SELECT_10:
      {
      // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         
      // This command is allowed to have data.         
         sensePtr = senseOk;
         checkForMedia(1);
         
         if (sensePtr == senseOk)
            return(USBS_PASSED);
         else
            return(USBS_FAILED);
      }                

      case TEST_UNIT_READY:
      case FORMAT_UNIT:
      {
      // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         
         if (dataTransferLen)    // This command shouldn't have any data!
            failedIn();         
         
         sensePtr = senseOk;
         checkForMedia(1);
         
         if (sensePtr == senseOk)
            return(USBS_PASSED);
         else
            return(USBS_FAILED);
      }                
      case REQUEST_SENSE:
      {
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
   
         waitForInBuffer();

         AUTOPTRL2 = LSB(EP6FIFOBUF);

         // First two bytes are 0x70 and 0x00
         XAUTODAT2 = 0x70;
         XAUTODAT2 = 0x00;
         // Clear the rest of the buffer
         mymemmovexx(EP6FIFOBUF+2, EP6FIFOBUF+1, 18-2);
         XAUTODAT2 = senseArray[sensePtr][0];

         AUTOPTRL2 = 7;
         XAUTODAT2 = 18-8;    // Length of data following this byte

         AUTOPTRL2 = 12;
         XAUTODAT2 = senseArray[sensePtr][1];
         XAUTODAT2 = senseArray[sensePtr][2];

         loadEP6BC(18);
         sensePtr = senseOk;
         return(USBS_PASSED);
      }
      case STOP_START_UNIT:
      case PREVENT_ALLOW_MEDIUM_REMOVAL:
         {
         BYTE options;

         options = EP2FIFOBUF[CBW_DATA_START+4];
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     
         
         if (dataTransferLen)    // This command shouldn't have any data!
            failedIn();         

         writeATA_DRIVESEL_REG();
         sensePtr = senseOk;
         checkForMedia(1);
         if (sensePtr != senseOk)
            return(USBS_FAILED);

         waitForBusyBit();
         if (cmd == PREVENT_ALLOW_MEDIUM_REMOVAL)
            {
            if (options & 1)
               writePIO8(ATA_COMMAND_REG, ATA_COMMAND_MEDIA_LOCK);
            else
               {
               flushCache();
               writePIO8(ATA_COMMAND_REG, ATA_COMMAND_MEDIA_UNLOCK);
               }

            // Cannot really lock the CF into the drive.  Forces Windows to poll us.
            if (bCompactFlash)
               return(USBS_FAILED);
            }

⌨️ 快捷键说明

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