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

📄 ata.c

📁 三星2443芯片
💻 C
📖 第 1 页 / 共 3 页
字号:
void ChangeATAMode(void)
{
#ifdef CFCON_MODE
	SetResTDelay(10); // TDelay 1 unit = 10us
	InitTDelayFunc();
	
	// CF controller - True IDE mode setting
	Outp32(ATA_MUX, 0x07); // Output pad disable, Card power off, ATA mode
	TDelay(100);
	Outp32(ATA_MUX, 0x03); // Output pad enable, Card power off, ATA mode
	TDelay(100);
	Outp32(ATA_MUX, 0x01); // Output pad enable, Card power on, ATA mode
	TDelay(50000); // wait for 500ms
#endif
}

void SetAtaDevice(unsigned int uLBA, unsigned int uSectorCount)
{
	WriteOnTaskFileReg(DEV_SECTOR,uSectorCount&0xFF);
	WriteOnTaskFileReg(DEV_LOWLBA,uLBA&0xFF);
	WriteOnTaskFileReg(DEV_MIDLBA,(uLBA>>8)&0xFF);
	WriteOnTaskFileReg(DEV_HIGHLBA,(uLBA>>16)&0xFF);
	WriteOnTaskFileReg(DEV_DEVICE,((uLBA>>24)&0xF)|0x40);
}


void SetConfigMode(ATA_MODE mode, bool isWriteMode)
{
	switch(mode)
	{
		case PIO_CPU:
			uCfgReg = ((uCfgReg&0x1F3) | (0<<2)); // set PIO_CPU class
			break;
		case PIO_DMA:
			uCfgReg = ((uCfgReg&0x1F3) | (1<<2)); // set PDMA class
			if (isWriteMode == TRUE)
				uCfgReg |= 0x10; // DMA write mode
			else
				uCfgReg &= (~0x10); // DMA read mode
			break;
		case UDMA:
			uCfgReg = ((uCfgReg&0x1F3) | (2<<2)); // set UDMA class
			uCfgReg |= 0x200; // set ATA DMA auto mode (enable multi block transfer)
			if (isWriteMode == TRUE)
				uCfgReg |= 0x10; // DMA write mode
			else
				uCfgReg &= (~0x10); // DMA read mode
			break;
		default:
			break;
	}
	Outp32(ATA_CFG, uCfgReg);
}

bool WriteSectors_Pio(unsigned int uLBA,unsigned int uSectorCount,unsigned int uSrcAddress) 
{
	unsigned int uCurrentCount;
	unsigned int uRemainderCount;
	unsigned int uCurrentLba;
	unsigned int uCurrentSrcAddr;
	unsigned int uRound;
	unsigned short* uAtaHostAddr;
	unsigned int i;
	
#if PERF_TEST_PIO_D	
	unsigned int op_time = 0;
	SetResStopwatch(10000); // us order, 10000us = 10ms
#endif
	
	uRemainderCount = uSectorCount;
	uCurrentLba = uLBA;
	uRound = 0;	

	while(uRemainderCount != 0) {
		if(uRemainderCount>256) {
			uCurrentCount = 256; //0 means 256
			uRemainderCount -= 256;
		} else {
			uCurrentCount = uRemainderCount;
			uRemainderCount = 0;
		}
		uCurrentLba = uLBA + uRound*256;
		uCurrentSrcAddr = uSrcAddress + uRound*256*ATA_SECTORSIZE;
		uAtaHostAddr = (unsigned short*)uCurrentSrcAddr;
		
		SetAtaDevice(uCurrentLba, uCurrentCount);
		WriteOnTaskFileReg(DEV_COMMAND, WRITESECTOR);

		while(uCurrentCount-- ) {	
			WaitForDeviceReady();
#if PERF_TEST_PIO_D	
	StartStopwatch(); // Start timer
#endif
			for (i=0;i<ATA_SECTORSIZE/2;i++) {			
				PutDataToDevice(*uAtaHostAddr);
				uAtaHostAddr++;
			}
#if PERF_TEST_PIO_D	
	op_time += EndStopwatch(); 	   // end timer, us order
#endif
		}		
		WaitForDeviceReady();

		uRound++;
	}

#if PERF_TEST_PIO_D	
	printf ("PIO Writing time : %d us, Performance : %lf MByte/sec\n"
			,op_time,(float)(uSectorCount*512./op_time));	
#endif

	return TRUE;
}


bool ReadSectors_Pio(unsigned int uLBA, unsigned int uSectorCount, unsigned int uDesAddress) 
{
	unsigned int uCurrentCount;
	unsigned int uRemainderCount;
	unsigned int uCurrentLba;
	unsigned int uCurrentDstAddr;
	unsigned int uRound;
	unsigned short* uAtaHostAddr;
	unsigned int i;

#if PERF_TEST_PIO_D	
	unsigned int op_time = 0;
	SetResStopwatch(10000); // us order, 10000us = 10ms
#endif
	
	uRemainderCount = uSectorCount;
	uCurrentLba = uLBA;
	uRound = 0;	

	while(uRemainderCount != 0) {
		if(uRemainderCount>256) {
			uCurrentCount = 256; //0 means 256
			uRemainderCount -= 256;
		} else {
			uCurrentCount = uRemainderCount;
			uRemainderCount = 0;
		}
		uCurrentLba = uLBA + uRound*256;
		uCurrentDstAddr = uDesAddress + uRound*256*ATA_SECTORSIZE;
		uAtaHostAddr = (unsigned short*)uCurrentDstAddr;

		SetAtaDevice(uCurrentLba, uCurrentCount);
		WriteOnTaskFileReg(DEV_COMMAND, READSECTOR);

		while(uCurrentCount-- ) {
			WaitForDeviceReady();
#if PERF_TEST_PIO_D	
	StartStopwatch(); // Start timer
#endif
			for (i=0;i<ATA_SECTORSIZE/2;i++) {
				 GetDataFromDevice(uAtaHostAddr);
				 uAtaHostAddr++;
			}
#if PERF_TEST_PIO_D	
	op_time += EndStopwatch(); 	   // end timer, us order
#endif
		}
		WaitForDeviceReady();

		uRound++;
	}

#if PERF_TEST_PIO_D	
	printf ("PIO Reading time : %d us, Performance : %lf MByte/sec\n"
			,op_time,(float)(uSectorCount*512./op_time));	
#endif

	return TRUE;
}




bool WriteSector_PioDma(unsigned int uLBA, unsigned int uSrcAddress) 
{
#if 1
	StartWritingBlocks(uLBA, 1, uSrcAddress);
	return IsWritingBlocksDone();
#else	
	/*Source Buffer 1 Setting*/
	Outp32(ATA_SBUF_START, uSrcAddress);
	Outp32(ATA_SBUF_SIZE, 1*ATA_SECTORSIZE);
	Outp32(ATA_XFR_NUM,   1*ATA_SECTORSIZE);
	
	SetAtaDevice(uLBA, 1);
	WriteOnTaskFileReg(DEV_COMMAND, WRITESECTOR);

	WaitForDeviceReady();

	SetConfigMode(PIO_DMA, TRUE);
	
	SetTransferCommand(ATA_CMD_START);
	WaitForTransferDone();
	SetTransferCommand(ATA_CMD_ABORT);

	SetConfigMode(PIO_CPU, TRUE);

	WaitForDeviceReady();
	
	return TRUE;
#endif	
}

bool ReadSector_PioDma(unsigned int uLBA, unsigned int uDesAddress) 
{
#if 1
	StartReadingBlocks(uLBA, 1, uDesAddress);
	return IsReadingBlocksDone();
#else
	/*Track Buffer 1 Setting*/
	Outp32(ATA_TBUF_START, uDesAddress);
	Outp32(ATA_TBUF_SIZE, 1*ATA_SECTORSIZE);
	Outp32(ATA_XFR_NUM, 1*ATA_SECTORSIZE);

	SetAtaDevice(uLBA, 1);
	WriteOnTaskFileReg(DEV_COMMAND, READSECTOR);
	
	WaitForDeviceReady();
		
	SetConfigMode(PIO_DMA, FALSE);
		
	SetTransferCommand(ATA_CMD_START);
	WaitForTransferDone();
	SetTransferCommand(ATA_CMD_ABORT);

	SetConfigMode(PIO_CPU, FALSE);

	WaitForDeviceReady();
			
	return TRUE;
#endif	
}


bool WriteSectors_Udma(unsigned int uLBA, unsigned int uSectorCount, unsigned int uSrcAddress) 
{
	unsigned int uCurrentCount;
	unsigned int uRemainderCount;
	unsigned int uCurrentLba;
	unsigned int uCurrentSrcAddr;
	unsigned int uRound;

#if PERF_TEST_UDMA_D	
	unsigned int op_time=0;
	SetResStopwatch(10000); // us order, 10000us = 10ms
#endif
	
	uRemainderCount = uSectorCount;
	uRound = 0;	

	
	while(uRemainderCount != 0) {
		if(uRemainderCount>256) {
			uCurrentCount = 256; //0 means 256
			uRemainderCount -= 256;
		} else {
			uCurrentCount = uRemainderCount;
			uRemainderCount = 0;
		}
		uCurrentLba = uLBA + uRound*256;
		uCurrentSrcAddr = uSrcAddress + uRound*256*ATA_SECTORSIZE;
#if 0
		StartWritingBlocks(uCurrentLba, uCurrentCount, uCurrentSrcAddr);
		IsWritingBlocksDone();
#else
		/*Source Buffer 1 Setting*/
		Outp32(ATA_SBUF_START, uCurrentSrcAddr);
		Outp32(ATA_SBUF_SIZE, uCurrentCount*ATA_SECTORSIZE);
		Outp32(ATA_XFR_NUM,   uCurrentCount*ATA_SECTORSIZE);	

		SetAtaDevice(uCurrentLba, uCurrentCount);
		WriteOnTaskFileReg(DEV_COMMAND,WRITEDMA);

		WaitForDeviceReady();
		SetConfigMode(UDMA, TRUE);
	
#if PERF_TEST_UDMA_D
	StartStopwatch(); // Start timer
#endif
		/*ATA Transfer Command */
		ChangeBufferControl(UDMA);
		SetBufferDirection(WRITEDMA);
		SetTransferCommand(ATA_CMD_START);

#if 1
		WaitForTransferDone();
#else  // abort operation
		while(1){
			Inp32(ATA_XFR_CNT, temp);
			if(temp <= uCurrentCount*ATA_SECTORSIZE) break;
		}
#endif
		SetTransferCommand(ATA_CMD_ABORT);
		SetBufferDirection(0); // clear to H
		ChangeBufferControl(PIO_CPU);

#if PERF_TEST_UDMA_D	
	op_time += EndStopwatch(); 	   // end timer, us order
#endif

		SetConfigMode(PIO_CPU, TRUE);
		WaitForDeviceReady();
		
		uCfgReg &= (~0x200); // disable ATA DMA auto mode
		Outp32(ATA_CFG, uCfgReg);	

#endif
		uRound++;
	}

#if PERF_TEST_UDMA_D	
	printf ("UDMA writing time : %d us, Performance : %lf MByte/sec\n"
			,op_time,(float)(uSectorCount*512./op_time));	
#endif

	return TRUE;

}


bool ReadSectors_Udma(unsigned int uLBA, unsigned int uSectorCount, unsigned int uDstAddress) 
{
	unsigned int uCurrentCount;
	unsigned int uRemainderCount;
	unsigned int uCurrentLba;
	unsigned int uCurrentDstAddr;
	unsigned int uRound;

#if PERF_TEST_UDMA_D	
	unsigned int op_time=0;
	SetResStopwatch(10000); // us order, 10000us = 10ms
#endif
	
	uRemainderCount = uSectorCount;
	uRound = 0;	

	
	while(uRemainderCount != 0) {

		if(uRemainderCount>256) {
			uCurrentCount = 256; //0 means 256
			uRemainderCount -= 256;
		} else {
			uCurrentCount = uRemainderCount;
			uRemainderCount = 0;
		}
		uCurrentLba = uLBA + uRound*256;
		uCurrentDstAddr = uDstAddress + uRound*256*ATA_SECTORSIZE;
#if 0
		StartReadingBlocks(uCurrentLba, uCurrentCount, uCurrentDstAddr);
		IsReadingBlocksDone();
#else
		/*Track Buffer 1 Setting*/
		Outp32(ATA_TBUF_START, uCurrentDstAddr);
		Outp32(ATA_TBUF_SIZE, uCurrentCount*ATA_SECTORSIZE);
		Outp32(ATA_XFR_NUM, uCurrentCount*ATA_SECTORSIZE);

		SetAtaDevice(uCurrentLba, uCurrentCount);
		WriteOnTaskFileReg(DEV_COMMAND,READDMA);

		WaitForDeviceReady(); // too long time.... in UDMA mode
		SetConfigMode(UDMA, FALSE);

#if PERF_TEST_UDMA_D	
	StartStopwatch(); // Start timer
#endif

		/*ATA Transfer Command */		
		ChangeBufferControl(UDMA);
		SetBufferDirection(READDMA);
		SetTransferCommand(ATA_CMD_START);

		WaitForTransferDone(); // Host

		SetTransferCommand(ATA_CMD_ABORT);	
		SetBufferDirection(0); // clear to H
		ChangeBufferControl(PIO_CPU);

#if PERF_TEST_UDMA_D	
	op_time += EndStopwatch(); 	   // end timer, us order
#endif

		SetConfigMode(PIO_CPU, FALSE);
		WaitForDeviceReady();

		uCfgReg &= (~0x200); // disable ATA DMA auto mode
		Outp32(ATA_CFG, uCfgReg);

#endif		
		uRound++;
	}

#if PERF_TEST_UDMA_D	
	printf ("UDMA reading time : %d us, Performance : %lf MByte/sec\n"
			,op_time,(float)(uSectorCount*512./op_time));	
#endif

	return TRUE;
}


void InitBufferControl(void) // added by junon for second UDMA test b'd 060902
{
#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	
	DbgAta(("IBC - rGPBCON = 0x%x \n",rGPBCON));
}

void ChangeBufferControl(ATA_MODE mode) // only for SMDK b'd 060902 using additianal logic
{
	if (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	  	
	DbgAta(("BC - rGPBDAT = 0x%x \n",rGPBDAT));
}

void SetBufferDirection(unsigned int dir) // only for SMDK b'd 060812 using additianal logic
{
	switch(dir)
	{
		case READDMA :
			rGPBDAT &= ~(1<<5); // GPB5 -> L, buffer direction - read setting s
			rGPBDAT &= ~(1<<6); // 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 &= ~(1<<5);	// GPB5 -> L, buffer direction - read setting -> must change to PIO mode
			rGPBDAT |= (1<<6);	// GPB6 -> H, buffer Output disable 
			break;
	}		
	DbgAta(("BD - rGPBDAT = 0x%x \n",rGPBDAT));
}


⌨️ 快捷键说明

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