📄 ata.c
字号:
/*
*******************************************************************************
* Magic Pixel
* 5F, No.3, Creation Road III, Science_Based
* Industrial Park, Hsinchu, Taiwan, R.O.C
* (c) Copyright 2004, Magic Pixel Inc, Hsinchu, Taiwan
*
* All rights reserved. Magic Pixel's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code contains
* confidential, trad secret material. Any attempt or participation in
* deciphering, decoding, reverse engineering or in ay way altering the source
* code is strictly prohibited, unless the prior written consent of Magic
* Pixel is obtained.
*
* Filename : ata.c
* Programmer(s) :
* Created :
* Descriptions :
*******************************************************************************
*/
/*
// define this module show debug message or not, 0 : disable, 1 : enable
*/
#define LOCAL_DEBUG_ENABLE 0
/*
// Include section
*/
#include "global612.h"
#include "mpTrace.h"
#include "uti.h"
#include "ata.h"
#include "devio.h"
#include "taskid.h"
#include "ui.h"
#include "utilregfile.h"
//#include "fs.h"
/*
// Constant declarations
*/
#if HD_ENABLE
#define ATA_TIMEOUT 0x400000
// define the HD command code
#define ATA_READ_SECTOR 0x2000
#define ATA_READ_SECTOR_EX 0x2400
#define ATA_WRITE_SECTOR 0x3000
#define ATA_WRITE_SECTOR_EXT 0x3400
#define ATA_READ_VERIFY 0x4000
#define ATA_READ_MULTIPLE 0xc400
#define ATA_WRITE_MULTIPLE 0xc500
#define ATA_SET_MULTIPLE 0xc600
#define ATA_IDENTIFY_DRIVE 0xec00
#define ATA_FEATURE_SET 0xef00
#define ATA_READ_DMA 0xc800
#define ATA_WRITE_DMA 0xca00
#define ATA_WRITE_DMA_EXT 0x3500
#define ATA_SETMAX_ADDRESS_EX 0x3700
#define ATA_READ_DMA_EX 0x2500
// define ATA tramsfer mode
#define ATA_PIO_MODE 0x00
#define ATA_MULTI_DMA_MODE 0x20
#define ATA_ULTRA_DMA_MODE 0x40
// ATA register definition
// field define for ATA DMA control register
#define ATA_DMA_IN 0x00000000
#define ATA_DMA_OUT 0x00020000
#define ATA_MULTI_DMA 0x00010000
#define ATA_ULTRA_DMA 0x00050000
#define ATA_NONE_DMA 0x00000000
#define ATA_PIO_TIMING 0x00298321
#define ATA_MDMA0_TIMING 0x00000d23
#define ATA_MDMA1_TIMING 0x00000952
#define ATA_MDMA2_TIMING 0x00000101
#define ATA_UDMA0_TIMING 0x0000422b
#define ATA_UDMA1_TIMING 0x000021ab
#define ATA_UDMA2_TIMING 0x0000192b
#define ATA_UDMA3_TIMING 0x000010ab
#define ATA_UDMA4_TIMING 0x000008ab
#define ATA_DELAY 0
#define HD_ICAUSE BIT2
///
///@defgroup ATA HardDisk
///@ingroup CONSTANT
///@{
///@}
/*
// Structure declarations
*/
struct ST_ATAINFO_TAG
{
DWORD dwAtaDmaMode;
WORD wDeviceNum;
WORD wMultiSector;
DWORD dwCapacity;
};
/*
// Type declarations
*/
typedef struct ST_ATAINFO_TAG ST_ATAINFO;
/*
// Variable declarations
*/
static ST_ATAINFO sInfo;
static BYTE bDescriptor[2] = "HD";
#pragma alignvar(4)
/*
// Static function prototype
*/
static void CommandProcess(void *pMcardDev);
static void WaitDelay(WORD wCount);
static void Select(void);
static void DeSelect(void);
static SWORD DmaWaitDataRdy(void);
static SWORD PioWaitDataRdy(void);
static SWORD WaitReady(void);
static DWORD SetParameters(DWORD dwLba, DWORD dwCount);
static void SetCommand(WORD wCommand);
static SWORD SetTransMode(BYTE bMode);
static SWORD PIORead(DWORD dwBuffer, WORD wSectorCnt);
static SWORD PIOWrite(DWORD dwBuffer, WORD wSectorCnt);
static SWORD DMARead(DWORD dwBuffer, WORD wSectorCnt);
static SWORD DMAWrite(DWORD dwBuffer, WORD wSectorCnt);
static SWORD DataRead(DWORD dwBuffer, DWORD dwLba, DWORD dwCount);
static SWORD DataWrite(DWORD dwBuffer, DWORD dwLba, DWORD dwCount);
static BYTE CalBit1(BYTE bValue);
static SWORD Identify(void);
static SWORD PowerOnInit(void);
/*
// Definition of internal functions
*/
void AtaInit(ST_MCARD_DEV * sDev)
{
sDev->pbDescriptor = bDescriptor;
sDev->dwLunNum = HD_LUN_NUM;
sDev->wMcardType = HD;
sDev->Flag.Installed = 1;
sDev->CommandProcess = CommandProcess;
}
/*
// Definition of local functions
*/
static void CommandProcess(void *pMcardDev)
{
register UART *sUart;
ST_MCARD_MAIL *sMcardRMail;
register ST_MCARD_DEV *pDev = ((ST_MCARD_DEV *) pMcardDev);
sMcardRMail = ((ST_MCARD_DEV *) pMcardDev)->sMcardRMail;
Select();
switch (sMcardRMail->wCmd)
{
case INIT_CARD_CMD:
if (!((ST_MCARD_DEV *) pMcardDev)->Flag.Detected)
{
//card in
((ST_MCARD_DEV *) pMcardDev)->Flag.Detected = 1;
if ((((ST_MCARD_DEV *) pMcardDev)->swStatus = PowerOnInit()))
{
((ST_MCARD_DEV *) pMcardDev)->Flag.Detected = 0;
((ST_MCARD_DEV *) pMcardDev)->Flag.Present = 0;
((ST_MCARD_DEV *) pMcardDev)->dwCapacity = sInfo.dwCapacity;
((ST_MCARD_DEV *) pMcardDev)->wSectorSize = MCARD_SECTOR_SIZE;
//McardSetCurLun(pDev->dwLunNum, NULL_DEVICE);
}
else
{
((ST_MCARD_DEV *) pMcardDev)->wRenewCounter++;
((ST_MCARD_DEV *) pMcardDev)->Flag.Present = 1;
((ST_MCARD_DEV *) pMcardDev)->dwCapacity = sInfo.dwCapacity;
((ST_MCARD_DEV *) pMcardDev)->wSectorSize = MCARD_SECTOR_SIZE;
//McardSetCurLun(pDev->dwLunNum, pDev->wMcardType);
//EventSet(UI_EVENT, EVENT_CARD_INIT);
}
}
else
{
//card out
((ST_MCARD_DEV *) pMcardDev)->Flag.Detected = 0;
((ST_MCARD_DEV *) pMcardDev)->Flag.Present = 0;
((ST_MCARD_DEV *) pMcardDev)->Flag.ReadOnly = 0;
((ST_MCARD_DEV *) pMcardDev)->Flag.PipeEnable = 0;
((ST_MCARD_DEV *) pMcardDev)->swStatus = 0;
((ST_MCARD_DEV *) pMcardDev)->dwCapacity = 0;
((ST_MCARD_DEV *) pMcardDev)->wSectorSize = 0;
McardSetCurLun(pDev->dwLunNum, NULL_DEVICE);
}
break;
case REMOVE_CARD_CMD: //Athena 03.11.2006 seperate card in & out
//card out
((ST_MCARD_DEV *) pMcardDev)->Flag.Detected = 0;
((ST_MCARD_DEV *) pMcardDev)->Flag.Present = 0;
((ST_MCARD_DEV *) pMcardDev)->Flag.ReadOnly = 0;
((ST_MCARD_DEV *) pMcardDev)->Flag.PipeEnable = 0;
((ST_MCARD_DEV *) pMcardDev)->swStatus = 0;
((ST_MCARD_DEV *) pMcardDev)->dwCapacity = 0;
((ST_MCARD_DEV *) pMcardDev)->wSectorSize = 0;
McardSetCurLun(pDev->dwLunNum, NULL_DEVICE);
break;
case READ_PAGE_CMD:
((ST_MCARD_DEV *) pMcardDev)->swStatus =
DataRead(sMcardRMail->dwBuffer, sMcardRMail->dwBlockAddr, sMcardRMail->dwBlockCount);
break;
case WRITE_PAGE_CMD:
((ST_MCARD_DEV *) pMcardDev)->swStatus =
DataWrite(sMcardRMail->dwBuffer, sMcardRMail->dwBlockAddr, sMcardRMail->dwBlockCount);
break;
case FORMAT_CMD:
default:
MP_DEBUG("-E- ATA INVALID CMD");
break;
}
DeSelect();
}
static void WaitDelay(WORD wCount)
{
WORD i, j;
for (i = 0; i < wCount; i++)
{
for (j = 0; j < 0x80; j++);
}
}
static void Select(void)
{
register MCARD *sMcard;
register GPIO *sGpio;
register UART *sUart;
register ATA *sAta;
sAta = (ATA *) (ATA_BASE);
McardSetClock(1);//set ata clock as PLL1/4
sGpio = (GPIO *) (GPIO_BASE);
///////////////////////////////
sGpio->Fgpcfg[0] = 0x0000ffff;
//??sGpio->Fgpcfg[1] &= ~0x06070000; // config Fgpio[16] as outpt for FPGA bug (control by software)
//??sGpio->Fgpcfg[1] |= 0x0000607; // config Fgpio[16] as outpt for FPGA bug (control by software)
sGpio->Fgpcfg[2] &= ~0x00260000;
sGpio->Fgpcfg[2] |= 0x00000026;
sGpio->Fgpcfg[3] &= ~0x00070000;
sGpio->Fgpcfg[3] |= 0x00000007;
sGpio->Fgpcfg[0] = 0x0000FFFF;
sGpio->Fgpcfg[1] = 0x00000607;
sGpio->Fgpcfg[2] = 0x00004026;
sGpio->Fgpcfg[3] = 0x00000187;
sMcard = (MCARD *) MCARD_BASE;
sMcard->McardC = 0x00000100; // enable ATA module
sAta->AtaSta = 0x00000001;
sAta->AtaSta = 0x00000000;
sAta->AtaPioTim = 0x00000108; //12109
sAta->AtaMdmaTim = 0x00000088;
sAta->AtaDevice = sInfo.wDeviceNum;
WaitDelay(5);
}
static void DeSelect(void)
{
MCARD *sMcard;
sMcard = (MCARD *) MCARD_BASE;
sMcard->McardC = 0;
}
static SWORD DmaWaitDataRdy(void)
{
register ATA *sAta;
DWORD dwTimeOut;
sAta = (ATA *) (ATA_BASE);
dwTimeOut = ATA_TIMEOUT;
while (dwTimeOut)
{
if ((sAta->AtaSta & 0x00000020)) // wait DMARQ
{
return PASS;
}
WaitDelay(1);
dwTimeOut--;
}
return FAIL;
}
static SWORD PioWaitDataRdy(void)
{
register ATA *sAta;
DWORD dwTimeOut;
sAta = (ATA *) (ATA_BASE);
dwTimeOut = ATA_TIMEOUT;
while (dwTimeOut)
{
if ((sAta->AtaStatusCommand & 0x8800) == 0x0800) // wait BSY=0 and DRQ=1
{
//MP_DEBUG("PioWaitDataRdy success!!!!!!!!!!!!");
return PASS;
}
WaitDelay(1);
dwTimeOut--;
}
return FAIL;
}
static SWORD WaitReady(void)
{
register ATA *sAta;
DWORD dwTimeOut;
sAta = (ATA *) (ATA_BASE);
dwTimeOut = ATA_TIMEOUT;
while (dwTimeOut)
{
if (!(sAta->AtaStatusCommand & 0x8000)) // wait BSY=0 and DRQ=0
{
return PASS;
}
WaitDelay(1);
dwTimeOut--;
}
return FAIL;
}
// Set ATA command register, and return the number of sector read
#if 1
static DWORD SetParameters(DWORD dwLba, DWORD dwCount)
{
register ATA *sAta;
DWORD dwTemp;
BYTE i,j;
j=1;
sAta = (ATA *) (ATA_BASE);
if(dwLba & 0xf0000000)
j=2;
for(i=0;i<j;i++)
{
if((i==0) && (j==1))
dwTemp = dwLba;
else if((i==0) && (j==2))
dwTemp = (dwLba & 0xff000000)>>24;
else if((i==1) && (j==2))
dwTemp = dwLba & 0x00ffffff;
sAta->AtaLbaL = (dwTemp & 0x000000ff) << 8;
WaitDelay(1);
sAta->AtaLbaM = dwTemp & 0x0000ff00;
WaitDelay(1);
dwTemp >>= 8;
sAta->AtaLbaH = dwTemp & 0x0000ff00;
WaitDelay(1);
if(!((i==0) && (j==2)))
{
dwTemp >>= 8;
sAta->AtaDevice = (dwTemp & 0x0000ff00) | (sInfo.wDeviceNum);
WaitDelay(1);
if (dwCount >= 256)
{
sAta->AtaSectorCnt = 0;
return 256;
}
else
{
sAta->AtaSectorCnt = (BYTE) dwCount << 8;
return dwCount;
}
}
if((i==0) &&(j==2))
{
if(dwCount>=256)
sAta->AtaSectorCnt = (0x01<<8);
else
sAta->AtaSectorCnt = 0x00;
}
}
}
#else
static DWORD SetParameters(DWORD dwLba, DWORD dwCount)
{
register ATA *sAta;
DWORD dwTemp;
sAta = (ATA *) (ATA_BASE);
dwTemp = dwLba;
sAta->AtaLbaL = (dwTemp & 0x000000ff) << 8;
WaitDelay(1);
sAta->AtaLbaM = dwTemp & 0x0000ff00;
WaitDelay(1);
dwTemp >>= 8;
sAta->AtaLbaH = dwTemp & 0x0000ff00;
WaitDelay(1);
dwTemp >>= 8;
sAta->AtaDevice = (dwTemp & 0x0000ff00) | (sInfo.wDeviceNum);
WaitDelay(1);
if (dwCount >= 256)
{
sAta->AtaSectorCnt = 0;
return 256;
}
else
{
sAta->AtaSectorCnt = (BYTE) dwCount << 8;
return dwCount;
}
}
#endif
static void SetCommand(WORD wCommand)
{
register ATA *sAta;
sAta = (ATA *) (ATA_BASE);
sAta->AtaStatusCommand = wCommand;
WaitDelay(1);
}
/*
ATA set transfer mode
*/
static SWORD SetTransMode(BYTE bMode)
{
register ATA *sAta;
DWORD dwTemp;
sAta = (ATA *) ATA_BASE;
sAta->AtaDevice = sInfo.wDeviceNum;
WaitDelay(1);
sAta->AtaErrorFeature = 0x0300; // set transfer mode subcommand
WaitDelay(1);
sAta->AtaSectorCnt = bMode << 8;
WaitDelay(1);
SetCommand(ATA_FEATURE_SET);
WaitDelay(1);
do
{
dwTemp = sAta->AtaStatusCommand;
WaitDelay(1);
if (dwTemp & 0x0100)
{
MP_DEBUG("Set Trans Mode fail");
return FAIL;
}
}
while (dwTemp & 0x8000);
return PASS;
}
static SWORD PIORead(DWORD dwBuffer, WORD wSectorCnt)
{
register ATA *sAta;
WORD wTmpSectorCnt;
WORD *pwTmpBufferC, *pwTmpBufferE;
sAta = (ATA *) (ATA_BASE);
pwTmpBufferC = (WORD *) dwBuffer;
pwTmpBufferE = pwTmpBufferC + 256;
MP_DEBUG1("PIO read begin %d!!!!!!!",wSectorCnt);
//TimerDelay(ATA_DELAY);
for (wTmpSectorCnt = 0; wTmpSectorCnt < wSectorCnt; wTmpSectorCnt++)
{
if (PioWaitDataRdy() != PASS)
{
return FAIL;
}
while (pwTmpBufferC < pwTmpBufferE)
{
*pwTmpBufferC = (WORD) sAta->AtaData;
WaitDelay(1);
pwTmpBufferC++;
}
pwTmpBufferE += 256;
}
return PASS;
}
static SWORD PIOWrite(DWORD dwBuffer, WORD wSectorCnt)
{
register ATA *sAta;
WORD wTmpSectorCnt;
WORD *pwTmpBufferC, *pwTmpBufferE;
sAta = (ATA *) (ATA_BASE);
pwTmpBufferC = (WORD *) dwBuffer;
pwTmpBufferE = pwTmpBufferC + 256;
//TimerDelay(ATA_DELAY);
for (wTmpSectorCnt = 0; wTmpSectorCnt < wSectorCnt; wTmpSectorCnt++)
{
if (PioWaitDataRdy() != PASS)
{
return FAIL;
}
while (pwTmpBufferC < pwTmpBufferE)
{
sAta->AtaData = (DWORD) * pwTmpBufferC;
WaitDelay(1);
pwTmpBufferC++;
}
pwTmpBufferE += 256;
}
return PASS;
}
static SWORD DMARead(DWORD dwBuffer, WORD wSectorCnt)
{
register CHANNEL *sChannel;
register ATA *sAta;
register GPIO *sGpio;
DWORD dwcount = ATA_TIMEOUT;
sGpio = (GPIO *) (GPIO_BASE);
//__asm("break 100");
if (!wSectorCnt)
{
UartOutText("DMA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -