📄 ide.c
字号:
//-----------------------------------------------------------------------------
// 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 + -