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

📄 ata.c

📁 三星2443芯片
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "system.h"
#include "etc.h"
#include "ata.h"


#define PERF_TEST_ATA 		0   // overall time
#define PERF_TEST_PIO_D 	0   // only data transfering time
#define PERF_TEST_UDMA_D	0	// only data transfering time

#define DBG_ATA		1


#if DBG_ATA
#define DbgAta(x) printf x
#else
#define DbgAta(x) 0;
#endif

#define CFCON_BASE 0x4B800000

#ifdef CFCON_MODE
#define ATA_MUX           (CFCON_BASE+0x1800)
#define ATA_BASE			(CFCON_BASE+0x1900)
#endif


/*--------------------------------------------------------------*/
/*	ATA Register						                        */
/*--------------------------------------------------------------*/
#define ATA_CONTROL		(ATA_BASE + 0x00)	//ATA0 enable and clock down status
#define ATA_STATUS		(ATA_BASE + 0x04)	//ATA0 status
#define ATA_COMMAND		(ATA_BASE + 0x08)	//ATA0 command
#define ATA_SWRST			(ATA_BASE + 0x0C)	//ATA0 software reset                  
#define ATA_IRQ			(ATA_BASE + 0x10)	//ATA0 interrupt sources
#define ATA_IRQ_MASK		(ATA_BASE + 0x14)	//ATA0 interrupt mask
#define ATA_CFG			(ATA_BASE + 0x18)	//ATA0 configuration for ATA interface               

#define ATA_PIO_TIME		(ATA_BASE + 0x2C)	//ATA0 PIO timing                                    
#define ATA_UDMA_TIME		(ATA_BASE + 0x30)	//ATA0 UDMA timing                                   
#define ATA_XFR_NUM		(ATA_BASE + 0x34)	//ATA0 transfer number                               
#define ATA_XFR_CNT		(ATA_BASE + 0x38)	//ATA0 current transfer count                        
#define ATA_TBUF_START	(ATA_BASE + 0x3C)	//ATA0 start address of track buffer                 
#define ATA_TBUF_SIZE		(ATA_BASE + 0x40)	//ATA0 size of track buffer                          
#define ATA_SBUF_START	(ATA_BASE + 0x44)	//ATA0 start address of Source buffer1               
#define ATA_SBUF_SIZE		(ATA_BASE + 0x48)	//ATA0 size of source buffer1                        
#define ATA_CADR_TBUF		(ATA_BASE + 0x4C)	//ATA0 current write address of track buffer         
#define ATA_CADR_SBUF		(ATA_BASE + 0x50)	//ATA0 current read address of source buffer         
#define ATA_PIO_DTR		(ATA_BASE + 0x54)	//ATA0 PIO device data register                      
#define ATA_PIO_FED		(ATA_BASE + 0x58)	//ATA0 PIO device Feature/Error register             
#define ATA_PIO_SCR		(ATA_BASE + 0x5C)	//ATA0 PIO sector count register                     
#define ATA_PIO_LLR		(ATA_BASE + 0x60)	//ATA0 PIO device LBA low register                   
#define ATA_PIO_LMR		(ATA_BASE + 0x64)	//ATA0 PIO device LBA middle register                
#define ATA_PIO_LHR		(ATA_BASE + 0x68)	//ATA0 PIO device LBA high register                  
#define ATA_PIO_DVR		(ATA_BASE + 0x6C)	//ATA0 PIO device register                           
#define ATA_PIO_CSD		(ATA_BASE + 0x70)	//ATA0 PIO device command/status register            
#define ATA_PIO_DAD		(ATA_BASE + 0x74)	//ATA0 PIO device control/alternate status register  
#define ATA_PIO_READY		(ATA_BASE + 0x78)	//ATA0 PIO data read/write ready                     
#define ATA_PIO_RDATA		(ATA_BASE + 0x7C)	//ATA0 PIO read data from device data register       
#define BUS_FIFO_STATUS	(ATA_BASE + 0x90)	//Internal AHBP fifo status                  
#define ATA_FIFO_STATUS	(ATA_BASE + 0x94)	//Internal ATA0  fifo status                 

