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

📄 ide_ata.c

📁 IDE 驱动程序对开发硬盘驱动很有用,对学习LINUX驱动开发有帮助
💻 C
📖 第 1 页 / 共 5 页
字号:
/************************************************************************
//    ide_ata.c
//
//    Modification History:
//          $Id: ide_ata.c,v 1.18 2005/10/05 09:38:06 raphael Exp $
//          $Log: ide_ata.c,v $
//          Revision 1.18  2005/10/05 09:38:06  raphael
//          Merge SONATA2_7_8 into Sonata2Customer head.
//
//          Revision 1.66.4.2  2005/08/17 08:16:27  hwxiao
//          modify HDD sleep mode. add idle Immediate command.
//
//          Revision 1.66.4.1  2005/07/25 04:04:23  shu
//          Synchronize core to SONATA2_6_RC_BRANCH
//
//          Revision 1.65.6.2  2005/07/22 10:35:00  hwxiao
//          fix bug 37512 Card Reader : show firmware version
//
//          Revision 1.65.6.1  2005/06/24 03:06:00  hwxiao
//          fix 37584, add timeout and modify polling module
//
//          Revision 1.65  2005/04/19 21:56:15  rinllow
//          reorganize card reader state machine
//
//          Revision 1.64  2005/04/11 02:09:07  hwxiao
//          fix bug 34912,add parameter for hdd_scheduler_get_cmd_ret
//
//          Revision 1.63  2005/03/23 08:34:45  hwxiao
//          fix bug 32478, if hdd not found, return IDE_IO_ERROR
//
//          Revision 1.62  2005/03/16 09:57:31  hwxiao
//          fix bug 34173,modify invalidate function
//
//          Revision 1.61  2005/02/17 07:19:08  hwxiao
//          fix Bug 33582, clear soft assert if there is Extended MS-DOS Partition
//          on media for flash card
//
//          Revision 1.60  2005/02/17 02:10:23  hwxiao
//          if card reader is disconnected, media thread exit.
//
//          Revision 1.59  2005/02/15 03:06:37  mahashin
//          fix for bug 33566
//          Added ide driver first initialization to ide_open in addition to existing in ide_init_drive to
//          prevent assert on unitialized variable in ide_open.
//
//          Revision 1.58  2005/02/13 22:52:31  mahashin
//          Port of fixes from 2.4.8 branch.
//
//          Revision 1.57  2005/02/10 01:02:52  jsu
//          [30992] added PIO mode to Rio->HDD transfer
//
//          Revision 1.56  2005/02/06 05:31:00  rinllow
//          [32711] fix memory card reader issues
//
//          Revision 1.55  2005/02/02 07:29:28  hwxiao
//          1) fix bug 31418,31479, modify for flash card hot plug
//          2) if card reader is disconnected, error register is 0,return FAIL
//
//          Revision 1.54  2005/01/14 18:24:08  mahashin
//          Added log header
//
//
*************************************************************************/

#include "nucleus.h"
#include "basetype.h"
#include "osapi.h"
#include "apitypes.h"
#include "eromdbg.h"
#include "chips.h"
#include "host.h"
#include "ide.h"
#include "apiconfig.h"
#include "hdcache.h"
#ifdef STREAM_ENABLE
#include "hdd_scheduler.h"
#endif
#include "ata.h"
#include "assert.h"
#include "bsp_io.h"
#include "string.h"

#undef FORCE_FORMAT
//#define FORCE_FORMAT

#define DEBUG_WINDOW                    3
#define TRACE_48BIT(fmt, args...)       //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_BIG(fmt, args...)         //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_DEBUG(fmt, args...)       //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_STDBY(fmt, args...)       //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_ID(fmt, args...)          //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define DEBUG_OUT(fmt, args...)	        //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_CACHE(fmt, args...)       //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_ERROR(fmt, args...)       {ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_WRITE(fmt, args...)       //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}
#define TRACE_READ(fmt, args...)        //{ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}

#define LOG_DIAG_ERROR(fmt, args...)    //{if (ide_diag_mode == TRUE) ERomPrintFunc (DEBUG_WINDOW, fmt, ## args);}

//-----------------------------------------------------------------------------
//  Local definitions
//-----------------------------------------------------------------------------

#define MAX_BLOCKS          256
#define HD_WAIT_TIMEOUT     240

#define CSWAP16(x)    (((Uint16)(x) << 8) | \
	((Uint16)(x) >> 8))
#define CSWAP32(x)    ((((Uint32)(x) >> 24) & 0x000000ff) | \
	(((Uint32)(x) >>  8) & 0x0000ff00) | \
	(((Uint32)(x) <<  8) & 0x00ff0000) | \
	(((Uint32)(x) << 24) & 0xff000000))
#define DRIVE_SELECT(driveID)		    ((driveID & 1) ? 0xB0 : 0xA0)
 

/*==========================================================================*/

ide_drive_desc diskDesc[NDISKS];
logical_drive_desc driveDesc[NDRIVES * NDISKS];

//-----------------------------------------------------------------------------
//  Local functions
//-----------------------------------------------------------------------------
static Int32 ide_command_diags (Uint8 driveID);
static Int32 ide_command_read_sectors (Uint8 * address, Uint16 disk, Uint32 blockno, Uint16 nblocks, Boolean use_cache);
Int32 ide_command_write_sectors(Uint8 * address, Uint16 disk, Uint32 blockno, Uint16 nblocks, Boolean use_cache);
static Int32 ide_controller_init(ide_drive_desc* desc);

//-----------------------------------------------------------------------------
//  External declarations
//-----------------------------------------------------------------------------

extern NU_SEMAPHORE* HstBusSem;

//-----------------------------------------------------------------------------
//  Local variables
//-----------------------------------------------------------------------------

/* The control structure - without too much difficulty we could go to
**   multiple controllers!
*/

static Uint8  ide_initialized = FALSE;
Boolean ide_diag_mode = FALSE;

/* Logical open count per partition. 
** We also increment this on raw opens! */

static cachingSystem ide_cache[NDISKS];

void UtilSwap16(Uint16 *to, Uint16 *from)
{
	Uint8       *fptr;
	Uint8       *tptr;


	fptr = (Uint8 *)from;
	tptr = (Uint8 *)to;

	*tptr = *(fptr + 1);
	*(tptr + 1) = *(fptr);
}

void UtilSwap32(Uint32 *to, Uint32 *from)
{
	Uint8       *fptr;
	Uint8       *tptr;


	fptr = (Uint8 *)from;
	tptr = (Uint8 *)to;

	*tptr = *(fptr + 3);
	*(tptr + 1) = *(fptr + 2);
	*(tptr + 2) = *(fptr + 1);
	*(tptr + 3) = *(fptr);

}

void UtilThrough16(Uint16 *to, Uint16 *from)
{
	Uint8       *fptr;
	Uint8       *tptr;


	fptr = (Uint8 *)from;
	tptr = (Uint8 *)to;

	*tptr = *fptr;
	*(tptr + 1) = *(fptr + 1);
}

void UtilThrough32(Uint32 *to, Uint32 *from)
{
	Uint8       *fptr;
	Uint8       *tptr;


	fptr = (Uint8 *)from;
	tptr = (Uint8 *)to;

	*tptr = *fptr;
	*(tptr + 1) = *(fptr + 1);
	*(tptr + 2) = *(fptr + 2);
	*(tptr + 3) = *(fptr + 3);
}

Int32 ide_device_version(Uint8 driveID, char **firmware_version)
{
	*firmware_version = diskDesc[driveID].firmware;
	TRACE_ID("ide_device_version: 0x%x[%s]\n", firmware_version, firmware_version);
	return SUCCESS;
}

Uint32 ide_set_multiple(Uint8 driveID, Uint32 multiple)
{
	IDE_Cmd cmd;

	if ( diskDesc[driveID].MediaDeviceBrand== MEDIADEVICE_BRAND_SAIN) 
	{
		return SUCCESS;
	}

	cmd.driveID = driveID;
	cmd.cmdCode = IDE_CMD_SETM;
	cmd.sectorCntReg = multiple;
	cmd.lba = 0;
	cmd.featureReg = 0;
	cmd.pktCmd = NULL;
	cmd.pktCmdSize = 0;
	cmd.data = 0;
	cmd.deviceReg = LBA_MODE;
	cmd.readWrite = 0;
	cmd.maxDataSize = 0;
	cmd.ext_cmd = FALSE;

	DEBUG_OUT("set multiple to: %d %d\n", cmd.sectorCntReg, driveID);
	if (IDE_SendCmd(&cmd)) 
	{
		return IDE_IO_ERROR;
	}
	else
	{
		return SUCCESS;
	}
}


//-----------------------------------------------------------------------------
Uint32 IDE_SendCmd(IDE_Cmd *cmd)
{
	Uint32 res;

	// fixme tango look
	ATA_LockBus(cmd->driveID);
	ATA_LockDevice(cmd->driveID);

	res = IDE_Send(cmd);
	switch (cmd->cmdCode)
	{
		case IDE_CMD_MSNS:
		case IDE_CMD_MEDIA:
			if (res)
			{
				res = ATA_ReadRegister(cmd->driveID, ATA_REG_ERROR) & 0xFF;
			}
			else
			{
				//ErrPrint(" MI %x \n", ATA_ReadRegister(cmd->driveID, ATA_REG_SECTOR_NUM));
			}
			break;

		case IDE_CMD_READS_EXT:
		case IDE_CMD_READM_EXT:
		case IDE_CMD_READS:
		case IDE_CMD_READM:
		case IDE_CMD_WRITEDMA_EXT:
		case IDE_CMD_WRITEDMA:
		case IDE_CMD_WRITES_EXT:
		case IDE_CMD_WRITEM_EXT:
		case IDE_CMD_WRITES:
		case IDE_CMD_WRITEM:
		case IDE_CMD_IDLE_IMMEDIATE:
			if (res)
			{
				res  = ATA_ReadRegister(cmd->driveID, ATA_REG_ERROR) & 0xFF;
				ErrPrint("IDE_SendCmd error: driveID[%d] cmd[0x%x] err[0x%x]\n", cmd->driveID, cmd->cmdCode, res);
			}
			break;
			
		case IDE_CMD_MEDIA_TYPE:
			if (res)
			{
				res  = ATA_ReadRegister(cmd->driveID, ATA_REG_ERROR) & 0xFF;
				ErrPrint("IDE_SendCmd error: driveID[%d] cmd[0x%x] err[0x%x]\n", cmd->driveID, cmd->cmdCode, res);
				res = 0;
			}else
			{
				res = ATA_ReadRegister(cmd->driveID, ATA_REG_SECTOR_NUM) & 0xFF;
			}
			break;
			
		default:
			break;
	}

	// fixme tango look
	ATA_ReleaseDevice(cmd->driveID);
	ATA_ReleaseBus(cmd->driveID);

	return res;
}

//-----------------------------------------------------------------------------
Uint32 IDE_Send(IDE_Cmd *cmd) 
{
	unsigned int    byteCnt, byteTx = 0;
	unsigned char   *buf = cmd->data;
	Uint32          error;
	Uint32          status = 0;
	unsigned int    i;
	unsigned int    maxTransfer, totalSecNum;
	ATA_Error_t     retval;
	Uint32          feature;
	Uint32          hd_cmd;

	if ((cmd->pktCmdSize != 0) && (cmd->pktCmdSize != 12)) 
	{
		TRACE_ERROR("Warning, sending IDE_Cmd %x with pktCmdSize %x\n", cmd->cmdCode, cmd->pktCmdSize);
		LOG_DIAG_ERROR("Warning, sending IDE_Cmd %x with pktCmdSize %x\n", cmd->cmdCode, cmd->pktCmdSize);
	}

	//if (ATA_WaitNotBusy(cmd->driveID, HD_WAIT_TIMEOUT) == ATA_FAIL) 
	//{
	//	TRACE_ERROR("Timeout Waiting For Drive Not Busy 1\n");
	//	LOG_DIAG_ERROR("Timeout Waiting For Drive Not Busy 1\n");
	//	return (IDE_ERRORCODE_TIMEOUT);
	//} 

	ATA_WriteRegister(cmd->driveID, ATA_REG_DRIVE_SEL, DRIVE_SELECT(cmd->driveID) | 
		(LBA_MODE & 0x40));

	//if (ATA_WaitNotBusy(cmd->driveID, HD_WAIT_TIMEOUT) == ATA_FAIL) 
	//{
	//	TRACE_ERROR("Timeout Waiting For Drive Not Busy 2\n");
	//	LOG_DIAG_ERROR("Timeout Waiting For Drive Not Busy 2\n");
	//	return (IDE_ERRORCODE_TIMEOUT);
	//}
	
	if (ATA_WaitDriveDRdy(cmd->driveID, HD_WAIT_TIMEOUT) == ATA_FAIL) 
	{
		TRACE_ERROR("Timeout Waiting For Drive Drdy 3 driveID = %d cmd = 0x%x\n", cmd->driveID, cmd->cmdCode);
		LOG_DIAG_ERROR("Timeout Waiting For Drive Drdy 3\n");
		return (IDE_ERRORCODE_TIMEOUT);
	}

	feature = cmd->featureReg;
	hd_cmd  = cmd->cmdCode;

#ifdef RIO_PIO_MODE				           
	if (hd_cmd == IDE_CMD_WRITEDMA)
		hd_cmd = IDE_CMD_WRITEM;
#endif

	retval = ATA_WriteRegister(cmd->driveID, ATA_REG_FEATURE, feature);
	if (retval == ATA_FAIL)
	{
		TRACE_ERROR("retval 4: 0x%x\n", retval);
		LOG_DIAG_ERROR("retval 4: 0x%x\n", retval);
	}

	// Writing the adress differes on 48bit feature set or not
	if (diskDesc[cmd->driveID].supports48bitAddFeatureSet && cmd->ext_cmd)
	//if (diskDesc[cmd->driveID].supports48bitAddFeatureSet == TRUE)
	{
		Uint32 sector_cnt_7_0;
		Uint32 sector_cnt_15_8;
		Uint32 lba_7_0;
		Uint32 lba_15_8;
		Uint32 lba_23_16;
		Uint32 lba_31_24;
		Uint32 lba_39_32;
		Uint32 lba_47_40;
		Uint32 device;

		sector_cnt_7_0  =  cmd->sectorCntReg & 0xFF;
		sector_cnt_15_8 = (cmd->sectorCntReg >> 8) & 0xFF;

		lba_7_0   =  cmd->lba & 0xFF;
		lba_15_8  = (cmd->lba >>  8) & 0xFF;
		lba_23_16 = (cmd->lba >> 16) & 0xFF;
		lba_31_24 = (cmd->lba >> 24) & 0xFF;
		lba_39_32 = 0;
		lba_47_40 = 0;

		// The 48-bit Address feature set operates in LBA only.
		device = LBA_MODE | DRIVE_SELECT(cmd->driveID);

		//TRACE_48BIT("IDE_Send - doing 48bit addressing\n");
		// sector cnt
		retval = ATA_WriteRegister(cmd->driveID, ATA_REG_SECTOR_CNT, sector_cnt_15_8);
		if (retval == ATA_FAIL)
		{
			TRACE_ERROR("retval 5: 0x%x\n", retval);
			LOG_DIAG_ERROR("retval 5: 0x%x\n", retval);
		}
		retval = ATA_WriteRegister(cmd->driveID, ATA_REG_SECTOR_CNT, sector_cnt_7_0);
		if (retval == ATA_FAIL)
		{
			TRACE_ERROR("retval 5: 0x%x\n", retval);
			LOG_DIAG_ERROR("retval 5: 0x%x\n", retval);
		}

		// lba low
		retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_LOW, lba_31_24);
		if (retval == ATA_FAIL)
		{
			TRACE_ERROR("retval 6: 0x%x\n", retval);
			LOG_DIAG_ERROR("retval 6: 0x%x\n", retval);
		}
		retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_LOW, lba_7_0);
		if (retval == ATA_FAIL)
		{
			TRACE_ERROR("retval 6: 0x%x\n", retval);
			LOG_DIAG_ERROR("retval 6: 0x%x\n", retval);
		}

		// lba mid
		retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_MID, lba_39_32); 
		if (retval == ATA_FAIL)
		{
			TRACE_ERROR("retval 7: 0x%x\n", retval);
			LOG_DIAG_ERROR("retval 7: 0x%x\n", retval);
		}
		retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_MID, lba_15_8);
		if (retval == ATA_FAIL)
		{
			TRACE_ERROR("retval 7: 0x%x\n", retval);
			LOG_DIAG_ERROR("retval 7: 0x%x\n", retval);
		}

		// lba high
		retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_HIGH, lba_47_40); 
		if (retval == ATA_FAIL)
		{
			TRACE_ERROR("retval 8: 0x%x\n", retval);
			LOG_DIAG_ERROR("retval 8: 0x%x\n", retval);
		}
		retval = ATA_WriteRegister(cmd->driveID, ATA_REG_LBA_HIGH, lba_23_16);
		if (retval == ATA_FAIL)
		{
			TRACE_ERROR("retval 8: 0x%x\n", retval);
			LOG_DIAG_ERROR("retval 8: 0x%x\n", retval);
		}

		// device
		retval = ATA_WriteRegister(cmd->driveID, ATA_REG_DRIVE_SEL, device);
		if (retval == ATA_FAIL)
		{
			TRACE_ERROR("retval 9: 0x%x\n", retval);
			LOG_DIAG_ERROR("retval 9: 0x%x\n", retval);
		}
	}
	else
	{
		Uint32 sector_cnt;
		Uint32 lba_low;
		Uint32 lba_mid;
		Uint32 lba_high;
		Uint32 device;

		sector_cnt = cmd->sectorCntReg;
		lba_low  =  cmd->lba & 0xFF;
		lba_mid  = (cmd->lba >> 8) & 0xFF;
		lba_high = (cmd->lba >> 16) & 0xFF;
		device   = 
			DRIVE_SELECT(cmd->driveID) | 
			(cmd->deviceReg & LBA_MODE) |		
			((cmd->lba >> 24) & 0x0F);

		//TRACE_48BIT("IDE_Send - doing regular addressing\n");
		// sector cnt
		retval = ATA_WriteRegister(cmd->driveID, ATA_REG_SECTOR_CNT, sector_cnt);

⌨️ 快捷键说明

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