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

📄 ide_ata.c

📁 IDE 驱动程序对开发硬盘驱动很有用,对学习LINUX驱动开发有帮助
💻 C
📖 第 1 页 / 共 5 页
字号:
		{
			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;

			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;
	}

	diskDesc[driveID].driveID = driveID;
	DEBUG_OUT("<ide_init_media> ide %d controller init start\n",driveID);
	return ide_controller_init(&(diskDesc[driveID]));
}
Int32 ide_init_drive(Uint8 driveID, Uint32 *part_count)
{
	Uint32  index;
	Int32   ret;
	Uint32  npart = 0;
	Uint32  partition_count;
	Uint32  ret_mbr;
	Boolean reformat;

	ret = SUCCESS;
	ret_mbr = SUCCESS;
	reformat = FALSE;

	soft_assert(part_count != NULL);
	(*part_count) = 0;

	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;

			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;
	}

	//soft_assert(diskDesc[driveID].initialized == FALSE);
	// the following block will be called only once.

/*
	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);
*/
	diskDesc[driveID].driveID = driveID;
	TRACE_48BIT("ide_init_drive - calling ide_controller_init on phys_disk: %d\n", driveID);
	if (ide_controller_init(&(diskDesc[driveID]))) 
	{
		ret = IDE_IO_ERROR;
		goto IDE_INIT_DRIVE_EXIT;
	}

	// 64 pages in caching... can be changed at will and different between disks 
	initCache(&ide_cache[driveID], WRITE_THROUGH_CACHE, 16);			
	
	npart = 0;
	DEBUG_OUT("!!!!!!!!!!!!!!!! reading MBR of disk: %d maxLBA: %d\n", driveID, diskDesc[driveID].maxLBA);
	ret_mbr = readMBR(driveDesc, driveID, 0, &partition_count);
	DEBUG_OUT("!!!!!!!!!!!!!!!!!!!!! result of readMBR %d \n", ret_mbr);
	if (ret_mbr != SUCCESS)
	{
		// Reformat if failing in reading MBR or there is 0 partition in the disk
		if (ret_mbr == IDE_BADMBR)
		{
			ret = IDE_BADMBR;
			goto IDE_INIT_DRIVE_EXIT;
		}
		else
		{
			ret = IDE_INTERNAL;
			goto IDE_INIT_DRIVE_EXIT;
		}
	}
	else
	{
		diskDesc[driveID].initialized = TRUE;
		npart += partition_count;
	}

	DEBUG_OUT("After readMBR, got %d partitions for drive: %d:\n", npart, driveID);
	{
		Uint8 count = 0;
		for (index = 0; index < (NDISKS * NDRIVES); index++) 
		{
			if ((driveDesc[index].fat_type != 0) && (driveDesc[index].phys_disk == driveID))
			{
				DEBUG_OUT("Type %x, start %x, end %x\n", 
					driveDesc[index].fat_type, 
					driveDesc[index].drv_start, 
					driveDesc[index].drv_end);
				count++;
			}
		}
		soft_assert(count == npart);
	}

	// Set the initial multiple
	if (diskDesc[driveID].maxMultipleTransfer > 1)
	{
		diskDesc[driveID].currentMultipleTransfer = diskDesc[driveID].maxMultipleTransfer;
		if (ide_set_multiple(driveID, diskDesc[driveID].maxMultipleTransfer) != 0)
		{
			DEBUG_OUT("set multiple failed init\n");
			soft_assert_fc(0);
			diskDesc[driveID].initialized = FALSE;
			ret = IDE_INTERNAL;
			goto IDE_INIT_DRIVE_EXIT;
		}
	}

IDE_INIT_DRIVE_EXIT:
	if (ret != SUCCESS)
	{
		soft_assert(ide_invalidate(driveID) == SUCCESS);
	}
	else
	{
		soft_assert(ret == SUCCESS);
		(*part_count) = npart;
	}
	return ret;
}

Int32 ide_diag_identify(Uint8 driveID, IDE_DIAG_IDENTIFY_RESULT *result)
{
	Int32 ret;
	Uint8 *tempBuffer;
	Uint32 i;
	Boolean reset_diag_mode = FALSE;
#if 1
	Uint16 w84, w87;
	Uint64	MaxUsrLBA = 0;
	Uint32  maxUsrLBA_H, maxUsrLBA_L;
#endif

	ret = SUCCESS;
	if (ide_diag_mode == FALSE)
	{
		ide_diag_mode = TRUE;
		reset_diag_mode = TRUE;
	}

	tempBuffer = NULL;
	tempBuffer = (Uint8 *) OS_Malloc(512 * sizeof(Uint8));
	if (tempBuffer == NULL) 
	{
		LOG_DIAG_ERROR("IDE diag identify cannot allocate buffer\n");
		ret = IDE_IO_ERROR;
		goto IDE_DIAG_IDENTIFY_EXIT;
	}
	tempBuffer = (Uint8 *)KSEG1(tempBuffer);
	
	/* First issue a reset to the controller without interrupts! */
	ATA_Command (driveID, 0x08);
	
	/* Get the hard drive parameters (number heads and sectors) */
	// Interrogate drive.
	if (ide_command_identify (driveID, (Uint8 *)tempBuffer))
	{
		LOG_DIAG_ERROR("IDE command identify failed\n");
		ret = IDE_IO_ERROR;
		goto IDE_DIAG_IDENTIFY_EXIT;
	}

	// block is the multiple size
	result->maxMultipleTransfer = tempBuffer[94];
#if 1
	SWAP32(&result->maxLBA, (Uint32 *) &tempBuffer[120]);
	TRACE_BIG("!!!!!!!!!!!!!!! ide_command_identify gave %d max LBA\n", result->maxLBA);
	if ( result->maxLBA >= 0xFFFFFFF )
	{
		SWAP32(&maxUsrLBA_L, (Uint32 *) &tempBuffer[200]);
		SWAP32(&maxUsrLBA_H, (Uint32 *) &tempBuffer[204]);
		MaxUsrLBA = maxUsrLBA_H;
		MaxUsrLBA = MaxUsrLBA << 32;
		MaxUsrLBA = MaxUsrLBA | (Uint64) maxUsrLBA_L;
		SWAP16(&w84, (Uint16 *) &tempBuffer[168]);
		SWAP16(&w87, (Uint16 *) &tempBuffer[174]);

		if ( (MaxUsrLBA > 0xFFFFFFF)   &&    ( (w84 & 0xc000) == 0x4000) && ((w87 & 0xc000) == 0x4000 ) )
		{
			result->supports48bitAddFeatureSet = TRUE;
			TRACE_BIG("!!!!!!!!!!!!!! HDD is size > 137 GB setting it to TRUE \n");
			soft_assert(MaxUsrLBA <= 0xFFFFFFFF);
			result->maxLBA = (Uint32) MaxUsrLBA;
		}
	}
#else
	SWAP32(&result->maxLBA, (Uint32 *) &tempBuffer[120]);
#endif
	 
	memset(result->serial, 0, 20);
	memset(result->firmware, 0, 8);
	memset(result->model, 0, 40);

	for (i = 0; i < (20 / 4); i += 4)
	{
		result->serial[i] = tempBuffer[20 + i + 1];
		result->serial[i+1] = tempBuffer[20 + i];
		result->serial[i+2] = tempBuffer[20 + i + 3];
		result->serial[i+3] = tempBuffer[20 + i + 2];
	}

	for (i = 0; i < (8 / 4); i += 4)
	{
		result->firmware[i] = tempBuffer[46 + i + 1];
		result->firmware[i+1] = tempBuffer[46 + i];
		result->firmware[i+2] = tempBuffer[46 + i + 3];
		result->firmware[i+3] = tempBuffer[46 + i + 2];
	}

	for (i = 0; i < (40 / 4); i += 4)
	{
		result->model[i] = tempBuffer[54 + i + 1];
		result->model[i+1] = tempBuffer[54 + i];
		result->model[i+2] = tempBuffer[54 + i + 3];
		result->model[i+3] = tempBuffer[54 + i + 2];
	}

	/* Now perform drive diagnostics */
	if (ide_command_diags(driveID) )
	{
		LOG_DIAG_ERROR("IDE command diagnostic failed\n");
		ret = IDE_IO_ERROR;
		goto IDE_DIAG_IDENTIFY_EXIT;
	}
 	

IDE_DIAG_IDENTIFY_EXIT:
	if (tempBuffer != NULL)
		OS_Free((Uint8 *) KSEG0(tempBuffer));
	tempBuffer = NULL;
	if (reset_diag_mode == TRUE)
		ide_diag_mode = FALSE;
	return ret;
}

