📄 ata.c
字号:
/*************************************************************
File Name: ATA.C
Last Modified Date: 2002/06/26
Programmer: Johnson (Huang Giun-Haur)
Compiler: ???
Platform: X86 protection mode without any function support,
Dragonball, MIPS, ARM7, AR2000
Usage:
1. WAIT_COMMAND_AVAILABLE(not in SMC)
2. WAIT_COMMAND_RESULT(not in SMC)
3. ATA_GET_PARAMETER(not in SMC)
4. ATA_READ
5. ATA_WRITE
Other Information :
990614 IO with a loop is used instead of 'rep' so that slower
HD can work correctly.
Timeout is used to wait till the disk is ready instead
of looping N times. More machine independent now.
History : Arti Engineer Huang TzeHeng updated(2002/6/26)
1. Added SMC option ( FAT_USE_SMC defined )
2. SMC option uses {driver/nflash} driver
Himark Engineer Huang TzeHeng updated(2002/11/19)
1. Added MMC option ( FAT_USE_MMC defined )
**************************************************************/
#include <sys/syscall.h>
/**** added by chilong 11/11/2001 ****/
#include <stdio.h>
#include "filesys/include/FileSys.h"
#include "../include/fat1x.h"
/**** added by chilong 11/11/2001 ****/
//#include "../include/fat1x.h"
/**** added by chilong temporarily 11/11/2001 ****/
#define TICK_HZ 32
/**** added by chilong temporarily 11/11/2001 ****/
#ifdef FAT_USE_PCMCIA
//#include "../../pcmcia/include/cf_typedef.h"
#include "../include/ata_pcc.h"
// #include "pcmcia/include/pcmcia.h"//thhuang added it
#ifdef __WIN32__
#include"../../diskEmu/include/cf_emu.h"
#else
#include "pcmcia/include/pcm_io.h"
#include "pcmcia/include/pcmcia.h"
#endif
#elif defined(FAT_USE_SMC)
#include "../../nflash/include/nflash.h"
#include "../include/ata_pcc.h"
#else
#include "../../../../../driver/mmc/include/mmc_drv.h"
#include "../include/ata_pcc.h"
#endif
#ifdef FAT_ID
///* marked by chilong 11/11/2001
#ifdef FAT_ATA_CACHE_ON
// ATA cache
struct FAT_sectorCache FATAtaCache[FAT1X_ATA_TAG_NO][FAT1X_ATA_BLOCK_PER_TAG];
#ifdef FAT1X_DEBUG
extern unsigned long FATAtaReadHit; // ATA read hit count
extern unsigned long FATAtaReadMiss; // ATA read miss count
extern unsigned long FATAtaWriteHit; // ATA write hit count
extern unsigned long FATAtaWriteMiss; // ATA write miss count
extern unsigned long FATAtaSwap; // ATA cache swap count
extern unsigned long FATAtaFlush; // ATA cache flush count
#endif
#endif
// marked by chilong 11/11/2001 */
/* init.c */
extern int FATIsLBA;
extern int FATHdDriver;
extern int FATAtaSemaphoreID;
#ifdef FAT_USE_PCMCIA//thhuang added it
#if (PCB_V >= 5 )
extern U16 gCFCardStatus;
#endif
#endif
/**** added by chilong 11/11/2001 ****/
#ifdef PCMCIA_DEBUG
extern unsigned char debugString[80];
#endif
// this line needs to be deleted after the test on rtos is ok
//unsigned char debugString[80];
/**** added by chilong 11/11/2001 ****/
/*************************************************************
Fuction: WAIT_COMMAND_AVAILABLE
**************************************************************/
#ifdef FAT_USE_PCMCIA
unsigned short WAIT_COMMAND_AVAILABLE(int driver, unsigned long howLong)
{
unsigned short result;
unsigned long timeout;
/**** added by chilong temporaily 11/11/2001 ****/
// unsigned int i = 0;
/**** added by chilong temporaily 11/11/2001 ****/
/**** added by chilong 11/11/2001 ****/
#ifdef PCMCIA_DEBUG
printString("WAIT_COMMAND_AVAILABLE\n\r");
#endif
timeout = howLong + sc_getTimeStamp();
/**** added by chilong 11/11/2001 ****/
// timeout = howLong + 1000;
/**** added by chilong 11/11/2001 ****/
/* Wait until BSY = 0 */
#ifdef FAT_USE_PCMCIA
result = pcmInport(driver + STATUS_REG);
#else
result = inportb(driver + STATUS_REG);
result = result & 0x00FF;
#endif
while ((result & ATA_COMMAND_BUSY) == ATA_COMMAND_BUSY)
{
if (timeout < sc_getTimeStamp())
break;
#if( PCB_V >=5 )
// if card removed , break of the wait loop immediately
if( gCFCardStatus != CF_CARD_IN )
break;
#endif
#ifdef FAT_USE_PCMCIA
result = pcmInport(driver + STATUS_REG);
#else
result = inportb(driver + STATUS_REG);
result = result & 0x00FF;
#endif
}
return result;
}
#endif
/*************************************************************
Fuction: GET_ERROR_RESULT
Get the error status reg.
return value: ATA_OK, ATA_FAILURE, ATA_FAIL_BBK, ATA_FAIL_UNC, ATA_FAIL_IDNF
ATA_FAIL_ABRT, ATA_FAIL_AMNF
**************************************************************/
#ifdef FAT_USE_PCMCIA
unsigned short GET_ERROR_RESULT(int driver)
{
unsigned short status;
status = WAIT_COMMAND_AVAILABLE(driver, FAT_TIMEOUT * TICK_HZ);
if (((status & ATA_COMMAND_BUSY) == ATA_COMMAND_BUSY) || ((status & ATA_DRIVE_READY) != ATA_DRIVE_READY))
{
#ifdef PCMCIA_DEBUG
printString("GET_ERROR_RESULT error\n\r");
#endif
return ATA_FAILURE;
}
#ifdef FAT_USE_PCMCIA
status = pcmInport(driver + DUP_ERROR_REG);
// status = (status & 0xFF00) >> 8;
status = status & 0x00FF;
#else
status = inportb(driver + DUP_ERROR_REG);
status = status & 0x00FF;
#endif
if (status & ERR_ALL)
{
if (status& ERR_BBK)
return ATA_FAIL_BBK;
if (status & ERR_UNC)
return ATA_FAIL_UNC;
#if 0//2003.3.24, don't know why be setted on sandisk 64MB
if (status & ERR_IDNF)
return ATA_FAIL_IDNF;
#endif
if (status & ERR_ABRT)
return ATA_FAIL_ABRT;
if (status & ERR_AMNF)
return ATA_FAIL_AMNF;
}
return ATA_OK;
}
#endif
/*************************************************************
Function: WAIT_COMMAND_RESULT
**************************************************************/
#ifdef FAT_USE_PCMCIA
unsigned short WAIT_COMMAND_RESULT(int driver, unsigned long howLong)
{
unsigned short result;
unsigned long timeout;
timeout = howLong + sc_getTimeStamp();
/* Wait until BSY = 0 & DRDY = 1 */
#ifdef FAT_USE_PCMCIA
result = pcmInport(driver + STATUS_REG);
#else
result = inportb(driver + STATUS_REG);
result = result & 0x00FF;
#endif
while (((result & ATA_COMMAND_BUSY) == ATA_COMMAND_BUSY) || ((result & ATA_DATA_READY) != ATA_DATA_READY))
{
if ((result & ATA_DATA_ERROR_AND_READY) == ATA_DATA_ERROR_AND_READY)
{
break;
}
else
{
if (timeout < sc_getTimeStamp())
break;
}
#if( PCB_V >= 5)
// if card removed , break of the wait loop immediately
if( gCFCardStatus != CF_CARD_IN )
break;
#endif
#ifdef FAT_USE_PCMCIA
result = pcmInport(driver + STATUS_REG);
#else
result = inportb(driver + STATUS_REG);
result = result & 0x00FF;
#endif
}
return result;
}
#endif
/*************************************************************
Function: ATA_GET_PARAMETER
**************************************************************/
#ifdef FAT_USE_PCMCIA
unsigned short ATA_GET_PARAMETER(int driver, unsigned short *buf)
{
unsigned short status;
short i;
unsigned short temp;
#ifdef PCMCIA_DEBUG
printString("ATA_GET_PARAMETER\n\r");
#endif
/**** added by chilong 11/11/2001 ****/
/* 0. Soft reset */
// outportb(driver + CONTROL_REG, 0x04);
// outportb(driver + CONTROL_REG, 0x00);
/* 1. Wait for the time ATA-Register can accept COMMAND */
status = WAIT_COMMAND_AVAILABLE(driver, FAT_TIMEOUT * TICK_HZ);
if ((status & ATA_COMMAND_BUSY) == ATA_COMMAND_BUSY)
{
#ifdef PCMCIA_DEBUG
printString("ATA_GET_PARAMETER: 1st step error\n\r");
#endif
return ATA_FAILURE;
}
#ifdef FAT_USE_PCMCIA
//#ifdef BIG_ENDIAN
// temp = (unsigned short)ATA_MASTER_DRV;
// if (FATIsLBA != FALSE)
// temp |= (unsigned short)ATA_LBA_MODE;
// temp = temp << 8;
// temp |= (unsigned short)ID_ATA_CMD;
//#else
temp = (unsigned short)ID_ATA_CMD;
temp = temp << 8;
temp |= (unsigned short)ATA_MASTER_DRV;
if (FATIsLBA != FALSE)
temp |= (unsigned short)ATA_LBA_MODE;
//#endif
pcmOutport(driver + DEV_HEADER_REG, temp);
#else
// 2. SELECT THE DISK-CONTROLLER
if (FATIsLBA == FALSE)
outportb(driver + DEV_HEADER_REG, ATA_MASTER_DRV);
else
outportb(driver + DEV_HEADER_REG, ATA_MASTER_DRV | ATA_LBA_MODE);
// 3. Wait for the time ATA-Register can accept COMMAND
status = WAIT_COMMAND_AVAILABLE(driver, FAT_TIMEOUT * TICK_HZ);
status = inportb(driver + STATUS_REG);
if (((status & ATA_COMMAND_BUSY) == ATA_COMMAND_BUSY) || ((status & ATA_DRIVE_READY) != ATA_DRIVE_READY))
{
#ifdef PCMCIA_DEBUG
printString("3th step error\n\r");
#endif
return ATA_FAILURE;
}
// 4. send identify ATA command
outportb(driver + COMMAND_REG, ID_ATA_CMD);
#endif
/* 5. Wait command executed completely */
status = WAIT_COMMAND_AVAILABLE(driver, FAT_TIMEOUT * TICK_HZ);
#ifdef FAT_USE_PCMCIA
status = pcmInport(driver + STATUS_REG);
#else
status = inportb(driver + STATUS_REG);
status = result & 0x00FF;
#endif
if (((status & ATA_COMMAND_BUSY) == ATA_COMMAND_BUSY) || ((status & ATA_DATA_READY) != ATA_DATA_READY))
{
if (((status & ATA_COMMAND_BUSY) == ATA_COMMAND_BUSY) || ((status & ATA_COMMAND_ERROR) == ATA_COMMAND_ERROR))
{
#ifdef PCMCIA_DEBUG
printString("5th step error\n\r");
#endif
return ATA_FAILURE;
}
}
/* 6. Move the parameter to caller's dataBuffer */
for (i = 0; i < WORDS_PER_SECTOR; i++)
{
#ifdef FAT_USE_PCMCIA
temp = pcmInport(driver + DATA_REG);
#ifdef BIG_ENDIAN
if ((i < 23) && (i > 46))
#else
if ((i >= 23) && (i <= 46))
#endif
*(buf + i) = ((temp & 0xFF00) >> 8) | ((temp & 0x00FF) << 8);
else
*(buf + i) = temp;
/**** added by chilong 11/11/2001 ****/
#ifdef PCMCIA_DEBUG
if (i % 8 == 0)
printString("\n\r");
sprintf(debugString, "%.2x ", (*(buf+i) >> 8) & 0xFF);
printString(debugString);
sprintf(debugString, "%.2x ", *(buf+i) & 0xFF);
printString(debugString);
#endif
/**** added by chilong 11/11/2001 ****/
#else
*(buf + i) = inportw(driver + DATA_REG);
#endif
}
return ATA_OK;
}
#endif
/*************************************************************
Function: ATA_READ_SECTOR
Read N sectors from drive
**************************************************************/
unsigned short ATA_READ_SECTOR(int driver, unsigned char secCount, unsigned long startSec, unsigned short *buf)
{
#ifdef FAT_USE_SMC
unsigned char i;
for ( i=0 ; i<secCount; i++ )
{
if ( LG_ReadFrame( (startSec+i)*SECTOR_SIZE, (unsigned char *) (buf+i*WORDS_PER_SECTOR) ) == NFLASH_FAIL )
return ATA_FAILURE;
}
return ATA_OK;
#elif defined FAT_USE_MMC
unsigned char i;
for ( i=0 ; i<secCount; i++ )
{
if ( MMC_ReadSector( (unsigned int *) (buf+i*WORDS_PER_SECTOR), startSec+i ) != SM_OK )
return ATA_FAILURE;
}
return ATA_OK;
#else
struct FAT_C_H_S readSec;
unsigned short status;
int i;
unsigned short* base;
if( secCount <= 0 )
return ATA_OK;
// read the sector from disk
FAT_logical_sector_to_chs(startSec, &readSec);
// 0. Wait for the time ATA-Register can accept COMMAND
status = WAIT_COMMAND_AVAILABLE(driver, FAT_TIMEOUT * TICK_HZ);
if ((status & ATA_COMMAND_BUSY) == ATA_COMMAND_BUSY)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -