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

📄 pccard.cpp

📁 三星公司S3c2443的测试程序源码
💻 CPP
字号:
#include <stdio.h>
#include "system.h"

#include "2443addr.h"
#include "pccard.h"
#include "etc.h"


#define DBG_PCCARD

#ifdef DBG_PCCARD
#define DbgPccard(x) printf x
#else
#define DbgPccard(x) 0;
#endif

#define CFMEM_BASE      0x4B800000

// ATA, Basic PC card select
#define ATA_MUX           CFMEM_BASE+0x1800

// PC card SFR base
#define PCCARD_SFR_BASE   CFMEM_BASE+0x1820

// PC Card Memory map
#define PCCARD_ATT_BASE   CFMEM_BASE		// refer to attribute memory region
#define PCCARD_IO_BASE    CFMEM_BASE+0x800  // refer to IO region
#define PCCARD_MEM_BASE   CFMEM_BASE+0x1000 // refer to common memory region

#define PCCARD_MEM_MODE		0
#define PCCARD_IO_MODE1		1
#define PCCARD_IO_MODE2		2
#define PCCARD_IO_MODE3		3


/*=========================================================================
 *        	             ATA Commands
 *=========================================================================
 */

#define IDENTIFYDEVICE				0xec
#define READSECTOR					0x20
#define READMULTIPLE				0xc4
#define READDMA						0xc8
#define WRITESECTOR					0x30
#define WRITEMULTIPLE				0xc5
#define WRITEDMA					0xca
#define SETFEATURES					0xef


/*=========================================================================
 *        	             I/O configuration address
 *=========================================================================
 */

#define PCCARD_CONFIG_OPTION	(PCCARD_ATT_BASE + 0x200)
#define PCCARD_CONFIG_STATUS	(PCCARD_ATT_BASE + 0x202)
#define PCCARD_CONFIG_REPLACE	(PCCARD_ATT_BASE + 0x200)
#define PCCARD_CONFIG_SOCKET	(PCCARD_ATT_BASE + 0x200)


/*=========================================================================
 *          	          PC card ATA Register Address
 *=========================================================================
 */

static U32 PCCARD_DATA =    	(PCCARD_MEM_BASE + 0x00);
static U32 PCCARD_ERROR =       (PCCARD_MEM_BASE + 0x01);
static U32 PCCARD_FEATURE =     (PCCARD_MEM_BASE + 0x01);
static U32 PCCARD_SECTOR =      (PCCARD_MEM_BASE + 0x02);
static U32 PCCARD_LOWLBA =      (PCCARD_MEM_BASE + 0x03);
static U32 PCCARD_MIDLBA =      (PCCARD_MEM_BASE + 0x04);
static U32 PCCARD_HIGHLBA =     (PCCARD_MEM_BASE + 0x05);
static U32 PCCARD_DEVICE =      (PCCARD_MEM_BASE + 0x06);
static U32 PCCARD_STATUS =      (PCCARD_MEM_BASE + 0x07);
static U32 PCCARD_COMMAND =     (PCCARD_MEM_BASE + 0x07);
static U32 PCCARD_DUP_EVEN =	(PCCARD_MEM_BASE + 0x08);
static U32 PCCARD_DUP_ODD =		(PCCARD_MEM_BASE + 0x09);
static U32 PCCARD_DUP_ERR =		(PCCARD_MEM_BASE + 0x0D);
static U32 PCCARD_DUP_FEATURE =	(PCCARD_MEM_BASE + 0x0D);
static U32 PCCARD_ALTANATE =    (PCCARD_MEM_BASE + 0x0E);
static U32 PCCARD_CONTROL =     (PCCARD_MEM_BASE + 0x0E);
static U32 PCCARD_DRV_ADDR =	(PCCARD_MEM_BASE + 0x0F);


//=========================================================================
//          	          PCCARD Functions
//=========================================================================

bool PCCARD::ChangeMode(U32 mode)
{
	if (mode == PCCARD_IO_MODE1) 
	{
		PCCARD_DATA =		(PCCARD_IO_BASE + 0x00);
		PCCARD_ERROR =      (PCCARD_IO_BASE + 0x01);
		PCCARD_FEATURE =    (PCCARD_IO_BASE + 0x01);
		PCCARD_SECTOR =     (PCCARD_IO_BASE + 0x02);
		PCCARD_LOWLBA =     (PCCARD_IO_BASE + 0x03);
		PCCARD_MIDLBA =     (PCCARD_IO_BASE + 0x04);
		PCCARD_HIGHLBA =    (PCCARD_IO_BASE + 0x05);
		PCCARD_DEVICE =     (PCCARD_IO_BASE + 0x06);
		PCCARD_STATUS =     (PCCARD_IO_BASE + 0x07);
		PCCARD_COMMAND =    (PCCARD_IO_BASE + 0x07);
		PCCARD_DUP_EVEN =	(PCCARD_IO_BASE + 0x08);
		PCCARD_DUP_ODD =	(PCCARD_IO_BASE + 0x09);
		PCCARD_DUP_ERR =	(PCCARD_IO_BASE + 0x0D);
		PCCARD_DUP_FEATURE =(PCCARD_IO_BASE + 0x0D);
		PCCARD_ALTANATE =   (PCCARD_IO_BASE + 0x0E);
		PCCARD_CONTROL =    (PCCARD_IO_BASE + 0x0E);		
		PCCARD_DRV_ADDR =	(PCCARD_IO_BASE + 0x0F);		

		Outp8(PCCARD_CONFIG_OPTION, PCCARD_IO_MODE1);
	}
	else if (mode == PCCARD_IO_MODE2) 
	{
		PCCARD_DATA =		(PCCARD_IO_BASE + 0x1F0);
		PCCARD_ERROR =      (PCCARD_IO_BASE + 0x1F1);
		PCCARD_FEATURE =    (PCCARD_IO_BASE + 0x1F1);
		PCCARD_SECTOR =     (PCCARD_IO_BASE + 0x1F2);
		PCCARD_LOWLBA =     (PCCARD_IO_BASE + 0x1F3);
		PCCARD_MIDLBA =     (PCCARD_IO_BASE + 0x1F4);
		PCCARD_HIGHLBA =    (PCCARD_IO_BASE + 0x1F5);
		PCCARD_DEVICE =     (PCCARD_IO_BASE + 0x1F6);
		PCCARD_STATUS =     (PCCARD_IO_BASE + 0x1F7);
		PCCARD_COMMAND =    (PCCARD_IO_BASE + 0x1F7);
		PCCARD_ALTANATE =   (PCCARD_IO_BASE + 0x3F6);
		PCCARD_DRV_ADDR =	(PCCARD_IO_BASE + 0x3F7);		

		Outp8(PCCARD_CONFIG_OPTION, PCCARD_IO_MODE2);
	}
	else if (mode == PCCARD_IO_MODE3) 
	{
		PCCARD_DATA =		(PCCARD_IO_BASE + 0x170);
		PCCARD_ERROR =      (PCCARD_IO_BASE + 0x171);
		PCCARD_FEATURE =    (PCCARD_IO_BASE + 0x171);
		PCCARD_SECTOR =     (PCCARD_IO_BASE + 0x172);
		PCCARD_LOWLBA =     (PCCARD_IO_BASE + 0x173);
		PCCARD_MIDLBA =     (PCCARD_IO_BASE + 0x174);
		PCCARD_HIGHLBA =    (PCCARD_IO_BASE + 0x175);
		PCCARD_DEVICE =     (PCCARD_IO_BASE + 0x176);
		PCCARD_STATUS =     (PCCARD_IO_BASE + 0x177);
		PCCARD_COMMAND =    (PCCARD_IO_BASE + 0x177);
		PCCARD_ALTANATE =   (PCCARD_IO_BASE + 0x376);
		PCCARD_DRV_ADDR =	(PCCARD_IO_BASE + 0x377);		

		Outp8(PCCARD_CONFIG_OPTION, PCCARD_IO_MODE3);
	}
	else // defualt PCCARD_MEM_MODE
	{
		PCCARD_DATA =		(PCCARD_MEM_BASE + 0x00);
		PCCARD_ERROR =      (PCCARD_MEM_BASE + 0x01);
		PCCARD_FEATURE =    (PCCARD_MEM_BASE + 0x01);
		PCCARD_SECTOR =     (PCCARD_MEM_BASE + 0x02);
		PCCARD_LOWLBA =     (PCCARD_MEM_BASE + 0x03);
		PCCARD_MIDLBA =     (PCCARD_MEM_BASE + 0x04);
		PCCARD_HIGHLBA =    (PCCARD_MEM_BASE + 0x05);
		PCCARD_DEVICE =     (PCCARD_MEM_BASE + 0x06);
		PCCARD_STATUS =     (PCCARD_MEM_BASE + 0x07);
		PCCARD_COMMAND =    (PCCARD_MEM_BASE + 0x07);
		PCCARD_DUP_EVEN =	(PCCARD_MEM_BASE + 0x08);
		PCCARD_DUP_ODD =	(PCCARD_MEM_BASE + 0x09);
		PCCARD_DUP_ERR =	(PCCARD_MEM_BASE + 0x0D);
		PCCARD_DUP_FEATURE =(PCCARD_MEM_BASE + 0x0D);
		PCCARD_ALTANATE =   (PCCARD_MEM_BASE + 0x0E);
		PCCARD_CONTROL =    (PCCARD_MEM_BASE + 0x0E);				
		PCCARD_DRV_ADDR =	(PCCARD_MEM_BASE + 0x0F);				

		Outp8(PCCARD_CONFIG_OPTION, PCCARD_MEM_MODE);
	}	
}