//-----------------------------------------------------------------------------
//  Function: ide_controller_init
//
//  Description:
//      This routine does the following operations:
//          . Issues a reset over the IDE bus
//          . Installs the hard disk interupt vector
//          . Requests all drives to perform diagnostics
//   
//-----------------------------------------------------------------------------
static Int32 ide_controller_init(ide_drive_desc* desc)
{
	Uint8   *tempBuffer;
	Uint16  cfa, i;
	Int32	retVal = IDE_IO_ERROR;
	Uint8   powerMode;
	//Uint8   retry = 5;
	
#if 1
	Uint16  w84, w87;
	Uint64	MaxUsrLBA = 0;
	Uint32  maxUsrLBA_H, maxUsrLBA_L;
#endif
	
	ATA_LockInit();
	tempBuffer = NULL;
	tempBuffer = (Uint8 *) OS_Malloc(512 * sizeof(Uint8));
	if (tempBuffer == NULL) 
	{
		ErrPrint("Malloc failed\n");
		goto ABORT;
	}
	tempBuffer = (Uint8 *)KSEG1(tempBuffer);
	
	/* First issue a reset to the controller without interrupts! */
	//ATA_Reset(desc->driveID, 0);
	//ATA_Command (desc->driveID, 0x08);
	//ATA_SetInt(desc->driveID, FALSE);
	ATA_WaitNotBusy(desc->driveID, HD_WAIT_TIMEOUT);

	if (!ide_command_check_power_mode(desc->driveID, &powerMode))
	{
		DEBUG_OUT("Ide power mode %d\n", powerMode);
		if (powerMode == 0)
		{
			ide_command_idle_immediate(desc->driveID);
		}
	}

	/* Get the hard drive parameters (number heads and sectors) */
	
	// Interrogate drive.

	if (ide_command_identify (desc->driveID, (Uint8 *)tempBuffer))
		goto ABORT;

	SWAP16(&cfa, (Uint16 *) &tempBuffer[0]);
	if (  cfa & 0x80 )
		desc->IsRemovableMediaDevice = TRUE;
	else
		desc->IsRemovableMediaDevice = FALSE;


	/*if ( desc->IsRemovableMediaDevice )
	{
		ide_command_enable_msns(desc->driveID);
 
		while (ide_command_media (desc->driveID))
		{
			if (retry == 0)
			{
				OS_Free((Uint8 *) KSEG0(tempBuffer));
				return IDE_IO_ERROR;
			}
			OS_TaskDelay(10);
			retry --;
		}
	}*/

	// block is the multiple size
	desc->maxMultipleTransfer = tempBuffer[94];
	desc->currentMultipleTransfer = 0;

#if 1
	SWAP32(&desc->maxLBA, (Uint32 *) &tempBuffer[120]);
	TRACE_48BIT("!!!!!!!!!!!!!!! ide_command_identify gave %d max LBA driverID %d\n", desc->maxLBA,desc->driveID);
	if ( desc->maxLBA >= 0xFFFFFFF )
	{
		SWAP32(&maxUsrLBA_L, (Uint32 *) &tempBuffer[200]);
		SWAP32(&maxUsrLBA_H, (Uint32 *) &tempBuffer[204]);
		MaxUsrLBA = maxUsrLBA_H;
		MaxUsrLBA = MaxUsrLBA << 32;
		MaxUsrLBA = MaxUsrLBA | (Uint64) maxUsrLBA_L;
		SWAP16(&w84, (Uint16 *) &tempBuffer[168]);
		SWAP16(&w87, (Uint16 *) &tempBuffer[174]);

		if ( (MaxUsrLBA > 0xFFFFFFF)   &&    ( (w84 & 0xc000) == 0x4000) && ((w87 & 0xc000) == 0x4000 ) )
		{
			desc->supports48bitAddFeatureSet = TRUE;
			TRACE_48BIT("!!!!!!!!!!!!!! HDD is size > 137 GB setting it to TRUE \n");
			soft_assert(MaxUsrLBA <= 0xFFFFFFFF);
			desc->maxLBA = (Uint32) MaxUsrLBA;
		}
	}
#else
	SWAP32(&desc->maxLBA, (Uint32 *) &tempBuffer[120]);
#endif
	DEBUG_OUT("ide_command_identify gave %d max LBA\n", desc->maxLBA);
 
	memset(desc->serial, 0, 20);
	memset(desc->firmware, 0, 8);
	memset(desc->model, 0, 40);

	for (i = 0; i < (20 / 4); i += 4)
	{
		desc->serial[i] = tempBuffer[20 + i + 1];
		desc->serial[i+1] = tempBuffer[20 + i];
		desc->serial[i+2] = tempBuffer[20 + i + 3];
		desc->serial[i+3] = tempBuffer[20 + i + 2];
	}

	for (i = 0; i < 8; i += 4)
	{
		desc->firmware[i] = tempBuffer[46 + i + 1];
		desc->firmware[i+1] = tempBuffer[46 + i];
		desc->firmware[i+2] = tempBuffer[46 + i + 3];
		desc->firmware[i+3] = tempBuffer[46 + i + 2];
	}

	for (i = 0; i < (40 / 4); i += 4)
	{
		desc->model[i] = tempBuffer[54 + i + 1];
		desc->model[i+1] = tempBuffer[54 + i];
		desc->model[i+2] = tempBuffer[54 + i + 3];
		desc->model[i+3] = tempBuffer[54 + i + 2];
	}

	TRACE_ID("!!!!!!!!!!!!!! serial  : %s\n", desc->serial);
	TRACE_ID("!!!!!!!!!!!!!! firmware: %s\n", desc->firmware);
	TRACE_ID("!!!!!!!!!!!!!! model   : %s\n", desc->model);




	if (  !strncasecmp(desc->model, "ATA16V2 M2C4",12) ||  !strncasecmp(desc->model,"EV V4.0 ATA4",12) )
	{
		desc->MediaDeviceBrand = MEDIADEVICE_BRAND_SAIN;
	}else if (!strncasecmp(desc->model, "OnSpec Elect",12))
	{
		desc->MediaDeviceBrand = MEDIADEVICE_BRAND_ONSPEC;
	}else 
	{
		desc->MediaDeviceBrand = MEDIADEVICE_BRAND_UNKNOWN;
	}

	if (desc->IsRemovableMediaDevice)
	{
		ide_command_enable_msns(desc->driveID);	
	}
	else
	{
	    /* Now perform drive diagnostics */
	    if (ide_command_diags(desc->driveID) )
				goto ABORT;
	}
	retVal = SUCCESS;
		
ABORT:	
	OS_Free((Uint8 *) KSEG0(tempBuffer));
	ATA_ReleaseInit();
	return retVal;
}

