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

📄 ide_ata.c

📁 IDE 驱动程序对开发硬盘驱动很有用,对学习LINUX驱动开发有帮助
💻 C
📖 第 1 页 / 共 5 页
字号:
				ATA_REG_STATUS
			);

		// Device is not busy, check DRQ
		if ( !(status & ATA_STATUS_BSY) &&
			((status & ATA_STATUS_DRDY) == ATA_STATUS_DRDY) )
		{  
			/* BSY = 0, DRQ = ATA_STATUS_DRDY */
			break;
		}
		
		// Check for timeout
		if ( (tickGet() - tickCnt) > HD_WAIT_TIMEOUT )
		{
			TRACE_ERROR("<ide_command_media> Timeout Waiting For Drive Drdy 2\n");
			//soft_assert(0);
			ATA_WriteRegister(driveID, ATA_REG_DEVICE_CONTROL, ATA_DEVICE_CTRL_SRT_BIT | ATA_DEVICE_CTRL_nIEN_BIT);
			ATA_ReleaseDevice(driveID);
			ATA_ReleaseBus (driveID);
			return (IDE_ERRORCODE_TIMEOUT);
		}
	}

	if ((status & ATA_STATUS_ERR) == ATA_STATUS_ERR)
	{
		retVal = ATA_ReadRegister(driveID, ATA_REG_ERROR);
	}
	else
	{
		retVal = ATA_SUCCESS;
	}

	ATA_ReleaseDevice(driveID);
	ATA_ReleaseBus (driveID);

	return retVal;
}
#else
Int32 ide_command_media(Uint8 driveID)
{
	IDE_Cmd cmd;

	cmd.cmdCode = IDE_CMD_MEDIA;
	cmd.sectorCntReg = 0;
	cmd.lba = 0;
	cmd.driveID = driveID;
	if( diskDesc[driveID].MediaDeviceBrand == MEDIADEVICE_BRAND_ONSPEC)
	{
		cmd.featureReg = 0;
	}else
	{
		cmd.featureReg = 1;
	}
	cmd.pktCmd = NULL;
	cmd.pktCmdSize = 0;
	cmd.data = NULL;
	cmd.deviceReg = 0;
	cmd.readWrite = 0;
	cmd.maxDataSize = 0;
	cmd.ext_cmd = FALSE;

	return IDE_SendCmd(&cmd);
}
#endif

static Int32 ide_initial_devices(Uint8 current_driveID)
{
	Int32	retVal = SUCCESS;

	if ( diskDesc[current_driveID].IsRemovableMediaDevice) 
		retVal = ide_command_enable_msns(current_driveID);

	return retVal;
}

Int32 ide_change_status(Uint8 driveID, IDE_STATE status)
{
	switch (status)
	{
		case IDE_STATE_UPGRADE_FIRMWARE:
			diskDesc[driveID].state= IDE_STATE_UPGRADE_FIRMWARE;
			break;
			
		case IDE_STATE_IDLE:
			diskDesc[driveID].state= IDE_STATE_IDLE;
			break;

		default :
			break;
	}
	return SUCCESS;
}

Int32 ide_inquire_media(Uint8 driveID)
{
	Int32	retVal;

	if (diskDesc[driveID].state == IDE_STATE_UPGRADE_FIRMWARE)
	{
		retVal = MEDIA_NO_MEDIA;
	}
	else if ( diskDesc[driveID].mediaChanged)
	{
		retVal = MEDIA_CHANGED;
	}
	else if ( diskDesc[driveID].IsRemovableMediaDevice) 
	{
		if(ATA_reseted(driveID))
		{
			ide_initial_devices(driveID);
			retVal = MEDIA_NO_MEDIA;
		}
		else
		{
			retVal = ide_command_media (driveID);
			if (retVal == MEDIA_READING)
			{
				ide_initial_devices(driveID);
				retVal = ide_command_media (driveID);
			}
		}
	}
	else
	{
		retVal = MEDIA_UNREMOVALBE;
	}
	
	diskDesc[driveID].mediaChanged = FALSE;
	return retVal;
}

Int32 ide_command_enable_msns(Uint8 driveID)
{
	IDE_Cmd cmd;

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

	cmd.cmdCode = IDE_CMD_MSNS;
	cmd.sectorCntReg = 0;
	cmd.lba = 0;
	cmd.driveID = driveID;
	cmd.featureReg = 0x95;
	cmd.pktCmd = NULL;
	cmd.pktCmdSize = 0;
	cmd.data = NULL;
	cmd.deviceReg = 0;
	cmd.readWrite = 0;
	cmd.maxDataSize = 0;
	cmd.ext_cmd = FALSE;

	return IDE_SendCmd(&cmd);
}

Int32 ide_command_disable_msns(Uint8 driveID)
{
	IDE_Cmd cmd;

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

	cmd.cmdCode = IDE_CMD_MSNS;
	cmd.sectorCntReg = 0;
	cmd.lba = 0;
	cmd.driveID = driveID;
	cmd.featureReg = 0x31;
	cmd.pktCmd = NULL;
	cmd.pktCmdSize = 0;
	cmd.data = NULL;
	cmd.deviceReg = 0;
	cmd.readWrite = 0;
	cmd.maxDataSize = 0;
	cmd.ext_cmd = FALSE;

	return IDE_SendCmd(&cmd);
}

int ide_invalidate(Uint8 driveID)
{
	Uint32 i;

	for (i = 0; i < (NDISKS * NDRIVES); i++)
	{
		if ((driveDesc[i].fat_type != 0) && 
			(driveDesc[i].phys_disk == driveID))
		{
			if (driveDesc[i].open_count > 0)
				return IDE_BADDRIVE;	

			driveDesc[i].fat_type = 0;
			driveDesc[i].drv_start = 0L;
			driveDesc[i].drv_end   = 0L;
			driveDesc[i].open_count= 0;
			driveDesc[i].phys_disk = 0; // we'll need to change that if we want to support several HD
			driveDesc[i].part_no = 0;
		}
	}

	if (diskDesc[driveID].IsRemovableMediaDevice)
	{
		diskDesc[driveID].driveID = 0;
		diskDesc[driveID].maxLBA = 0;
		diskDesc[driveID].maxMultipleTransfer = 0;
		diskDesc[driveID].currentMultipleTransfer = 0;
		diskDesc[driveID].supports48bitAddFeatureSet = FALSE;
		diskDesc[driveID].initialized = FALSE;
		diskDesc[driveID].mediaChanged = FALSE;
	}
	else
	{
		diskDesc[driveID].driveID = 0;
		diskDesc[driveID].maxLBA = 0;
		diskDesc[driveID].maxMultipleTransfer = 0;
		diskDesc[driveID].currentMultipleTransfer = 0;
		diskDesc[driveID].IsRemovableMediaDevice = FALSE;
		diskDesc[driveID].supports48bitAddFeatureSet = FALSE;
		diskDesc[driveID].initialized = FALSE;
		diskDesc[driveID].mediaChanged = FALSE;
	}

	// Close the ide
	closeCache(&ide_cache[driveID]);

	return SUCCESS;
}

Int32 ide_reset_MBR(Uint8 driveID)
{
	// Disk must be invalidated after reset MBR
	Int32 ret = SUCCESS;

	diskDesc[driveID].driveID = driveID;
	TRACE_48BIT("ide_reset_MBR - calling ide_controller_init on phys_disk: %d\n", driveID);
	if (ide_controller_init(&(diskDesc[driveID]))) 
	{
		ret = IDE_INTERNAL;
		goto IDE_RESET_MBR_EXIT;
	}

	// Now reset the MBR
	soft_assert(writeMBR(driveID, 0, diskDesc[driveID].maxLBA) == SUCCESS);

IDE_RESET_MBR_EXIT:
	soft_assert(ide_invalidate(driveID) == SUCCESS);
	return ret;
}

