📄 ata.c
字号:
/**************************************************************************************
*
* Project Name : S3C6400 Validation
*
* Copyright 2006 by Samsung Electronics, Inc.
* All rights reserved.
*
* Project Description :
* This software is only for validating functions of the S3C6400.
* Anybody can use this software without our permission.
*
*--------------------------------------------------------------------------------------
*
* File Name : ata.c
*
* File Description : This file implements the driver functions for CF Controller and PIO/UDMA mode on it.
*
* Author : Sunil,Roe
* Dept. : AP Development Team
* Created Date : 2007/1/26
* Version : 0.1
*
* History
* - Created(Sunil,Roe 2007/1/26)
*
**************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "def.h"
#include "option.h"
#include "library.h"
#include "sfr6400.h"
#include "system.h"
#include "timer.h"
#include "cf.h"
#include "ata.h"
#include "gpio.h"
#define ATA(__n) ( ( volatile oATA_REGS * ) ( g_paATASFRBase[__n] ) )
#define SMDK6400 1
/*=========================================================================
* ata Command
*=========================================================================
*/
#define ATA_CMD_IDENTIFYDEVICE 0xec
#define ATA_CMD_READSECTOR 0x20
#define ATA_CMD_READMULTIPLE 0xc4
#define ATA_CMD_READDMA 0xc8
#define ATA_CMD_WRITESECTOR 0x30
#define ATA_CMD_WRITEMULTIPLE 0xc5
#define ATA_CMD_WRITEDMA 0xca
#define ATA_CMD_SETFEATURES 0xEF
typedef struct tag_ATA_REGS
{
u32 rrATA_CONTROL; // ATA enable and clock down status
u32 rrATA_STATUS; // ATA status
u32 rrATA_COMMAND; // ATA command
u32 rrATA_SWRST; // ATA software reset
u32 rrATA_IRQ; // ATA interrupt sources
u32 rrATA_IRQ_MASK; // ATA interrupt mask
u32 rrATA_CFG; // ATA configuration for ATA interface
u32 rReserved1;
u32 rReserved2;
u32 rReserved3;
u32 rReserved4;
u32 rrATA_PIO_TIME; // ATA PIO timing
u32 rrATA_UDMA_TIME; // ATA UDMA timing
u32 rrATA_XFR_NUM; // ATA transfer number
u32 rrATA_XFR_CNT; // ATA current transfer count
u32 rrATA_TBUF_START; // ATA start address of track buffer
u32 rrATA_TBUF_SIZE; // ATA size of track buffer
u32 rrATA_SBUF_START; // ATA start address of source buffer
u32 rrATA_SBUF_SIZE; // ATA size of source buffer
u32 rrATA_CADR_TBUF; // ATA current write address of track buffer
u32 rrATA_CADR_SBUF; // ATA current read address of source buffer
u32 rrATA_PIO_DTR; // ATA PIO device data register
u32 rrATA_PIO_FED; // ATA PIO device Feature/Error register
u32 rrATA_PIO_SCR; // ATA PIO sector count register
u32 rrATA_PIO_LLR; // ATA PIO device LBA Low register
u32 rrATA_PIO_LMR; // ATA PIO device LBA middle register
u32 rrATA_PIO_LHR; // ATA PIO device LBA high register
u32 rrATA_PIO_DVR; // ATA PIO device register
u32 rrATA_PIO_CSD; // ATA PIO device command/status register
u32 rrATA_PIO_DAD; // ATA PIO device control/alternate status register
u32 rrATA_PIO_READY; // ATA PIO read data from device data register
u32 rrATA_PIO_RDATA; // ATA PIO read data from device data register
u32 rReserved5;
u32 rReserved6;
u32 rReserved7;
u32 rReserved8;
u32 rrBUS_FIFO_STATUS; // ATA internal AHB FIFO status
u32 rrATA_FIFO_STATUS; // ATA internal ATA FIFO status
}
oATA_REGS;
// define global variables
static void * g_paATASFRBase[ATA_CONNUM];
extern volatile ATA_oInform g_oaATAInform[];
/*---------------------------------- Init Functions ---------------------------------*/
void ATA_SetSFRBaseAddr(u8 ucCon, u32 uBaseAddress);
void ATA_InitPort(u8, u8);
void ATA_InitBufferControl(void);
void ATA_SetTimingParams(u8 ucCon, eATA_MODE_6400 eMode, u32 uValue);
/*---------------------------------- Functions for Implement ATA Test functions ---------------------------------*/
void ATA_WaitForDeviceReady(u8 ucCon);
u8 ATA_GetDeviceReg(u8 ucCon, eCF_TASKFILE_Id eTaskFileRegId);
u16 ATA_GetDataFromDevice(u8 ucCon);
void ATA_SetDataToDevice(u8 ucCon, u16 usData);
bool ATA_WriteSectors_PIO(u8 ucCon, u32 uLBA, u32 uSectorCount, u32 uSrcAddress);
bool ATA_ReadSectors_PIO(u8 ucCon, u32 uLBA, u32 uSectorCount, u32 uDstAddress);
bool ATA_WriteSectors_PDMA(u8 ucCon, u32 uLBA, u32 uSectorCount, u32 uSrcAddress);
bool ATA_ReadSectors_PDMA(u8 ucCon, u32 uLBA, u32 uSectorCount, u32 uSrcAddress);
bool ATA_WriteSectors_UDMA(u8 ucCon, u32 uLBA, u32 uSectorCount, u32 uSrcAddress);
bool ATA_ReadSectors_UDMA(u8 ucCon, u32 uLBA, u32 uSectorCount, u32 uSrcAddress);
void ATA_SetDevicePosition(u8 ucCon, u32 uLba, u32 uSectorCount);
bool ATA_IsWritingSectorsDone(u8 ucCon);
bool ATA_IsReadingSectorsDone(u8 ucCon);
bool ATA_IsWritingBlocksDone(u8 ucCon);
bool ATA_IsReadingBlocksDone(u8 ucCon);
bool ATA_IsDmaDone(u8 ucCon);
/*---------------------------------- APIs of ATA_STATUS Registers ---------------------------------*/
void ATA_WaitForTransferDone(u8 ucCon);
void ATA_SetSwRst(u8 ucCon, u8 ucEnFlag);
void ATA_SetTransferCommand(u8 ucCon, eATA_XFR_CMD eXfrCmd);
void ATA_SetIRQ(u8 ucCon, eATA_IRQ_SRC eIrqSrc);
void ATA_SetIRQMask(u8 ucCon, eATA_IRQ_SRC eIrqSrc);
/*---------------------------------- APIs of ATA_CFG Registers ---------------------------------*/
void ATA_SetConfig(u8 ucCon, eATA_MODE_6400 eMode, eATA_DMA_DIR eDmaDir);
void ATA_SetUdmaAutoMode(u8 ucCon, u8 ucEnFlag);
void ATA_SetEndian(u8 ucCon, eATA_ENDIAN eEndianMode);
void ATA_SetDMAXferDir(u8 ucCon, eATA_DMA_DIR eDmaDir);
void ATA_SetXferMode(u8 ucCon, eATA_MODE_6400 eAtaMode);
void ATA_SetIORDY(u8 ucCon, u8 ucEnFlag);
void ATA_SetRst(u8 ucCon, u8 ucEnFlag);
void ATA_SetSBufStart(u8 ucCon, u32 uBufAddr);
void ATA_SetTBufStart(u8 ucCon, u32 uBufAddr);
void ATA_SetSBufSize(u8 ucCon, u32 uSize);
void ATA_SetTBufSize(u8 ucCon, u32 uSize);
void ATA_SetXfrNum(u8 ucCon, u32 uNum);
u8 ATA_GetTaskFileRegValue(u8 ucCon, eCF_TASKFILE_Id uATATaskFileRegId);
u16 ATA_GetTaskFileRegValue16(u8 ucCon, eCF_TASKFILE_Id uATATaskFileRegId);
void ATA_SetTaskFileRegValue(u8 ucCon, eCF_TASKFILE_Id uATATaskFileRegId, u32 uValue);
void ATA_SetTaskFileRegValue16(u8 ucCon, eCF_TASKFILE_Id uATATaskFileRegId, u16 uValue);
/*---------------------------------- APIs of ATA_FIFO_STATUS Registers ---------------------------------*/
void ATA_WaitForHostReady(u8 ucCon);
/*---------------------------------- APIs of general ATA ---------------------------------*/
u32 ATA_GetRegAddr(u8 ucCon, eATA_Id uATARegId);
u32 ATA_GetRegValue(u8 ucCon, eATA_Id uATARegId);
void ATA_SetRegValue(u8 ucCon, eATA_Id uATARegId, u32 uValue);
/*---------------------------------- Init Functions ---------------------------------*/
//////////
// Function Name : ATA_Init
// Function Description : This function initializes a certain ATA Controller.
// Input : ucCon - ATA Controller Number
// Output : TRUE - Memory Device is reset
// FALSE - Memory Device is not reset because of ERROR
// Version : v0.1
bool ATA_Init(u8 ucCon, u8 ucOpMode)
{
u32 uSFRBaseAddress; // for PCCARD Controller Base Register
Assert( (ucCon == ATA_CON0) );
if (ucCon == ATA_CON0)
{
uSFRBaseAddress = ATA_BASE;
}
else
{
return FALSE;
}
// EBI Setup for CF controller
CF_SetEBI(ucOpMode);
ATA_SetSFRBaseAddr(ucCon, uSFRBaseAddress);
ATA_InitBuffer(ucCon);
ATA_InitPort(ucCon,ucOpMode);
return TRUE;
}
//////////
// Function Name : ATA_SetSFRBaseAddr
// Function Description : This function sets up the base address of ATA Registers.
// Input : ucCon - ATA controller number
// uBaseAddress - the baseaddress of ATA registers
// Output : NONE
// Version : v0.1
void ATA_SetSFRBaseAddr(u8 ucCon, u32 uBaseAddress)
{
g_paATASFRBase[ucCon] = (void *)uBaseAddress;
}
//////////
// Function Name : ATA_InitBuffer
// Function Description : This function sets up the buffer address of ATA Registers.
// Input : ucCon - ATA controller number
// Output : NONE
// Version : v0.1
void ATA_InitBuffer(u8 ucCon)
{
g_oaATAInform[ucCon].puATAWriteBuf = (u32*) CF_WRITE_BUF;
g_oaATAInform[ucCon].puATAReadBuf = (u32*) (CF_WRITE_BUF + 0x400000);
}
//////////
// Function Name : ATA_InitPort
// Function Description :
// This function Initialize ports as ATA.
// Input : ucCon - ATA Controller Number
// Output : NONE
// Version : v0.1
void ATA_InitPort(u8 ucCon, u8 ucOpMode)
{
switch(ucCon)
{
case ATA_CON0 :
if (ucOpMode == DIRECT_MODE)
{
#if 1 // default.. OK A1,D1,C1
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x55555555); // D: Set XhiDATA[15:0] pins as CF Data[15:0]
GPIO_SetFunctionAll(eGPIO_L, 0x00000666, 0x0); // A: Set XhiADDR[2:0] pins as CF ADDR[2:0]
GPIO_SetFunctionAll(eGPIO_M, 0x00066666, 0x0); // C: Set Xhi control pins as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // OK A1,D1,C2
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x55555555); // D: Set XhiDATA[15:0] pins as CF Data[15:0]
GPIO_SetFunctionAll(eGPIO_L, 0x00000666, 0x00055555); // A1: Set XhiADDR[2:0] pins as CF ADDR[2:0], C2 : Set XhiADDR[12:8] as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // A1,D1,D2,C2
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x00000055); // D1: Set XhiDATA[9:0] pins as CF Data[9:0]
GPIO_SetFunctionAll(eGPIO_M, 0x00555555, 0x00000000); // D2: Set Xhi control pins as CF Data[15:10]
GPIO_SetFunctionAll(eGPIO_L, 0x00000666, 0x00055555); // A1: Set XhiADDR[2:0] pins as CF ADDR[2:0], C2 : Set XhiADDR[12:8] as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // A1,D1,D2,D3,C2
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x00000000); // D1: Set XhiDATA[7:0] pins as CF Data[7:0]
GPIO_SetFunctionAll(eGPIO_M, 0x00555555, 0x00000000); // D2: Set Xhi control pins as CF Data[15:10]
GPIO_SetFunctionAll(eGPIO_L, 0x00000666, 0x05555555); // A1: Set XhiADDR[2:0] pins as CF ADDR[2:0], C2 : Set XhiADDR[12:8] as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0]), D3 : Set XhiData[17:16] as CF Data[9:8]
#endif
#if 0 // OK A4,D1,C2
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x55555555); // Set XhiDATA[15:0] pins as CF Data[15:0]
GPIO_SetFunctionAll(eGPIO_B, 0x00000555, 0x00000000); // Set XuRXD2, XuTXD2, XuRXD3 pins as CF ADDR[2:0]
GPIO_SetFunctionAll(eGPIO_L, 0x00000000, 0x00055555); // Set XhiADDR[12:8] as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // only for type2 CPU board A10,D1,C2
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x55555555); // Set XhiDATA[15:0] pins as CF Data[15:0]
GPIO_SetFunctionAll(eGPIO_H, 0x66000000, 0x00000006); // Set MMC1DATA[6:4] pins as CF ADDR[2:0]
GPIO_SetFunctionAll(eGPIO_L, 0x00000000, 0x00055555); // Set XhiADDR[12:8] as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // for GPIO test :A1, A2, D1,D2,D3,C2
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x00000000); // D: Set XhiDATA[7:0] pins as CF Data[7:0]
GPIO_SetFunctionAll(eGPIO_M, 0x00066666, 0x00000000); // D2: Set Xhi control pins as CF Data[15:10]
GPIO_SetFunctionAll(eGPIO_A, 0x00005500, 0x00000000); // A2: Set XuCTSn0, XuRTSn0 pins as CF ADDR[2:0]
GPIO_SetFunctionAll(eGPIO_L, 0x00060000, 0x02255555); // A1: Set XhiADDR2 pin as CF ADDR2, D3: Set XhiDATA[17:16] pins as CF Data[9:8] , C: Set Xhi control pins as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // for GPIO test :A1, A3,D1,C1
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x55555555); // D: Set XhiDATA[15:0] pins as CF Data[15:0]
GPIO_SetFunctionAll(eGPIO_L, 0x00000600, 0x00000000); // A1: Set XhiADDR2 pins as CF ADDR2
GPIO_SetFunctionAll(eGPIO_A, 0x55000000, 0x00000000); // A3: Set XuCTSn1, XuRTSn1 pins as CF ADDR[2:0]
GPIO_SetFunctionAll(eGPIO_M, 0x00066666, 0x00000000); // C: Set Xhi control pins as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // for GPIO test :A5,D1,C1
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x55555555); // D: Set XhiDATA[15:0] pins as CF Data[15:0]
GPIO_SetFunctionAll(eGPIO_C, 0x00000555, 0x00000000); // A5: Set XspiMISO0, XspiCLK0, XspiMOSI0 pins as CF ADDR[2:0]
GPIO_SetFunctionAll(eGPIO_M, 0x00066666, 0x00000000); // C: Set Xhi control pins as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // for GPIO test :A6,D1,C1
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x55555555); // D: Set XhiDATA[15:0] pins as CF Data[15:0]
GPIO_SetFunctionAll(eGPIO_D, 0x00000ddd, 0x00000000); // A6: Set XpcmDCLK0, XpcmEXTCLK0, XpcmFSYNC0 pins as CF ADDR[2:0]
GPIO_SetFunctionAll(eGPIO_M, 0x00066666, 0x00000000); // C: Set Xhi control pins as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // for GPIO test :A7,D1,C1
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x55555555); // D: Set XhiDATA[15:0] pins as CF Data[15:0]
GPIO_SetFunctionAll(eGPIO_N, 0x003f0000, 0x00000000); // A7: Set XEINT[10:8] pins as CF ADDR[2:0]
GPIO_SetFunctionAll(eGPIO_M, 0x00066666, 0x00000000); // C: Set Xhi control pins as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // for GPIO test : A8,D1,C1
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x55555555); // D: Set XhiDATA[15:0] pins as CF Data[15:0]
GPIO_SetFunctionAll(eGPIO_G, 0x00000555, 0x00000000); // A8: Set XmmcCLK0, XmmcCMD0, XmmcDAT0 pins as CF ADDR[2:0]
GPIO_SetFunctionAll(eGPIO_M, 0x00066666, 0x00000000); // C: Set Xhi control pins as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
#if 0 // for GPIO test :A9,D1,C1
GPIO_SetFunctionAll(eGPIO_K, 0x55555555, 0x55555555); // D: Set XhiDATA[15:0] pins as CF Data[15:0]
GPIO_SetFunctionAll(eGPIO_H, 0x00000555, 0x00000000); // A9: Set XmmcCLK1, XmmcCMD1, XmmcDAT1 pins as CF ADDR[2:0]
GPIO_SetFunctionAll(eGPIO_M, 0x00066666, 0x00000000); // C: Set Xhi control pins as CF control pins(IORDY, IOWR, IORD, CE[1], CE[0])
#endif
OpenConsole(); // This line must be here because Uart ports(GPIO_A) are changed after setting GPIO_K.
}
//--- CF controller - PC card mode setting ---//
// Output pad disable, Card power off, PC card mode
CF_SetMUXReg(eCF_MUX_OUTPUT_DISABLE, eCF_MUX_CARDPWR_OFF, eCF_MUX_MODE_IDE);
// DelayfrTimer( milli, 100); // wait for 100ms, be positively necessary
// Output pad enable, Card power off, PC card mode
CF_SetMUXReg(eCF_MUX_OUTPUT_ENABLE, eCF_MUX_CARDPWR_OFF, eCF_MUX_MODE_IDE);
// DelayfrTimer( milli, 100); // wait for 100ms, be positively necessary
// Card Power on (PC Card mode)
CF_SetMUXReg(eCF_MUX_OUTPUT_ENABLE, eCF_MUX_CARDPWR_ON, eCF_MUX_MODE_IDE);
DelayfrTimer( milli, 100); // wait for 100ms, be positively necessary
// Card configuration
ATA_SetTimingParams(ucCon, eATA_MODE_PIO, 0x1C238);
ATA_SetTimingParams(ucCon, eATA_MODE_UDMA, 0x20B1362);
ATA_SetEndian(ucCon, eATA_ENDIAN_LITTLE);
ATA_SetEnable(ucCon, ENABLE);
DelayfrTimer( milli, 100); // wait for 200ms, be positively necessary
#if 0 // for pull-down-dedicated nCD pins
GPIO_SetFunctionEach(eGPIO_P, eGPIO_14, 1); // set CData/EINT as output
GPIO_SetDataEach(eGPIO_P, eGPIO_14 , 1); //GPN[8] -> High
DelayfrTimer(milli,500); //Delay about 10ms
GPIO_SetFunctionEach(eGPIO_P, eGPIO_14, 2); // set CData/EINT as CData
GPIO_SetDataEach(eGPIO_P, eGPIO_14 , 1); //GPN[8] -> High
DelayfrTimer(milli,500); //Delay about 10ms
#endif
#if 1 // for CF card boot up signal
GPIO_SetFunctionEach(eGPIO_N, eGPIO_8, 1); // set XEINT8/ADDR_CF0/GPN8 as output
GPIO_SetDataEach(eGPIO_N, eGPIO_8 , 1); //GPN[8] -> High
DelayfrTimer(milli,100); //Delay about 10ms
GPIO_SetDataEach(eGPIO_N, eGPIO_8 , 0); //GPN[8] -> Low
#endif
break;
default :
break;
}
}
void ATA_InitBufferControl(void) // added by junon for second UDMA test b'd 060902
{
#if 0
#ifdef __EVT1
rGPACDH = 0x1aa8a; // GPA10 RDATA_OEN setting
#else
rGPBCON = rGPBCON & ~((3<<8)|(3)) | (1<<8)|(1); // GPB0,4 output setting (TOUT0, TCLK - TP21,20)
rGPBCON = rGPBCON & ~((3<<12)|(3<<10)) | (1<<12)|(1<<10); // GPB5,6 output setting (nXBACK, nXBREQ)
rGPBDAT = rGPBDAT & ~((7<<4)|(1)) | (1<<6); // GPB6->high, GPB0,4,5->low
#endif
Disp("IBC - rGPBCON = 0x%x \n",rGPBCON);
#endif
}
//extern u8 g_ucATAConNum;
void ATA_ChangeBufferControl(eATA_MODE_6400 mode) // only for SMDK b'd 060902 using additianal logic
{
#if 0
Disp("MODE5:%d, mode:%d\n", g_oaATAInform[g_ucATAConNum].eAtaMode, mode);
if (mode == eATA_MODE_UDMA)
rGPBDAT = rGPBDAT | (1<<4)|(1); // GPB0->high,GPB4->high => UDMA mode
else // PIO
rGPBDAT = rGPBDAT & ~(1<<4) | (1); // GPB0->high,GPB4->low => ATA PIO mode
Disp("BC - rGPBDAT = 0x%x \n",(u32)rGPBDAT);
#endif
}
void ATA_SetTimingParams(u8 ucCon, eATA_MODE_6400 eMode, u32 uValue)
{
switch(eMode)
{
case eATA_MODE_PIOCPU:
case eATA_MODE_PIODMA:
ATA_SetRegValue(ucCon, eATA_PIO_TIME, uValue);
break;
case eATA_MODE_UDMA :
ATA_SetRegValue(ucCon, eATA_UDMA_TIME, uValue);
break;
}
}
/*---------------------------------- Functions for Implement ATA Test functions ---------------------------------*/
//////////
// Function Name : ATA_TestResetAll
// Function Description : This function implements reset function of ATA device.
// Input : ucCon - ATA Controller Number
// Output : NONE
// Version : v0.1
void ATA_TestResetAll(u8 ucCon)
{
// TDelay timer setting
DelayfrTimer( milli, 2); // wait for 2ms
DelayfrTimer( micro, 25); // wait for 25us
ATA_SetSwRst( ucCon, RESET); // CF controller reset
DelayfrTimer( micro, 5); // wait for 5us
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -