📄 ide_ata.c
字号:
{
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 + -