int ide_io(Uint8 driveno,Uint32 sector,void *buffer,Uint16 count,Uint8 reading, void *ctxt)
{
#ifdef STREAM_ENABLE
	if (ctxt == 0)
	{
		Boolean use_cache;
		use_cache = TRUE;
		return ide_exec(driveno, sector, buffer, count, reading, use_cache);
	}
	else
	{
		ctxtIdeClient *ptr;
		msgStreamCmd msg;
		OS_MSG_Q_ID msgQID; 

		ptr = (ctxtIdeClient *)ctxt;

		//TRACE_DEBUG("!!!!!!!!!!!!!!! ide io called\n");

		// Build the message
		msg.clientID = ptr->clientID;
		msg.cmd.ideCmd.driveNo = driveno;
		msg.cmd.ideCmd.sector = sector;
		msg.cmd.ideCmd.buffer = buffer;
		msg.cmd.ideCmd.count = count;
		msg.cmd.ideCmd.reading = reading;
		msg.cmd.ideCmd.semID = ptr->semID;

		// Grab hold of the sempahore
		OS_SemTake(msg.cmd.ideCmd.semID, OS_WAIT_FOREVER);

		// Send the message over 
		soft_assert(hdd_scheduler_msgQueueID(&msgQID) == SUCCESS);

⌨️ 快捷键说明

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