📄 ide_func.c
字号:
/*
* description : ATA/ATAPI Interface
* Maker : Hideyuki Nekoshima
* Copyright : (C)2003,SEIKO EPSON Corp. All Rights Reserved.
*/
#include "SPRDEF.h"
#include "SPRSTS.h"
#include "IDE_Func.h"
/* ATA/ATAPI IF function list */
/*
*/
static LONG GetDeviceParameter( USHORT portNumber, UCHAR masterSlave, IDE_FUNCDEVICELIST* );
static LONG StatusWait( USHORT portNumber, UCHAR masterSlave );
static LONG ATACommandSet( USHORT deviceNo, UCHAR transferMode, IDE_FUNCCMDPARA *pCmdBlock);
static LONG ATAPItoATACommandSet( USHORT deviceNo, UCHAR transferMode, IDE_FUNCCMDPARA *pCmdBlock);
static LONG ATAPICommandSet( USHORT deviceNo, UCHAR transferMode, IDE_FUNCCMDPARA *pCmdBlock );
static LONG ATAErrorStatusSet( UCHAR error );
static LONG ATAPIRequestSense( USHORT deviceNo, UCHAR *pSenseData );
#define FREE_ID 0x00 /* Free the ID */
#define ALLOC_ID 0x01 /* Allocate ID */
#define FIRST_OPEN 0x01 /* IDE Function Module Firat Open Check */
#define NO_DEVICE 0xFF /* DEVICE Type Initialize */
#define ENABLE 0x00 /* Enable */
#define DISABLE 0x01 /* Disable */
#define IDENTIFY_DEVICE 0xEC /* ATA Identify Device Command */
#define IDENTIFY_PACKET_DEVICE 0xA1 /* ATA Identify Packet Device Command */
#define SET_FEATURS 0xEF /* ATA Set Featues Command */
#define HDD_READ 0xC8 /* READ DMA Command */
#define HDD_WRITE 0xCA /* WRITE DMA Command */
#define HDD_BIGDRV_READ 0x25 /* BIG Drive Read DMA Command*/
#define HDD_BIGDRV_WRITE 0x35 /* BIG Drive Write DMA Command */
#define READ6 0x08 /* ATAPI Read6 Command */
#define WRITE6 0x0A /* ATAPI Write6 Command */
#define READ10 0x28 /* ATAPI Read10 Command */
#define WRITE10 0x2A /* ATAPI Write10 Command */
#define READ12 0xA8 /* ATAPI Read12 Command */
#define WRITE12 0xAA /* ATAPI Write12 Command */
#define VERIFY10 0x2F /* ATAPI Verify10 Command */
#define SEEK 0x2B /* ATAPI SEEK Command */
#define START_STOP 0x1B /* ATAPI START/STOP UNIT Command */
#define READ_SECTOR 0x20 /* ATA Read Sector Command */
#define WRITE_SECTOR 0x30 /* ATA Write Sector Command */
#define READ_DMA 0xC8 /* ATA Read DMA Command */
#define WRITE_DMA 0xCA /* ATA Write DMA Command */
#define READ_VERIFY 0x40 /* ATA Read Verify Command */
#define READ_SECTOR_BIG 0x24 /* ATA Read Sector Command */
#define WRITE_SECTOR_BIG 0x34 /* ATA Write Sector Command */
#define SEEK_ATA 0x70 /* ATA Seek Command */
#define IDLE 0xE3 /* ATA Idle Command */
#define IDLE_IMMEDIATE 0xE1 /* ATA Idle Immedate Command */
#define STANDBY 0xE2 /* ATA Standby Command */
#define STANDBY_IMMEDIATE 0xE0 /* ATA Standby Immediate Command */
#define FLUSH_CACHE_EXT 0xEA /* ATA FLUSH CACHE EXT Command */
#define READ_NATIVE_MAX_ADDRESS_EXT 0x27 /* ATA READ NATIVE MAX ADDRESS EXT Command */
#define READ_VERIFY_SECTOR_EXT 0x42 /* ATA READ VERIFY SECTOR(S) EXT Command */
#define SET_MAX_ADDRESS_EXT 0x37 /* ATA SET MAX ADDRESS EXT Command */
#define SEL_BIG_DRIVE 0x01 /* HDD Big Drive Enable */
#define IDE_FUNC_DMAREQ 0x80
#define IDE_FUNC_IORDY 0x10
#define DMA_TRAN 0x01 /* H/W DMA transfer */
#define SOFT_TRAN 0x02 /* Software data transfer */
typedef struct selectdevice{
USHORT portNumber; /* Device connection port number */
UCHAR MasterSlave; /* Device master/slave */
UCHAR type; /* Device Type (HDD, CD, MO, etc..) */
}SELECT_DEVICE;
static SELECT_DEVICE SelectDeviceNo[MAX_DEVICE]; /* device managment table */
static ATA_IFSTATUS DeviceStatus; /* ATA Status */
static ATA_IFATACMD ATACmd; /* ATA Command */
static ATA_IFTRANPARA TranPara; /* ATA Data Transfer Parameter */
static ATA_IFINTERRUPT IntStat; /* ATA Interrupt Status */
static UCHAR ATAPICmd[12]; /* ATAPI Command Block */
typedef struct devicepara{
UCHAR PioMode; /* PIO Transfer Mode */
UCHAR DmaMode; /* MultiWordDma Transfer Mode */
UCHAR UltraEnb; /* UltraDma Enable/Disable */
UCHAR UltraMode; /* UltraDma Transfer Mode */
UCHAR BigDrive; /* Big Drive Enale/Disable */
}DEVICE_PARA;
static DEVICE_PARA DevicePara[MAX_DEVICE]; /* Device Parameter management */
typedef struct cmdstatus{
USHORT id; /* Upper layer ID */
USHORT status; /* Command Status (STOP, COMP, EXEC) */
}IDE_FUNC_CMDSTS;
static IDE_FUNC_CMDSTS CMDState[MAX_DEVICE]; /* ATA/ATAPI Command management */
typedef struct dmastatus{
USHORT id; /* Upper layer ID */
USHORT status; /* DMA Transfer Status (STOP, COMP, EXEC)*/
}IDE_FUNC_DMASTS;
static IDE_FUNC_DMASTS DMAState[MAX_DEVICE]; /* DMA transfer management */
typedef struct compflag{
UCHAR dmaComp :1; /* IDE DMA Complete */
UCHAR intrq :1; /* ATA Intrq */
UCHAR reserve :6;
}IDE_FUNC_COMPFLAG;
// Delete because not used.
//static volatile IDE_FUNC_COMPFLAG CompleteFlag;
static UCHAR DeviceCnt; /* The number of connected devices */
static ULONG TransferLba; /* Read/Write transfer start sector adress(Encryption use) */
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncReset
//
// description : Initialize the IDE Function Module.
//
// : Initialize the local varibles of IDE Function Module,
// and initialzie the lower layer.
//
// argument : none
//
// return : LONG status Processing result
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncReset( void )
{
UCHAR i;
/* Clear internal work data */
DeviceCnt = 0;
/* PORT Execution Flag Clear */
for(i=0; i<MAX_DEVICE; i++){
CMDState[i].status = IDE_FUNC_CMD_STOP;
DMAState[i].status = IDE_FUNC_DMA_STOP;
}
/* Reset lower layer */
ATA_IFReset();
IDEDMA_IFReset();
/* Complete */
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncOpen
//
// description : Open IDE Function Module.
//
// Open IDE Function Module,it enters the usable status.
// If Open is not executed, will not do the API processing in Module
//
// argument : non
//
// return : LONG status Processing result
//
// flag : UCHAR OpenFlag PASS It Indicates if Interface Module is usable.
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncOpen( void )
{
LONG result;
UCHAR i;
/* OPEN the lower layer */
result = ATA_IFOpen();
if( result != STATUS_SUCCESS ){
return result;
}
result = IDEDMA_IFOpen();
if( result != STATUS_SUCCESS ){
return result;
}
DeviceCnt = 0;
for(i=0; i<MAX_DEVICE; i++){
CMDState[i].status = IDE_FUNC_CMD_STOP;
DMAState[i].status = IDE_FUNC_DMA_STOP;
}
/* Complete */
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncDeviceReset
//
// description : Initialzie the specified device.
//
//
// argument : USHORT id the identifier of the upper layer
// USHORT deviceNo Initialized device No
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncDeviceReset( USHORT id, USHORT deviceNo )
{
LONG result;
if( deviceNo >= DeviceCnt ){
/* Parameter error */
return STATUS_INVALID_PARAMETER;
}
/* DMA PORT Reset */
result = IDEDMA_IFInitPort( SelectDeviceNo[deviceNo].portNumber );
if( result != STATUS_SUCCESS ){
return result;
}
/* ATA/ATAPI Device Reset */
/* PORT Lock */
result = ATA_IFLockPort( SelectDeviceNo[deviceNo].portNumber );
if(( result != STATUS_SUCCESS )&&( result != STATUS_LOCKED_PORT )){
return result;
}
/* Device Reset */
result = ATA_IFSelResetDevice( SelectDeviceNo[deviceNo].portNumber, SelectDeviceNo[deviceNo].MasterSlave );
/*PORT Unlock */
result = ATA_IFUnlockPort( SelectDeviceNo[deviceNo].portNumber );
if( result != STATUS_SUCCESS ){
return result;
}
/* Clear the internal prameter. */
CMDState[deviceNo].status = IDE_FUNC_CMD_STOP;
DMAState[deviceNo].status = IDE_FUNC_DMA_STOP;
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: IDE_FuncGetDeviceList
//
// description : Get the device list that connected to the port
//
//
// argument : USHORT id Identifier of the upper layer.
// IDE_FUNCDEVICELIST *pList Device list
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
LONG IDE_FuncGetDeviceList( USHORT id, IDE_FUNCDEVICELIST *pList )
{
LONG result;
USHORT portCount;
USHORT i;
UCHAR masterEnb;
UCHAR slaveEnb;
if( DeviceCnt == 0x00 ){
for(portCount=0; portCount < ATA_IF_MAX_PORT; portCount++){
/* ATA Function PORT LOCK */
result = ATA_IFLockPort( portCount );
if(result != STATUS_SUCCESS){
DeviceCnt = 0x00;
pList->deviceCount = 0x00;
return result;
}
/* Check the initial value of the Status & Register */
/* BSY negate wait */
result = StatusWait( portCount, ATA_IF_MASTER );
if( result != STATUS_SUCCESS ){
return result;
}
/* ATA Task Register Check */
if( DeviceStatus.IntReasen == 0x01 || DeviceStatus.status == 0x50 ){
masterEnb = ENABLE;
}else{
masterEnb = DISABLE;
}
result = StatusWait( portCount, ATA_IF_SLAVE );
if( result != STATUS_SUCCESS ){
return result;
}
/* ATA Task Register Check */
if( DeviceStatus.status == 0x50 ){
slaveEnb = ENABLE;
}else{
if( DeviceStatus.IntReasen == 0x01 && DeviceStatus.transfersize != 0x00 ){
slaveEnb = ENABLE;
}else{
slaveEnb = DISABLE;
}
}
/* Get Master Device Parameter */
if( masterEnb == ENABLE ){
result = GetDeviceParameter( portCount, ATA_IF_MASTER, pList );
if(result != STATUS_SUCCESS){
ATA_IFUnlockPort( portCount );
DeviceCnt = 0x00;
pList->deviceCount = 0x00;
return result;
}
}
/* Get Slave Device Parameter */
if( slaveEnb == ENABLE ){
result = GetDeviceParameter( portCount, ATA_IF_SLAVE, pList );
if(result != STATUS_SUCCESS){
ATA_IFUnlockPort( portCount );
DeviceCnt = 0x00;
pList->deviceCount = 0x00;
return result;
}
}
/* ATA Function PORT Unlock */
result = ATA_IFUnlockPort( portCount );
}
}
/* Device List Data Set */
pList->deviceCount = DeviceCnt;
if( DeviceCnt != 0x00 ){
for( i=0; i<DeviceCnt; i++){
pList->deviceType[i] = SelectDeviceNo[i].type;
}
}
return STATUS_SUCCESS;
}
/*
////////////////////////////////////////////////////////////////////////
// Function_Name: GetDeviceParameter
//
// description : Get the parameter of the device
//
//
// argument : USHORT portNumber The port thet device is connected
// UCHAR masterSlabe ATA Master/Slave selection
//
// return : LONG status Processing result
//
////////////////////////////////////////////////////////////////////////
*/
static LONG GetDeviceParameter( USHORT portNumber, UCHAR masterSlave, IDE_FUNCDEVICELIST *pList )
{
LONG result;
USHORT i;
UCHAR ataAtapi;
UCHAR identifydata[0x200];
UCHAR inquirydata[4];
/* ATA Command Clear */
ATACmd.reg01 = 0x00;
ATACmd.reg02 = 0x00;
ATACmd.reg03 = 0x00;
ATACmd.reg04 = 0x00;
ATACmd.reg05 = 0x00;
ATACmd.reg06 = 0x00;
ATACmd.reg07 = 0x00;
/* Send IDE IDENTIFY DEVICE Command */
ATACmd.reg07 = ataAtapi = IDENTIFY_DEVICE;
result = ATA_IFATACommandOutA( portNumber, masterSlave, ATA_IF_PIO_MODE2, &ATACmd );
/* BSY negate wait */
result = StatusWait( portNumber, masterSlave );
if( result != STATUS_SUCCESS ){
return result;
}
/* ERROR Complete Check */
if( ( DeviceStatus.status & 0x01 ) ){
/* Send ATAPI IDENTIFY PACKET DEVICE Command */
ATACmd.reg07 = ataAtapi = IDENTIFY_PACKET_DEVICE;
result = ATA_IFATACommandOutA( portNumber, masterSlave, ATA_IF_PIO_MODE2, &ATACmd );
if( result != STATUS_SUCCESS ){
return result;
}
/* BSY negate wait */
result = StatusWait( portNumber, masterSlave );
/* ERROR Complete Check */
if( ( DeviceStatus.status & 0x01 ) ){
return STATUS_SUCCESS;
}
}
/* Check DRQ assert */
if( !( DeviceStatus.status & 0x08 ) ){
return STATUS_SUCCESS;
}
/* Read IDENTIFY DEVICE DATA */
TranPara.transfersize = 0x200;
TranPara.direction = ATA_IF_IDE_IN;
TranPara.dataPointer = (ULONG)( identifydata );
result = ATA_IFPIODataTransfer( portNumber, masterSlave, &TranPara );
#ifdef FPGA_DEBUG_C
identifydata[106]=0x0;
identifydata[126]=0x04; /* MultiWord DMA Mode 2 */
identifydata[176]=0x04; /* Ultra DMA Mode 2 */
#endif
if(result != STATUS_SUCCESS ){
return result;
}
/* BSY negate wait */
result = StatusWait( portNumber, masterSlave );
if(result != STATUS_SUCCESS ){
return STATUS_SUCCESS;
}
/* ERROR Complete Check */
if( ( DeviceStatus.status & 0x01 ) ){
return STATUS_SUCCESS;
}
/* ATA/ATAPI Device Check */
if( ataAtapi == IDENTIFY_PACKET_DEVICE ){
/* Send ATAPI DEVICE Inquiry Command */
for(i=0; i<0x0c; i++){
ATAPICmd[i] = 0;
}
ATAPICmd[0] = 0x12;
ATAPICmd[4] = 0x04;
result = ATA_IFAtapiCommandOutA( portNumber, masterSlave, ATA_IF_PIO, ATA_IF_PIO_MODE2, ATAPICmd );
if(result != STATUS_SUCCESS){
return result;
}
/* BSY negate wait */
result = StatusWait( portNumber, masterSlave );
if(result != STATUS_SUCCESS ){
return STATUS_SUCCESS;
}
/* Clear DRQ assert */
if( !( DeviceStatus.status & 0x08 ) ){
return STATUS_SUCCESS;
}
/* Read Inquiry Data */
TranPara.transfersize = 0x04;
TranPara.direction = ATA_IF_IDE_IN;
TranPara.dataPointer = (ULONG)( inquirydata );
result = ATA_IFPIODataTransfer( portNumber, masterSlave, &TranPara );
if(result != STATUS_SUCCESS ){
return result;
}
/* BSY negate wait */
result = StatusWait( portNumber, masterSlave );
if(result != STATUS_SUCCESS ){
return STATUS_SUCCESS;
}
/* ERROR Complete Check */
if( ( DeviceStatus.status & 0x01 ) ){
return STATUS_SUCCESS;
}
/* Device Type Set */
SelectDeviceNo[DeviceCnt].type = inquirydata[0];
}else{
/* Device Type Set */
SelectDeviceNo[DeviceCnt].type = IDE_FUNC_HDD;
}
/* Set port No. the device is connected & Master/Slave driver */
SelectDeviceNo[DeviceCnt].portNumber = portNumber;
SelectDeviceNo[DeviceCnt].MasterSlave = masterSlave;
/* set the PIO transfer mode */
if( (identifydata[128] & 0x02) ){
DevicePara[DeviceCnt].PioMode = ATA_IF_PIO_MODE4;
}
else{
if( (identifydata[128] & 0x01) ){
DevicePara[DeviceCnt].PioMode = ATA_IF_PIO_MODE3;
}else{
DevicePara[DeviceCnt].PioMode = ATA_IF_PIO_MODE0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -