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