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

📄 ata.c

📁 三星2413芯片的测试代码,对进行驱动开发很有帮助.
💻 C
📖 第 1 页 / 共 3 页
字号:
/*=========================================================================
 *                	S5H5002 ata source.
 *=========================================================================
 * File: ata.c 
 *
 * Date: 2002.09.16
 *
 * Author: Cha,  JeongIl   E-mail: noface.cha@samsung.com
 *
 * Description:
 *
 *=========================================================================
 */
 
#include <stdio.h>
#include <stdlib.h>

#include "2413addr.h"
#include "System.h"
#include "Exception.h"
#include "Console.h"
#include "def.h"
#include "ata.h"
#include "console.h"

//#include "myLIB.h"

//#include "system.h"

#define Disp        printf
#define Dbg         printf
#define DBG_ATA

static volatile U32 bIsDone;
static volatile U32 bIsXferDone;


//#define Assert(a) {if (!(a)) {Disp("\n %s(line %d)\n", __FILE__, __LINE__); exit(0);}}

#ifdef DBG_ATA
#define DbgAta(x) Dbg x
#else
#define DbgAta(x) 0;
#endif

#define Outp32(addr, data) (*(volatile U32 *)(addr) = (data))
#define Outp16(addr, data) (*(volatile U16 *)(addr) = (data))
#define Outp8(addr, data)  (*(volatile U8 *)(addr) = (data))
#define Inp32(addr, data) (data = (*(volatile U32 *)(addr)))
#define Inp16(addr, data) (data = (*(volatile U16 *)(addr)))
#define Inp8(addr, data)  (data = (*(volatile U16 *)(addr)))
#define Input32(addr) (*(volatile U32 *)(addr))


extern U32 ARMCLK, HCLK, PCLK;
U32 m_uCfgReg;
struct ATA_DEV_INFO m_oDevice[2];
int m_eMode;
void SetAtaMode(int mode) { m_eMode = mode; }

static const U32 uPreScale = 250;//gh0522.cha PCLK/8/(10*uAdjust); // It makes about 10kHz
int count;
	

/*
#define ATA_INT_SBUF_EMPTY			4
#define ATA_INT_TBUF_FULL			3
#define ATA_INT_IRQ					2
#define ATA_INT_UDMA_HOLD			1
#define ATA_INT_XFER_DONE			0
*/
/*=========================================================================
 *          	      ata controller error type
 *=========================================================================
 */
#define TIME_OUT_VALUE				2400 //1200
#define ATA_ABSENT					0
#define ATA_ATA						1
#define ATA_ATAPI					2
#define ATA_SECTORSIZE				512

//-------------------------------------------------------------------------
#define DEV_ACC_READY		0x2
#define PIO_DATA_READY	0x1

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

#define INT_FIU      21

//+daedoo 060919
#define ALL_ATA_INT_MASK	0xffffffe2


void __irq Isr_Ata(void)
{
	U32 i, nthBit, temp1, temp2, temp_ATA_IRQ;

	rINTSUBMSK |= BIT_SUB_CF;
	rINTMSK |= BIT_SDI_CF;
	
#if 1

	for(i=0;i<SRC_INT_NUM;i++) {
		Inp32(ATA_IRQ, temp1);
		Inp32(ATA_IRQ_MASK, temp2);

		//printf("ATA_IRQ = 0x%x\n", temp1);
		//printf("ATA_IRQ_MASK = 0x%x\n", temp2);

		if(((temp1&(~temp2))>>i)&0x01) 
			break;
	}

	nthBit = i;

	if(nthBit == 0)
	{
		//printf("D\n");
		ATA_ClearPending(ATA_INT_XFER_DONE);
		IsDmaDone();
		bIsXferDone = true;
	}
	
	else if (nthBit == 2)
	{
		//printf("A\n");
		ATA_ClearPending(ATA_INT_IRQ);
		bIsDone = true;
	}

	//rSUBSRCPND |= (BIT_SUB_CF);
	//ClearPending(BIT_SDI_CF);

	if (nthBit == 3)
	{
		//printf("T\n");
		ATA_ClearPending(ATA_INT_TBUF_FULL);
	}

	else if (nthBit == 4)
	{
		//printf("S\n");
		ATA_ClearPending(ATA_INT_SBUF_EMPTY);
	}

#else

	//Inp32(ATA_IRQ, temp_ATA_IRQ);	
	//printf("ATA_IRQ = 0x%x\n", temp_ATA_IRQ);
	
	if(temp_ATA_IRQ == 1)
	{
		printf("D\n");
		ATA_ClearPending(ATA_INT_XFER_DONE);
		printf("D-1\n");
		IsDmaDone();
		printf("D-2\n");
		bIsXferDone = true;
	}
	
	else if (temp_ATA_IRQ == 4)
	{
		printf("A\n");
		ATA_ClearPending(ATA_INT_IRQ);
		bIsDone = true;
	}

	ClearPending(BIT_SDI_CF);
	rSUBSRCPND |= (BIT_SUB_CF);

	if (temp_ATA_IRQ == 8)
	{
		printf("T\n");
		ATA_ClearPending(ATA_INT_TBUF_FULL);
	}

	else if (temp_ATA_IRQ == 0x10)
	{
		printf("S\n");
		ATA_ClearPending(ATA_INT_SBUF_EMPTY);
	}

#endif	

	rSUBSRCPND |= (BIT_SUB_CF);
	ClearPending(BIT_SDI_CF);

	rINTSUBMSK &= ~(BIT_SUB_CF);
	rINTMSK &= ~(BIT_SDI_CF);

	//ATA_ClearAllInterrupt();

}


void * func_ata_test[][2]=
{	
	//ATA Function Test Item
    	(void *)TestPioMode,              	"Test ATA PIO Mode. ",
	(void *)TestPioIntMode,		"Test ATA PIO INT Mode",
    	(void *)TestPioDmaMode,		"Test ATA PIO DMA Mode. ", 
    	(void *)TestPioDmaIntMode,	"Test ATA PIO DMA INT Mode",
    	0,0
};
    
void Ch23_Ata(void)
{
	int i;
		
	while(1)
	{
		i=0;
		printf("\n\n================== ATA Function Test =====================\n\n");
		
		while(1)
		{   //display menu
			printf("%2d:%s",i,func_ata_test[i][1]);
			i++;
			if((int)(func_ata_test[i][0])==0)
			{
				printf("\n");
				break;
			}
			if((i%1)==0)
			printf("\n");
		}
		printf("\n==========================================================\n");
		printf("Select #Item or Press Enter key to exit : ");
		i = GetIntNum(); //gh0522.cha
		if(i==-1) break;		// return.
		if(i>=0 && (i<((sizeof(func_ata_test)-1)/8)) )	// select and execute...
			( (void (*)(void)) (func_ata_test[i][0]) )();
	}
	
}

void FindIntReq(void)
{

}


void ATA_ClearPending(U32 nbit)
{
	Outp32(ATA_IRQ, (1<<nbit));
}

void ATA_ClearAllInterrupt(void)
{
	Outp32(ATA_IRQ, 0x1f);
	Outp32(ATA_IRQ_MASK, 0xffffffe2);
}

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

void ATA_Reset()
{
	U32 temp;
	
	Inp32(ATA_CFG, temp);
	Outp32(ATA_CFG, temp|0x1);
}