/*=========================================================================
 *          	          ata Register Address
 *=========================================================================
 */

#define DEV_ERROR			(ATA_BASE + 0x58)
#define DEV_FEATURE		(ATA_BASE + 0x58)
#define DEV_SECTOR			(ATA_BASE + 0x5c)
#define DEV_LOWLBA		(ATA_BASE + 0x60)
#define DEV_MIDLBA			(ATA_BASE + 0x64)
#define DEV_HIGHLBA		(ATA_BASE + 0x68)
#define DEV_DEVICE			(ATA_BASE + 0x6c)
#define DEV_STATUS			(ATA_BASE + 0x70)
#define DEV_COMMAND		(ATA_BASE + 0x70)
#define DEV_ALTANATE		(ATA_BASE + 0x74)
#define DEV_CONTROL		(ATA_BASE + 0x74)

/*=========================================================================
 *          	               ata Command
 *=========================================================================
 */
#define IDENTIFYDEVICE		0xec
#define READSECTOR			0x20
#define READMULTIPLE		0xc4
#define READDMA			0xc8
#define WRITESECTOR		0x30
#define WRITEMULTIPLE		0xc5
#define WRITEDMA			0xca
#define SETFEATURES		0xEF

//-------------------------------------------------------------------------

#define ATAPI_MASK					0xffffffe0
#define ATA_SECTORSIZE				512

#define STATUS_DEVICE_BUSY	0x80
#define STATUS_DATA_REQUEST	0x58
#define STATUS_ERR				0x1


// only for SMDK b'd
void SetBufferDirection(unsigned int dir); // 060822
void InitBufferControl(void); // 060902
void ChangeBufferControl(ATA_MODE mode); // 060902




unsigned int uCfgReg;
ATA_MODE eMode;	
unsigned int uMaxMultiple;
unsigned int uCurrentMultiple;
unsigned int uMaxSectors;
PIOMODE eMaxPioMode;
PIOMODE eCurrentPioMode;
unsigned int uMaxUdmaMode;
unsigned int uCurrentUdmaMode;



/*=========================================================================
 *          	    ata controller register functions
 *=========================================================================
 */

void SetAtaOnOff(unsigned char OnOff)
{
	unsigned int temp;
	Inp32(ATA_CONTROL, temp);

	if(OnOff==1)
		Outp32(ATA_CONTROL, temp | 0x1);
	else if(OnOff == 0)
		Outp32(ATA_CONTROL, temp &0xfffffffe);
}


void SetLittleEndian(void)
{
	// set Little endian		
	uCfgReg &= (~0x40); 
	Outp32(ATA_CFG, uCfgReg);
}


void SetTransferCommand(ATA_TRANSFER_CMD command)
{
	unsigned char cmd = (command == ATA_CMD_STOP) ? 0 :
			(command == ATA_CMD_START) ? 1 :
			(command == ATA_CMD_ABORT) ? 2 : 3;
	WaitForHostReady(); /// needed
	Outp32(ATA_COMMAND, cmd);
}

void IsTBufFullContinue(bool* status)
{
	unsigned int temp;
	Inp32(ATA_CFG, temp);
	*status = (temp&0x80) ? TRUE : FALSE;
}

void IsSBufEmptyContinue(bool* status)
{
	unsigned int temp;
	Inp32(ATA_CFG, temp);
	*status = (temp&0x100) ? TRUE : FALSE; 
}




/*=========================================================================
 *          	       ata controller register I/O fuctions
 *=========================================================================
 */


void WaitForHostReady(void)
{
	unsigned int tempRead;

	do {
		Inp32(ATA_FIFO_STATUS, tempRead); // modified by Bryan W. Lee (Oct.19th, 2005)
	} while((tempRead>>28)!=0);
}



void ReadDeviceReg(unsigned int nRegister, unsigned char* data) 
{
	unsigned int tempRead;

	WaitForHostReady();
	Inp32(nRegister, tempRead);
	WaitForHostReady();
	Inp32(ATA_PIO_RDATA, tempRead);
	*data = (unsigned char )(tempRead&0xFF);
}

void GetDataFromDevice(unsigned short* data) 
{
	unsigned int tempRead;

	WaitForHostReady();
	Inp32(ATA_PIO_DTR, tempRead);
	WaitForHostReady();
	Inp32(ATA_PIO_RDATA, tempRead);
	*data = (unsigned short)(tempRead&0xFFFF);
}

void WriteOnTaskFileReg(unsigned int nRegister,unsigned int nValue) 
{

	WaitForHostReady();
	Outp32(nRegister, nValue);
}

void PutDataToDevice(unsigned short data) 
{

	WaitForHostReady();
	Outp32(ATA_PIO_DTR, data);
}

void WaitForTransferDone(void)
{
	unsigned int x;

	do {
		WaitForHostReady(); /// needed
		Inp32(ATA_STATUS, x);
	} while((x & 3)!=0);
}


bool WaitForDeviceReady(void)
{
	unsigned char tempRead;

	DbgAta(("\n"));
	while(1) 
	{
		ReadDeviceReg(DEV_ALTANATE, &tempRead);
		ReadDeviceReg(DEV_STATUS, &tempRead);
		DbgAta(("[DS:0x%x] ",tempRead));
		if((tempRead&STATUS_DEVICE_BUSY) == 0) 
			break;
	}
	DbgAta(("\n"));

	return TRUE;
}


void Clear_Pending(unsigned int srcInt)
{
//	Assert(srcInt < SRC_INT_NUM);
	
	Outp32(ATA_IRQ, (1<<srcInt));
}


bool FindInterruptRequest(unsigned int* nthBit)
{
	unsigned int i, temp1, temp2;

	for(i=0;i<SRC_INT_NUM;i++) {
		Inp32(ATA_IRQ, temp1);
		Inp32(ATA_IRQ_MASK, temp2);
		if(((temp1&(~temp2))>>i)&0x01) 
			break;
	}

	*nthBit = i;
	
	if (i == SRC_INT_NUM)
		return FALSE;
	else
		return TRUE;
	
	
}

void ClearAllInterrupt(void)
{
	Outp32(ATA_IRQ, 0xff);
	Outp32(ATA_IRQ_MASK, ATAPI_MASK|(1<<ATA_INT_IRQ));
}


/*=========================================================================
 *          				FIU BASIC routine
 *=========================================================================
 */

void ResetAll(void )
{
	
	// TDelay timer setting
	SetResTDelay(10); // TDelay 1 unit = 10us
	InitTDelayFunc();

	TDelay(203); // 2ms+25us
	
	Outp32(ATA_SWRST, 0x1);	 // CF controller reset
	TDelay(1); // need 5us

	Outp32(ATA_SWRST, 0x0);
	TDelay(200); // need 2ms

	Outp32(ATA_CFG, 0x1); // ata device reset.	
	TDelay(1);

	Outp32(ATA_CFG, 0x0); // ata device no reset.
	TDelay(25000); // need 200ms
}
	


void Init(void)
{
	// TDelay timer setting
	SetResTDelay(10); // TDelay 1 unit = 10us
	InitTDelayFunc();

	// GPIO, EBI setting
	rEBICON |= (1<<10)|(1<<9); // bank3_cfg->CF,bank2_cfg->CF 
    rGPGCON |= (3<<30)|(3<<28)|(3<<26)|(3<<24)|(3<<22); //nCARD_PWREN, RESET_CF,nRE3G_CF,nINPACK,nIREQ_CF
#ifdef __EVT1
	rGPACDH = 0x1aa8a; // GPA10 RDATA_OEN setting
#else
	rGPACON |= (1<<27)|(1<<11)|(1<<14)|(1<<13);// nWE_CF,nOE_CF,nRCS3,nRCS2 enable //S3C2443X01
#endif
	rMISCCR &=(~(1<<30)); // card detect when card is detected ,the bit should be '0'.

	// Buffer direction mode setting for SMDK2443 060902
	InitBufferControl();
	ChangeBufferControl(PIO_CPU);

	// CF controller - True IDE mode setting
	Outp32(ATA_MUX, 0x07); // Output pad disable, Card power off, ATA mode
	TDelay(100);
	Outp32(ATA_MUX, 0x03); // Output pad enable, Card power off, ATA mode
	TDelay(100);
	Outp32(ATA_MUX, 0x01); // Output pad enable, Card power on, ATA mode
	TDelay(40000); // wait for 500ms, be positively necessary

	// Card configuration
	Outp32(ATA_PIO_TIME, 0x1C238);
	Outp32(ATA_UDMA_TIME, 0x20B1362);
	SetLittleEndian();	
	SetAtaOnOff(1);
	TDelay(20000); // wait for 200ms, be positively necessary
	
	uCfgReg = 0;  // configuration register value
}


void IdentifyDevice(void) 
{
	unsigned short readBuffer[ATA_SECTORSIZE/2];
	unsigned char tempBuffer;
	volatile unsigned char *tempString;
	unsigned int tBuf[4];
	int i;

	for (i=0;i<ATA_SECTORSIZE/2;i++)
		readBuffer[i] = 1;

	
	uCfgReg |= 0x40; // set Big endian (must be)
	Outp32(ATA_CFG, uCfgReg);

	Outp32(ATA_IRQ_MASK, 0xffffffff);
	WriteOnTaskFileReg(DEV_DEVICE, 0x40);
	WriteOnTaskFileReg(DEV_COMMAND, IDENTIFYDEVICE);

	WaitForDeviceReady();
    
	printf("\n");
	for(i=0; i<ATA_SECTORSIZE/2; i++) {
		GetDataFromDevice(&readBuffer[i]);
		printf("(DATA:0x%04X) ",readBuffer[i]);
	}
	printf("\n");

	WaitForDeviceReady();

	//
	//verify identify data~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	tempString = (unsigned char *)&readBuffer[10];
	printf("\nSerial Number :");
	for(i=0;i<20;i++) printf("%c",*(tempString+i));

	tempString = (unsigned char *)&readBuffer[27];
	printf("\nModel Number :");
	for(i=0;i<40;i++) printf("%c",*(tempString+i));

	tBuf[0] = (unsigned char)(readBuffer[61]&0xff);
	tBuf[1] = (unsigned char)((readBuffer[61]&0xff00)>>8);
	tBuf[2] = (unsigned char)(readBuffer[60]&0xff);
	tBuf[3] = (unsigned char)((readBuffer[60]&0xff00)>>8);
	uMaxSectors = (unsigned int)((tBuf[0]<<24)|(tBuf[1]<<16)|(tBuf[2]<<8)|tBuf[3]);
	printf("\nMax Sectors : %d\n",uMaxSectors);

	// Caution: readBuffer[x] - Big Endian, so upper byte means LSB..
	uMaxMultiple= (readBuffer[47]>>8)&0xFF;
	printf("\nMax Multiple : %02X\n",uMaxMultiple);
	if (readBuffer[59]&0x1) { //multiple sector setting is valid
		uCurrentMultiple= (readBuffer[59]>>8)&0xFF;
		printf("Current Multiple : %03X\n",uCurrentMultiple);
	}
	
	if ((readBuffer[64]>>8)&0x3 == 1) eMaxPioMode = PIO3;
	else if ((readBuffer[64]>>8)&0x3 == 3) eMaxPioMode = PIO4;
	else eMaxPioMode = PIO2;
	printf("Max PIO Mode : %d\n",eMaxPioMode);

	uMaxUdmaMode =0;
	tempBuffer = readBuffer[88]>>8;
	for(i=4;i>=0;i--) {
		if(tempBuffer&(0x01<<i)) {
			uMaxUdmaMode = i;
			break; 
		}
	}

	uCurrentUdmaMode =0;
	tempBuffer = readBuffer[88]&0x00ff;
	for(i=0;i<5;i++) {
		if(tempBuffer&(0x01<<i)) {
			uCurrentUdmaMode = i;
			break; ///
		}
	}

	printf("Max UDMA Mode : %d\n", uMaxUdmaMode);
	printf("Current UDMA Mode : %d\n", uCurrentUdmaMode);
	//
	//verify identify data~~~~~~~~~~~~~~~~~~~~~~~END
	//

	SetLittleEndian();
}

void GetMaxSectors(unsigned int* maxSec)
{
	*maxSec = uMaxSectors;
}

⌨️ 快捷键说明

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