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

📄 ide.c

📁 Cy68013的应用——USB2.0接口转IDE、CF卡接口
💻 C
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------
//  Copyright (c) 1999-2002 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.
//
// $Workfile: ide.c $
// $Date: 7/05/02 5:24p $
// $Revision: 18 $
//-----------------------------------------------------------------------------
#include "Fx2.h"
#include "Fx2regs.h"
#include "gpif.h"
#include "scsi.h"
#include "globals.h"


static bit ideReadCommand(BYTE command);
static bit ideWriteCommand(BYTE command);
bit ideUdmaWriteCommand();
static void IDEnop();
static DWORD dwLBA;     // This is global to help the optimizer
WORD stuffLBAandSector(bit readWrite);      // Stuff the LBA registers, returns sectorCount
static void IDEPrepareForXfer();
static void loadEP8BC(WORD dataLen);
//void checkForMedia();    /* This command is only used for removable DRIVES, not removable media.  An example of removable drive is Compact Flash */
BYTE loadSensePtrFromErrorRegister(bit readWrite);

// 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 senseCRCError[] =          {0x0b, 0x08, 0x03};    // Set on CRC error.  Causes host to retry  
const char code senseInvalidFieldInCDB[] = {0x05, 0x24, 0x00};    // 300 calls this InvalidCommandField   
const char code senseOk[] =                {0x00, 0x00, 0x00}; 
const char code senseNoMedia[] =           {0x02, 0x3a, 0x00}; 
const char code senseWriteFault[] =        {0x03, 0x03, 0x00}; 
const char code senseReadError[] =         {0x03, 0x11, 0x00}; 
const char code senseAddrNotFound[] =      {0x03, 0x12, 0x00}; 
const char code senseInvalidOpcode[] =     {0x05, 0x20, 0x00}; 
const char code senseInvalidLBA[] =        {0x05, 0x21, 0x00}; 
const char code senseInvalidParameter[] =  {0x05, 0x26, 0x00}; 
const char code senseCantEject[] =         {0x05, 0x53, 0x02}; 
const char code senseMediaChanged[] =      {0x06, 0x28, 0x00}; 
const char code senseDeviceReset[] =       {0x06, 0x29, 0x00};    // Initial value.  Set in ATARESET.c
const char code senseWriteProtected[] =    {0x07, 0x27, 0x00}; 

  
char code * sensePtr;

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


bit generalIDEInCommand()
{
   BYTE cmd;
   bit status;

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

   switch (cmd)
   {
      // Minimum processing for a case in this switch statement:
      case INQUIRY:
      {
         BYTE i;
         
         // relinquish control of the bulk buffer occupied by the CBW
         EP2BCL = 0x80;     

         waitForInBuffer();
         // CompactFlash uses a lot of local stuff
         if (bCompactFlash)
            {
            AUTOPTRL2 = LSB(EP8FIFOBUF);

            // Clear out the EP buffer
            for (i = SCSI_IDENTIFY_LEN; i; i--)
               XAUTODAT2 = 0;

            // Load fields we use
            EP8FIFOBUF[SCSI_INQUIRY_REMOVABLE_BYTE] |= SCSI_INQUIRY_REMOVABLE_BIT;
            mymemmovexx(EP8FIFOBUF+SCSI_INQUIRY_MANUFACTURER, (void *)"Cypress Semi", sizeof("Cypress Semi"));
            }

         else
            {
            SendDeviceIdentifyCommand();

            FetchDeviceIdentifyIntoEp8();
   
            // copy the IDENTIFY data into the top of EP8FIFOBUF
            mymemmovexx(EP8FIFOBUF+256, EP8FIFOBUF, 256);
   
            // clear out the bottom of EP8FIFOBUF.  This is where we are going to build
            // the response to the IDENTIFY command.
            AUTOPTRL2 = LSB(EP8FIFOBUF);
            for (i = SCSI_IDENTIFY_LEN; i; i--)
               XAUTODAT2 = 0;
   
            // Place the fields that we need into the SCSI block
            AUTOPTRL2 = LSB(EP8FIFOBUF+SCSI_INQUIRY_MANUFACTURER);
            for (i = 0; i < SCSI_INQUIRY_MANUFACTURER_LEN; i++)
               {
               // swap bytes within words.  This is stored backwards!
               XAUTODAT2 = EP8FIFOBUF[(ATAPI_INQUIRY_MANUFACTURER * 2 + (i ^ 1)) + 256];
               }
            
            EP8FIFOBUF[SCSI_INQUIRY_REVISION+1] = EP8FIFOBUF[(ATAPI_INQUIRY_REVISION * 2) + 256]+'0';
            EP8FIFOBUF[SCSI_INQUIRY_REVISION+3] = EP8FIFOBUF[(ATAPI_INQUIRY_REVISION * 2 +2) + 256]+'0';
            EP8FIFOBUF[SCSI_INQUIRY_REMOVABLE_BYTE] |= SCSI_INQUIRY_REMOVABLE_BIT & EP8FIFOBUF[(ATAPI_INQUIRY_REMOVABLE_BYTE) + 256];
            }

         EP8FIFOBUF[SCSI_INQUIRY_REVISION_LEN] = 0x1F;
         loadEP8BC(SCSI_IDENTIFY_LEN);
         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(1);
            writePIO8(ATAPI_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(EP8FIFOBUF);
            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;

            loadEP8BC(num_bytes);
            status = USBS_PASSED;
         }
         else
         {
            failedIn();
            status = USBS_FAILED;
         }

         return(status);
      }

      ///////////////////////////////////////////////////////////
      // 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(EP8FIFOBUF);

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

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

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

         loadEP8BC(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();
         
         if (bCompactFlash)
            {
            if ((cmd == PREVENT_ALLOW_MEDIUM_REMOVAL && (options & 1)) ||  // media_lock
               (cmd == STOP_START_UNIT && ((options & 3) == 2)))           // STOP_START_UNIT(EJECT):
               {
               sensePtr = senseCantEject;
               return(USBS_FAILED);
               }
            else // start unit or other command we didn't consider -- should return okay.
               {
               sensePtr = senseOk;
               return(USBS_PASSED);
               }
            }

         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
               writePIO8(ATA_COMMAND_REG, ATA_COMMAND_MEDIA_UNLOCK);
            }
         else      // STOP_START_UNIT:
            if ((options & 3) == 2)
               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:

⌨️ 快捷键说明

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