void WaitForDeviceAccessReady(void)
{
	U32 tempRead;

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

U16 GetDataFromDevice() 
{
	U32 tempRead;
	U16 data;
	
	//WaitForDeviceAccessReady();
	Inp32(ATA_PIO_DTR, tempRead);
	
	WaitForDeviceAccessReady();
	Inp32(ATA_PIO_RDATA, tempRead);
	data = (U16)(tempRead&0xFFFF);
	
	return data;
}

U8 ReadDeviceReg(U32 nRegister) 
{
	U32 tempRead;
	U8 data;

	WaitForDeviceAccessReady();
	Inp32(nRegister, tempRead);
	WaitForDeviceAccessReady();
	Inp32(ATA_PIO_RDATA, tempRead);
	data = (U8 )(tempRead&0xFF);
	
	return data;
}

U32 WaitForNoBusyStatus(void)
{
	U8 tempRead;
	
	while(1) 
	{
		tempRead = ReadDeviceReg(DEV_ALTANATE);	//+daedoo why??
		tempRead = ReadDeviceReg(DEV_STATUS);
	
		if((tempRead&STATUS_DEVICE_BUSY) == 0) break;
	}
	return;
}

void WaitForTransferDone(void)
{
	U32 x;

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


void WriteOnTaskFileReg(U32 nRegister,U32 nValue) 
{
	WaitForDeviceAccessReady();
	Outp32(nRegister, nValue);
}


U32 GetMaxSectors()
{
	U32 maxSec;
	
	maxSec = m_oDevice[0].MaxSectors;
	
	return maxSec;
	
}
	
void IdentifyDevice(void) 
{
	U16 readBuffer[256];
	U8 tempBuffer;
	U8 *tempString;
	U32 tBuf[4];
	U8 tempRead;


	int i=0;

	Outp32(ATA_IRQ_MASK, 0xffffffff);

	for (i=0;i<256;i++) readBuffer[i] = 0;
	
	// why??? big endian
	m_uCfgReg |= 0x40; // set Big endian (must be)
	Outp32(ATA_CFG, m_uCfgReg);

	WriteOnTaskFileReg(DEV_DEVICE, 0x40);
	WriteOnTaskFileReg(DEV_COMMAND, IDENTIFYDEVICE);

#if 0
	if (WaitForNoBusyAlternateStatus() == ATA_TIMEOUT) {

	//	DbgAta(("ERROR : busy Time out!!!\n"));

		return;
	}
	//ReadDeviceReg(DEV_STATUS, tempBuffer);
	tempBuffer = ReadDeviceReg(DEV_STATUS);
#elif 1

	WaitForNoBusyStatus();

#endif

	for(i=0; i<ATA_SECTORSIZE/2; i++) 
	{
		readBuffer[i] = GetDataFromDevice();
	}

	WaitForNoBusyStatus();


	//CF CARD Indentification Start
	// CF Serial Number
	tempString = (U8 *)&readBuffer[10];
	DbgAta(("\nSerial Number :"));
	for(i=0;i<20;i++) DbgAta(("%c",*(tempString+i)));

	// CF Serial Model Number
	tempString = (U8 *)&readBuffer[27];
	DbgAta(("\nModel Number :"));
	for(i=0;i<40;i++) DbgAta(("%c",*(tempString+i)));

	// CF Max Sector Size
	tBuf[0] = (U8)(readBuffer[61]&0xff);
	tBuf[1] = (U8)((readBuffer[61]&0xff00)>>8);
	tBuf[2] = (U8)(readBuffer[60]&0xff);
	tBuf[3] = (U8)((readBuffer[60]&0xff00)>>8);
	m_oDevice[0].MaxSectors = (U32)((tBuf[0]<<24)|(tBuf[1]<<16)|(tBuf[2]<<8)|tBuf[3]);
	DbgAta(("\nMax Sectors : %d\n",m_oDevice[0].MaxSectors));

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

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

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

	DbgAta(("Max UDMA Mode : %d\n",m_oDevice[0].MaxUdmaMode));
	DbgAta(("Current UDMA Mode : %d\n",m_oDevice[0].CurrentUdmaMode));
	//CF CARD Indentification End

	m_uCfgReg &= (~0x40); // set Little endian
	Outp32(ATA_CFG, m_uCfgReg);

}

void SetAtaOnOff(U8 OnOff)
{
	U32 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		
	m_uCfgReg &= (~0x40); 
	Outp32(ATA_CFG, m_uCfgReg);
}


void ATA_Init(void)
{
	m_uCfgReg = 0;	//
	
	SetAtaOnOff(1);
	SetLittleEndian();
//	CheckDevice(); 	
}


void SetPioMode(int  pmode) 
{
	U8 nMode = (pmode == PIO0) ? 0 :
				(pmode == PIO1) ? 1 :
				(pmode == PIO2) ? 2 :
				(pmode == PIO3) ? 3 :
				(pmode == PIO4) ? 4 : 0;
	
	U32 uT1;
	U32 uT2;
	U32 uTeoc;
	U32 i;
	
	U32 uPioTime[5];
	U32 m_uPioT1[5] = {200,40,20,50,30};    // min = {70,50,30,30,25};
	U32 m_uPioT2[5] = {300,300,190,130,70}; // min = {290,290,290,80,70};
	U32 m_uPioTeoc[5] = {70,20,0,0,0};  // min = {20,15,10,10,10};
	
	U32 uCycleTime = (U32)(1000000000/HCLK);


	for (i=0; i<5; i++)
	{
		uT1   = (m_uPioT1[i]  /uCycleTime )&0xff;
		uT2   = (m_uPioT2[i]  /uCycleTime )&0xff;
		uTeoc = (m_uPioTeoc[i]/uCycleTime )&0x0f;
		uPioTime[i] = (uTeoc<<12)|(uT2<<4)|uT1;
//		DbgAta(("PIO%dTIME = %x\n", i, uPioTime[i]));
	}
	
	//Outp32(ATA_IRQ, 0xff);
	//Outp32(ATA_IRQ_MASK, ATAPI_MASK);


    WriteOnTaskFileReg(DEV_CONTROL,0);
	WriteOnTaskFileReg(DEV_FEATURE,0x03); //set transfer mode based on value in Sector Count register
	WriteOnTaskFileReg(DEV_SECTOR,0x08|(nMode&0x7)); // PIO flow control transfer mode
	WriteOnTaskFileReg(DEV_LOWLBA,0x00);
	WriteOnTaskFileReg(DEV_MIDLBA,0x00);
	WriteOnTaskFileReg(DEV_HIGHLBA,0x00);
	WriteOnTaskFileReg(DEV_DEVICE,0x40);
	

⌨️ 快捷键说明

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