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