bool PCCARD::OpenMedia(U32 mode)
{	
	// 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
	rGPACON |= (1<<27)|(1<<11)|(1<<14)|(1<<13);// nWE_CF,nOE_CF,nRCS3,nRCS2 enable
	rMISCCR &=(~(1<<30)); // card detect when card is detected ,the bit should be '0'.
	
	// CF controller - PC card mode setting
	Outp32(ATA_MUX, 0x06); 	// Output pad disable, Card power off, PC card mode
	TDelay(100);
	Outp32(ATA_MUX, 0x02); 	// Output pad enable, Card power off, PC card mode
	TDelay(100);
	Outp32(ATA_MUX, 0x00); 	// Card Power on (PC Card mode)
	// wait for at least 20ms (SanDisk: 25ms, MicroDrive: 125ms, Hagiwara: )
	// No other method available.
	TDelay(12500); // 125ms

	// Card configuration
	rPCCARD_CNF_STATUS = (1<<11)|(1<<10)|(1<<9)|(1<<8); // wain en, attr mem 16bit, com mem 16bit, IO 16bit
    rPCCARD_INTMSK_SRC = (1<<10)|(1<<9)|(1<<8); // mask ERR, IREQ, CD
    rPCCARD_ATTR = (3<<16)|(0x19<<8)|(9); // Timing Hold, Command, Setup in attr mem mode
    rPCCARD_IO = (3<<16)|(0x19<<8)|(9); // Timing Hold, Command, Setup in IO mode
    rPCCARD_COMM = (3<<16)|(0x19<<8)|(9); // Timing Hold, Command, Setup in comm mem mode
	
	// Card reset
	rPCCARD_CNF_STATUS |= (1<<13);
	TDelay(100); // 1ms
	rPCCARD_CNF_STATUS &= ~(1<<13);
	TDelay(10000); // 100ms

	// Change access mode
	ChangeMode(mode);
	
	return true;
}

bool PCCARD::CloseMedia(void)
{
	// Output pad disable, Card power off, PC card mode
	Outp32(ATA_MUX, 0x06);
	
	return true;
}

void PCCARD::GetAttribData(U32 index, U8& data)
{
	Inp8(PCCARD_ATT_BASE+index, data);
}

void PCCARD::ReadRegister(U32 nRegister, U8& data)
{
	Inp8(nRegister, data);
}

void PCCARD::WriteRegister(U32 nRegister, U8 nValue)
{
	U8 temp;
	do
	{
		ReadRegister(PCCARD_STATUS, temp);
	} while (temp == 0x80) ;
	Outp8(nRegister, nValue);
	DbgPccard(("reg addr : 0x%x\n", nRegister));
}

void PCCARD::PutDataToDevice(U16 nData)
{
	Outp16(PCCARD_DATA, nData);
}

void PCCARD::GetDataFromDevice(U16& uData)
{
	Inp16(PCCARD_DATA, uData);

}

bool PCCARD::ReadBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
	// uBlocks: sector count
	// uLba:     (head&0x0f)<<24 | (LBA_high<<16) | (LBA_mid<<8) | LBA_low
	// uDstAddr:    host address
	
	U8 temp;
	U16* uCurrentAddr = (U16*) uBufAddr;

	WriteRegister(PCCARD_FEATURE,0);
	WriteRegister(PCCARD_SECTOR,uBlocks);
	WriteRegister(PCCARD_LOWLBA,(uStBlock&0x00ff));
	WriteRegister(PCCARD_MIDLBA,((uStBlock>>8)&0x00ff));
	WriteRegister(PCCARD_HIGHLBA,((uStBlock>>16)&0x00ff));
	WriteRegister(PCCARD_DEVICE,((uStBlock>>24)&0x000f) | 0xe0);  //LBA enabled, Drive 0