//-----------------------------------------------------------------------------
//  Function: ide_open
//
//  Description:
//      Open function. This is pointed to by the bdevsw[] table
//      
//
//  Returns: Uint8
//      
//
//-----------------------------------------------------------------------------
#ifdef FORCE_FORMAT
static Boolean force_format_flag = TRUE;
#endif
int ide_open(Uint8 driveID, Uint8 partno, Boolean force_format, Uint8 *driveno)
{
	Int32   ret = SUCCESS;
	Uint32  i, index;
	Uint32  part_count;

	DEBUG_OUT("ide_open1 driverId %d\n",driveID);

	if (!ide_initialized)	// Nothing has been initialized yet...
	{
		for (index = 0; index < NDISKS; index++)
		{
			diskDesc[index].driveID = 0;
			diskDesc[index].maxLBA = 0;
			diskDesc[index].maxMultipleTransfer = 0;
			diskDesc[index].currentMultipleTransfer = 0;
			diskDesc[index].initialized = FALSE;
			diskDesc[index].IsRemovableMediaDevice = FALSE;
			diskDesc[index].supports48bitAddFeatureSet = FALSE;
			diskDesc[index].state = IDE_STATE_IDLE;

			ide_cache[index].pages = NULL;
			ide_cache[index].data = NULL;
		}

		for (index = 0; index < (NDRIVES * NDISKS); index++) 
		{
			driveDesc[index].fat_type = 0;
			driveDesc[index].drv_start = 0L;
			driveDesc[index].drv_end   = 0L;
			driveDesc[index].open_count= 0;
			driveDesc[index].phys_disk = 0; // we'll need to change that if we want to support several HD
			driveDesc[index].part_no = 0;
		}
		ide_initialized = TRUE;
	}

	if (diskDesc[driveID].initialized == FALSE)
	{
		Boolean reset_mbr = FALSE;

		for (i = 0; i < (NDISKS * NDRIVES); i++)
		{
			// Any thing corresponding to this phys_disk needs to be erased
			// Nothing must be pointing to the physical disk it must have been invalidated previously
			if ((driveDesc[i].fat_type != 0) && (driveDesc[i].phys_disk == driveID))
			{
				soft_assert(0);
			}
		}

		// Reset the current variable
		soft_assert(diskDesc[driveID].driveID == 0);
		soft_assert(diskDesc[driveID].maxLBA == 0);
		soft_assert(diskDesc[driveID].maxMultipleTransfer == 0);
		soft_assert(diskDesc[driveID].currentMultipleTransfer == 0);
		//soft_assert(diskDesc[driveID].initialized == FALSE);
		//soft_assert(diskDesc[driveID].IsRemovableMediaDevice == FALSE);
		soft_assert(diskDesc[driveID].supports48bitAddFeatureSet == FALSE);

		part_count = 0;
		ret = ide_init_drive(driveID, &part_count);
#ifdef FORCE_FORMAT
		if (force_format_flag == TRUE)
		{
			ret = IDE_BADMBR;
			soft_assert(ide_invalidate(driveID) == SUCCESS);
		}
#endif

		// Handle error codes
		switch(ret)
		{
		case IDE_BADMBR:
			if (force_format == TRUE)
				reset_mbr = TRUE;
			break;

		case SUCCESS:
		case IDE_IO_ERROR:
			break;

		default:
			soft_assert(0);
			break;
		}
		// Handle 0 partition
		if ((part_count == 0) && (force_format == TRUE))
		{
			if (force_format == TRUE)
				reset_mbr = TRUE;
			else
				ret = IDE_BADMBR;
		}

		// We don't check for multiple partition and if the single
		// partition does not span entire HDD here
		// This is because opening a drive should not make any assumption
		// When the user decides to format, we will give the option
		// to wipe the MBR and not just the partition

		if (reset_mbr == TRUE)
		{
			//soft_assert(ide_invalidate(driveID) == SUCCESS);
			soft_assert(ide_reset_MBR(driveID) == SUCCESS);
			soft_assert(ide_init_drive(driveID, &part_count) == SUCCESS);
			soft_assert(part_count == 1);
			ret = IDE_MBR_RESET;
#ifdef FORCE_FORMAT
			force_format_flag = FALSE;
#endif
		}
		DEBUG_OUT("ide init drive returning ret: %d containing: %d partitions driverID %d\n", ret, part_count,driveID);
	}
	else
	{
/*
		if ( diskDesc[driveID].IsRemovableMediaDevice) 
		{
			if (ide_command_media (driveID))
			{
				return FAIL;
			}
		}
*/
	}
	
	//soft_assert(diskDesc[driveID].initialized == TRUE);
	// If this partition does not exist then return fail
	if (ret == SUCCESS)
	{
		Boolean drive_found = FALSE;
		Uint8 drive_wanted, i;
		drive_wanted = 0;
		for (i = 0; i < (NDISKS * NDRIVES); i++)
		{
			if ((driveDesc[i].fat_type != 0) && 
				(driveDesc[i].phys_disk == driveID) && 
				(driveDesc[i].part_no == partno))
			{
				drive_wanted = i;
				drive_found = TRUE;
			}
		}

		if (drive_found == FALSE)
		{
			// Reset this to false for next time
			diskDesc[driveID].initialized = FALSE;
			LOG_DIAG_ERROR("ide_diag_open requested partition %d for disk: %d is invalid\n", partno, driveID);
			return IDE_BADDRIVE;
		}
		else
		{
			(*driveno) = drive_wanted;
			driveDesc[drive_wanted].open_count += 1;
		}
		soft_assert(diskDesc[driveID].initialized == TRUE);
	}
	else
	{
		LOG_DIAG_ERROR("ide_diag_open ide_init_drive failed with error code: %d\n", ret);
	}

	DEBUG_OUT("ide_open returns: %d driverID %d\n", ret,driveID);
	return ret;
}

#if 0
int ide_open (Uint8 driveno, Boolean force_format)
{
	STATUS ret = SUCCESS;
	DEBUG_OUT("ide_open1\n");
	//if (!ide_initialized)	// Nothing has been initialized yet...
	{
        DEBUG_OUT("ide_open2\n");
        ret = ide_init_drives(force_format);
	}
	
	if ((ret == SUCCESS) || (ret == IDE_REFORMAT_NEEDED))
	{
		DEBUG_OUT("ide_open4\n");
		/* This just counts the number of calls after the initial Open !   */
		driveDesc[driveno].open_count += 1;
	}

	return ret;
}
#endif

//-----------------------------------------------------------------------------
//  Function:
//
//  Description:
//      Close function. This is pointed to by the bdevsw[] table
//
//
//  Returns: Uint8
//
//
//-----------------------------------------------------------------------------
int ide_close(Uint8 driveno)
{
	if (!driveDesc[driveno].open_count)
		return IDE_BADDRIVE;

	driveDesc[driveno].open_count -= 1;
	
	return SUCCESS;
}

Int32 ide_init_media(Uint8 driveID)
{
	Uint32 index;

	if (!ide_initialized)	// Nothing has been initialized yet...
	{
		for (index = 0; index < NDISKS; index++)

⌨️ 快捷键说明

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