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

📄 ata.cpp

📁 Samsung S3C2443 Test program source code
💻 CPP
📖 第 1 页 / 共 3 页
字号:
}

/**********************************
 * PIO mode maximum transfer rate
 * PIO0 : 3.3MB/s
 * PIO1 : 5.2MB/s
 * PIO2 : 8.3MB/s
 * PIO3 : 11.1MB/s
 * PIO4 : 16.7MB/s
 *
***********************************/
 
void ATA::SetPioMode(PIOMODE  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,50,30,50,30};    // min = {70,50,30,30,25};
	U32 m_uPioT2[5] = {300,300,290,100,70}; // min = {290,290,290,80,70};
	U32 m_uPioTeoc[5] = {100,40,20,30,20};  // min = {20,15,10,10,10};
	
	U32 uCycleTime = (U32)(1000000000/HCLK);


	for (i=0; i<5; i++)
	{
		uT1   = (m_uPioT1[i]  /uCycleTime + 1)&0xff;
		uT2   = (m_uPioT2[i]  /uCycleTime + 1)&0xff;
		uTeoc = (m_uPioTeoc[i]/uCycleTime + 1)&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);
	
	WriteOnTaskFileReg(DEV_COMMAND,SETFEATURES); //set feature command

	WaitForDeviceReady();

	switch(pmode) { // modified by Bryan W. Lee (Oct. 19th, 2005)
		case PIO1:
			m_uCfgReg &= (~0x2); //IORDY disable
			Outp32(ATA_PIO_TIME, uPioTime[1]);
			break;
		case PIO2:
			m_uCfgReg &= (~0x2); //IORDY disable
			Outp32(ATA_PIO_TIME, uPioTime[2]);
			break;
		case PIO3:
			m_uCfgReg |= 0x2; //IORDY enable
			Outp32(ATA_PIO_TIME, uPioTime[3]);
			break;
		case PIO4:
			m_uCfgReg |= 0x2; //IORDY enable
			Outp32(ATA_PIO_TIME, uPioTime[4]);
			break;
		default:
			m_uCfgReg &= (~0x2); //IORDY disable
			Outp32(ATA_PIO_TIME, uPioTime[0]);
			break;
		}
	Outp32(ATA_CFG, m_uCfgReg);
	m_eCurrentPioMode = pmode;

}

//uSector: the number of sectors per block
// if the block count is not supported, an Abort Command error is posted,
// and the Read Multiple and Write Multiple commands are disabled.
void ATA::SetMultiple(U32 uSector) 
{
	m_uCurrentMultiple = uSector;

    WriteOnTaskFileReg(DEV_CONTROL,0);
	WriteOnTaskFileReg(DEV_SECTOR,uSector&0xff);
	WriteOnTaskFileReg(DEV_LOWLBA,0x00);
	WriteOnTaskFileReg(DEV_MIDLBA,0x00);
	WriteOnTaskFileReg(DEV_HIGHLBA,0x00);
	WriteOnTaskFileReg(DEV_DEVICE,0x40);
	WriteOnTaskFileReg(DEV_COMMAND,0xC6); //Set Multiple mode (implemented in ATA IP ??)

	WaitForDeviceReady();
}

/**********************************
 * UDMA mode maximum transfer rate
 * UDMA0 : 16.7MB/s
 * UDMA1 : 25.0MB/s
 * UDMA2 : 33.3MB/s
 * UDMA3 : 44.4MB/s
 * UDMA4 : 66.7MB/s
 * UDMA5 : 100 MB/s 
 *
***********************************/
void ATA::SetUdmaMode(UDMAMODE umode) 
{
	U8 nMode;
	U32 uTdvh1;
	U32 uTdvs;
	U32 uTrp;
	U32 uTss;
	U32 uTackenv;
	U32 i;

	U32 uUdmaTime[5];
	U32 uUdmaTdvh[5] = {20,20,10,10,10}; //{7,7,7,7,7};
	U32 uUdmaTdvs[5] = {100,60,50,35,20}; //{70,48,31,20,7};
	U32 uUdmaTrp[5] = {160,125,100,100,100};
	U32 uUdmaTss[5] = {50,50,50,50,50};
	U32 uUdmaTackenvMin[5] = {20,20,20,20,20};
	U32 uUdmaTackenvMax[5] = {70,70,70,55,55};	
	U32 uCycleTime = (U32)(1000000000/HCLK);

	// added GPB setting for SMDK buffer mechanism 060812
	rGPBDAT |= (3<<5); // GPB5,6 -> H
	rGPBCON = rGPBCON & ~(0xf<<10) | (5<<10); // GPB5,6 output mode
	
	for (i=0; i<5; i++)
	{
		uTdvh1	= (uUdmaTdvh[i] / uCycleTime + 1)&0x0f;
		uTdvs	= (uUdmaTdvs[i] / uCycleTime + 1)&0xff;
		uTrp	= (uUdmaTrp[i]  / uCycleTime + 1)&0xff;
		uTss	= (uUdmaTss[i]  / uCycleTime + 1)&0x0f;
		uTackenv= (uUdmaTackenvMin[i]/uCycleTime + 1)&0x0f;
		uUdmaTime[i] = (uTdvh1<<24)|(uTdvs<<16)|(uTrp<<8)|(uTss<<4)|uTackenv;
//		DbgAta(("UDMA%dTIME = %x\n", i, uUdmaTime[i]));
	}	

	Outp32(ATA_IRQ, 0xff);
	Outp32(ATA_IRQ_MASK, ATAPI_MASK);

    WriteOnTaskFileReg(DEV_CONTROL,0);
	WriteOnTaskFileReg(DEV_FEATURE,0x03);
	WriteOnTaskFileReg(DEV_SECTOR,0x40|(nMode&0x7));
	WriteOnTaskFileReg(DEV_LOWLBA,0x00);
	WriteOnTaskFileReg(DEV_MIDLBA,0x00);
	WriteOnTaskFileReg(DEV_HIGHLBA,0x00);
	WriteOnTaskFileReg(DEV_DEVICE,0x40);
	WriteOnTaskFileReg(DEV_COMMAND,SETFEATURES);

	WaitForDeviceReady();

	
	switch(umode) {
		case UDMA0:
			nMode = 0;
			Outp32(ATA_UDMA_TIME, uUdmaTime[0]);
			break;		
		case UDMA1:
			nMode = 1;
			Outp32(ATA_UDMA_TIME, uUdmaTime[1]);
			break;
		case UDMA2:
			nMode = 2;
			Outp32(ATA_UDMA_TIME, uUdmaTime[2]);
			break;
		case UDMA3:
			nMode = 3;
			Outp32(ATA_UDMA_TIME, uUdmaTime[3]);
			break;
		case UDMA4:
			nMode = 4;
			Outp32(ATA_UDMA_TIME, uUdmaTime[4]);
			break;
		default:
			DbgAta(("Wrong UDMA mode in SetUdmaMode()\n"));
			break;
		}
	m_uCurrentUdmaMode = nMode;
	

}

bool ATA::OpenMedia(void)
{
	ATA_MODE mode;
	
	Init();

	IdentifyDevice();

	// Decide what mode is best choice in this media.
	if (m_uMaxUdmaMode == 0)
	{
		mode = PIO_DMA;
	}
	else
	{
		mode = UDMA;
	}

	SetAtaMode(mode);
	if (mode == PIO_CPU || mode == PIO_DMA)
	{
		SetPioMode(m_eMaxPioMode);				
	}
	else 
	{
		UDMAMODE udmaMode = 
			(m_uMaxUdmaMode == 0) ? UDMA0 :
			(m_uMaxUdmaMode == 1) ? UDMA1 :
			(m_uMaxUdmaMode == 2) ? UDMA2 :
			(m_uMaxUdmaMode == 3) ? UDMA3 : UDMA4;
		SetPioMode(PIO0);
		SetUdmaMode(udmaMode);		
	}

	return true;
}

bool ATA::OpenMedia(ATA_MODE mode)
{	
	Init();

	IdentifyDevice();

	SetAtaMode(mode);
	if (mode == PIO_CPU || mode == PIO_DMA)
	{
		SetPioMode(m_eMaxPioMode);				
	}
	else 
	{
		UDMAMODE udmaMode = 
			(m_uMaxUdmaMode == 0) ? UDMA0 :
			(m_uMaxUdmaMode == 1) ? UDMA1 :
			(m_uMaxUdmaMode == 2) ? UDMA2 :
			(m_uMaxUdmaMode == 3) ? UDMA3 : UDMA4;
		SetPioMode(PIO0);
		SetUdmaMode(udmaMode);		
	}

	return true;
}

bool ATA::CloseMedia(void)
{
	SetAtaOnOff(0);

	// Output pad disable, Card power off, PC card mode
	Outp32(ATA_MUX, 0x06);

	return true;
}

bool ATA::ReadBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
//	Assert(uStBlock+uBlocks <= m_uMaxSectors);
	
	U32 k;
	ATA_MODE mode = m_eMode;
	bool status;
	
	switch(mode) 
	{
		case PIO_CPU:
			status = ReadSectors_Pio( uStBlock, uBlocks, uBufAddr);
			break;
			
		case PIO_DMA:
			for(k=0; k<uBlocks; k++) 
			{
				ReadSector_PioDma(uStBlock+k, uBufAddr+ATA_SECTORSIZE*k);
				WaitForTransferDone();
			}
			status = true; // need to move..
			break;
			
		case UDMA:
			status = ReadSectors_Udma( uStBlock, uBlocks, uBufAddr);
			break;
			
		default:
			DbgAta(("Not supported mode in ReadBlocks()\n"));
			break;
	}
	return status;
}

bool ATA::WriteBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
//	Assert(uStBlock+uBlocks <= m_uMaxSectors);
	
	U32 k;
	ATA_MODE mode = m_eMode;
	bool status;
	
	switch(mode) 
	{
		case PIO_CPU:
			status = WriteSectors_Pio( uStBlock, uBlocks, uBufAddr);
			break;
			
		case PIO_DMA:
			for(k=0; k<uBlocks; k++)
			{
				WriteSector_PioDma(uStBlock+k, uBufAddr+ATA_SECTORSIZE*k);
				WaitForTransferDone();
			}
			status = true;
			break;
		case UDMA:			
			status = WriteSectors_Udma( uStBlock, uBlocks, uBufAddr);
			break;
		default:
			DbgAta(("Not supported mode in WriteBlocks()\n"));
			break;
	}
	
	return status;
}


void SetBufferDirection(U32 dir) // only for SMDK b'd 060812
{
	switch(dir)
	{
		case READDMA :
			rGPBDAT &= ~(3<<5); // GPB5 -> L, buffer direction - read setting 
								// GPB6 -> L, buffer Output enable 
			break;
		case WRITEDMA :
			rGPBDAT |= (1<<5); 	// GPB5 -> H, buffer direction - write setting 
			rGPBDAT &= ~(1<<6); // GPB6 -> L, buffer Output enable 060812
			break;
		default : // clear
			rGPBDAT |= (3<<5); 	// GPB5 -> H, buffer direction - write setting 
								// GPB6 -> H, buffer Output disable 
			break;
	}		
}


bool ATA::StartReadingBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
//	Assert(!(m_eMode == PIO_CPU));
	
	U32 deviceCmd = (m_eMode == UDMA) ? READDMA : READSECTOR;
	
	/*Track Buffer 1 Setting*/
	Outp32(ATA_TBUF_START, uBufAddr);
	Outp32(ATA_TBUF_SIZE, uBlocks*ATA_SECTORSIZE);
	Outp32(ATA_XFR_NUM, uBlocks*ATA_SECTORSIZE);

	SetAtaDevice(uStBlock, uBlocks);
	WriteOnTaskFileReg(DEV_COMMAND, deviceCmd);

	WaitForDeviceReady();
	
	SetConfigMode(m_eMode, false);
	if (m_eMode == UDMA) // apply at specific set using buffer control
	{
		printf("Ready for reading data in UDMA. Change dip SW & Press Enter..\n");
		getchar();
		SetBufferDirection(READDMA);
	}
	
	SetTransferCommand(ATA_CMD_START);
	
	return true;
}

bool ATA::IsReadingBlocksDone(void)
{
	return IsWritingBlocksDone();
}

void ATA::ContinueReadingBlocks(void)
{

}


bool ATA::StartWritingBlocks(U32 uStBlock, U32 uBlocks, U32 uBufAddr)
{
//	Assert(!(m_eMode == PIO_CPU));

	U32 deviceCmd = (m_eMode == UDMA) ? WRITEDMA : WRITESECTOR;

	
	/*Source Buffer Setting*/
	Outp32(ATA_SBUF_START, uBufAddr);
	Outp32(ATA_SBUF_SIZE, uBlocks*ATA_SECTORSIZE);
	Outp32(ATA_XFR_NUM,   uBlocks*ATA_SECTORSIZE);
	
	SetAtaDevice(uStBlock, uBlocks);
	WriteOnTaskFileReg(DEV_COMMAND, deviceCmd);

	WaitForDeviceReady();

	SetConfigMode(m_eMode, true);	
	if (m_eMode == UDMA) // apply at specific set using buffer control
	{
		printf("Ready for writing data in UDMA. Change dip SW & Press Enter..\n");
		getchar();
		SetBufferDirection(WRITEDMA); // for SMDK buffer direction only
	}

	SetTransferCommand(ATA_CMD_START);

	return true;
}

bool ATA::IsWritingBlocksDone(void)
{
	WaitForTransferDone();

⌨️ 快捷键说明

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