#ifdef DBG_PCCARD
	ReadRegister(PCCARD_SECTOR,temp);
	printf("Sector W:0x%x, R:0x%x\n",uBlocks,temp);
	ReadRegister(PCCARD_LOWLBA,temp);
	printf("lLBA W:0x%x, R:0x%x\n",(uStBlock&0x00ff),temp);
	ReadRegister(PCCARD_MIDLBA,temp);
	printf("mLBA W:0x%x, R:0x%x\n",((uStBlock>>8)&0x00ff),temp);
	ReadRegister(PCCARD_HIGHLBA,temp);
	printf("hLBA W:0x%x, R:0x%x\n",((uStBlock>>16)&0x00ff),temp);
	ReadRegister(PCCARD_DEVICE,temp);  //LBA enabled, Drive 0
	printf("device W:0x%x, R:0x%x\n",((uStBlock>>24)&0x000f) | 0xe0,temp);
#endif

	WriteRegister(PCCARD_COMMAND, READSECTOR);

	do
	{
		ReadRegister(PCCARD_STATUS, temp);
		TDelay(1);  // need over 25MHz
		DbgPccard(("(0x%x) ",temp));
	}
	while(temp != 0x58) ;


	for (U32 j=0; j<uBlocks; j++)
	{
		for (U32 i=0; i<512/2; i++)
		{
#if 1	// both case are OK	
			GetDataFromDevice(*uCurrentAddr);
#else
			Inp16(PCCARD_BASE+0x400+i*2, *uCurrentAddr);
#endif
			uCurrentAddr++;
		}

		do
		{
			ReadRegister(PCCARD_STATUS, temp);
			TDelay(1); // need over 25MHz
			DbgPccard(("{0x%x} ",temp));
		}
		while(temp != 0x50 && temp != 0x58);

	}

	return true;
}


bool PCCARD::WriteBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
	U8 temp;
	U16* uCurrentAddr = (U16*) uBufAddr;
	
	// uBlocks: sector count
	// uLba:     (head&0x0f)<<24 | (LBA_high<<16) | (LBA_mid<<8) | LBA_low
	// uSrcAddr:    host address
		
	WriteRegister(PCCARD_FEATURE,0);
	WriteRegister(PCCARD_SECTOR,uBlocks);
	WriteRegister(PCCARD_LOWLBA,(uStBlock&0x00ff));
	WriteRegister(PCCARD_MIDLBA,((uStBlock>>8)&0x00ff));
	WriteRegister(PCCARD_HIGHLBA,((uStBlock>>16)&0x00ff));
	WriteRegister(PCCARD_DEVICE,((uStBlock>>24)&0x000f) | 0xe0);  //LBA enabled, Drive 0

#ifdef DBG_PCCARD
	ReadRegister(PCCARD_SECTOR,temp);
	printf("Sector W:0x%x, R:0x%x\n",uBlocks,temp);
	ReadRegister(PCCARD_LOWLBA,temp);
	printf("lLBA W:0x%x, R:0x%x\n",(uStBlock&0x00ff),temp);
	ReadRegister(PCCARD_MIDLBA,temp);
	printf("mLBA W:0x%x, R:0x%x\n",((uStBlock>>8)&0x00ff),temp);
	ReadRegister(PCCARD_HIGHLBA,temp);
	printf("hLBA W:0x%x, R:0x%x\n",((uStBlock>>16)&0x00ff),temp);
	ReadRegister(PCCARD_DEVICE,temp);  //LBA enabled, Drive 0
	printf("device W:0x%x, R:0x%x\n",((uStBlock>>24)&0x000f) | 0xe0,temp);
#endif

	WriteRegister(PCCARD_COMMAND, WRITESECTOR);

	do
	{
		ReadRegister(PCCARD_STATUS, temp);
		TDelay(1);  // need over 25MHz
		DbgPccard(("[0x%x] ",temp));
	}
	while(temp != 0x58) ;   	



	for (U32 j=0; j<uBlocks; j++)
	{
		for (U32 i=0; i<512/2; i++)
		{
#if 1	// both case are OK	
			PutDataToDevice(*uCurrentAddr);	
#else
			Outp16(PCCARD_BASE+0x400+i*2, *uCurrentAddr);
#endif
			uCurrentAddr++;
		}

		do
		{
			ReadRegister(PCCARD_STATUS, temp);
			TDelay(1); // need over 25MHz
			DbgPccard(("|0x%x| ",temp));
		}
		while(temp != 0x50 && temp != 0x58) ;

	}

	return true;
}

⌨️ 快捷键说明

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