📄 config.c
字号:
MmUnmapIoSpace(ConfigData->ControlPortAddress,
ConfigData->RangeOfControlPort);
}
//
// return failure status
//
return(STATUS_NO_SUCH_DEVICE);
}
//
// We have a drive, so now issue the IDENTIFY command and
// get back some disk geometry information
//
if (!IssueIdentify(ConfigData, buffer)) {
//
// The IDENTIFY failed,
//
#if DBG
DbgPrint("IdeGetDiskConfig: IDENITFY issuance failed\n");
#endif
//
// Unmap the ControllerBase
//
if (ConfigData->ControllerBaseMapped) {
MmUnmapIoSpace(ConfigData->ControllerBaseAddress,
ConfigData->RangeOfControllerBase);
}
//
// Unmap the ControlPort
//
if (ConfigData->ControlPortMapped) {
MmUnmapIoSpace(ConfigData->ControlPortAddress,
ConfigData->RangeOfControlPort);
}
//
// return failure
//
return(STATUS_NO_SUCH_DEVICE);
}
//
// store some of the geometry
//
ConfigData->Disk.IdentifyNumberOfCylinders =
((PIDENTIFY_DATA)buffer)->NumberOfCylinders;
ConfigData->Disk.IdentifyTracksPerCylinder =
((PIDENTIFY_DATA)buffer)->NumberOfHeads;
ConfigData->Disk.IdentifySectorsPerTrack =
((PIDENTIFY_DATA)buffer)->SectorsPerTrack;
//
// Map BIOS vector 41
//
tmpPtr.QuadPart = PTR_TO_FDPT0_ADDRESS;
paramVector = MmMapIoSpace(tmpPtr, sizeof(ULONG), FALSE);
if( (*paramVector) == 0) {
//
// the MmMapIoSpace() was unsuccessful, so we have to
// quit.
//
#if DBG
DbgPrint("IdeGetDiskConfig: MmMapIoSpace failure for BIOS parameter table\n");
#endif
//
// Unmap the ControllerBase
//
if (ConfigData->ControllerBaseMapped) {
MmUnmapIoSpace(ConfigData->ControllerBaseAddress,
ConfigData->RangeOfControllerBase);
}
//
// Unmap the ControlPort
//
if (ConfigData->ControlPortMapped) {
MmUnmapIoSpace(ConfigData->ControlPortAddress,
ConfigData->RangeOfControlPort);
}
//
// return failure
//
return(STATUS_NO_SUCH_DEVICE);
}
//
// We've mapped the bios, so now update the ConfigData
// structure with the bios information
//
UpdateWithBios(ConfigData,((*(paramVector + 1)) << 4) + *paramVector);
//
// Now we check the registry to see if there are
// any parameters within the registry that needs to
// modify the BIOS configuration data
//
ReconcileWithRegistry(DriverObject, ConfigData);
//
// unmap the BIOS
//
MmUnmapIoSpace(paramVector, sizeof(ULONG));
//
// if we've sucessfully completed all of the above,
// then we've found a disk, so return success
//
return(STATUS_SUCCESS);
}
///////////////////////////////////////////////////////////////////////////////
//
// UpdateWithBios
//
// This routine updates the DISK_EXTENSION data in the configData from
// the BIOS parameter table
//
// INPUTS:
//
// ConfigData - device configuration data
// ControlFlags - points to value to set in controller for init
// ParameterTableOffset - ROM address of the BIOS table
//
// OUTPUTS:
//
// ConfigData - updated information
//
// RETURNS:
//
// None.
//
// IRQL:
//
// IRQL_PASSIVE_LEVEL
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
static VOID
UpdateWithBios(PCONFIG_DATA ConfigData,
ULONG ParameterTableOffset)
{
PFIXED_DISK_PARAMETER_TABLE parameterTable;
PDRIVE_DATA driveData = (&ConfigData->Disk);
LARGE_INTEGER p;
p.QuadPart = ParameterTableOffset;
parameterTable = MmMapIoSpace(p, DRIVE_PARAMETER_TABLE_LENGTH, FALSE);
//
// Initialize this drive.
//
driveData->BytesPerSector = 512;
driveData->BytesPerInterrupt = 512;
driveData->ReadCommand = 0x20;
driveData->WriteCommand = 0x30;
driveData->VerifyCommand = 0x40;
driveData->PretendNumberOfCylinders = parameterTable->MaxCylinders;
driveData->PretendTracksPerCylinder = parameterTable->MaxHeads;
driveData->PretendSectorsPerTrack = parameterTable->SectorsPerTrack;
driveData->WritePrecomp = parameterTable->StartWritePrecomp;
//
// store the control flags
//
ConfigData->ControlFlags = parameterTable->ControlFlags;
//
// Some of these values might have been "pretend" values useful for
// dealing with DOS. If so, determine the real values.
//
if ((parameterTable->Signature & 0xf0) == 0xa0) {
//
// The values obtained were fake; get the real ones.
//
driveData->NumberOfCylinders = parameterTable->TranslatedMaxCylinders;
driveData->TracksPerCylinder = parameterTable->TranslatedMaxHeads;
driveData->SectorsPerTrack = parameterTable->TranslatedSectorsPerTrack;
} else {
//
// The values obtained were correct (as far as it goes).
//
driveData->NumberOfCylinders = parameterTable->MaxCylinders;
driveData->TracksPerCylinder = parameterTable->MaxHeads;
driveData->SectorsPerTrack = parameterTable->SectorsPerTrack;
}
//
// unmap the BIOS parmaeter table and return
//
MmUnmapIoSpace(parameterTable, sizeof(FIXED_DISK_PARAMETER_TABLE));
return;
}
///////////////////////////////////////////////////////////////////////////////
//
// ReconcileWithRegistry
//
// This routine checks the geometry data returned from the bios with
// information in the registry
//
// INPUTS:
//
// DriverObject - pointer to our driver object
// ConfigData - current configuration data
//
// OUTPUTS:
//
// ConfigData - updated configuration data
//
// RETURNS:
//
// TRUE if information for this disk existed in the registry from BIOS
//
// IRQL:
//
// IRQL_PASSIVE_LEVEL
//
// NOTES:
//
///////////////////////////////////////////////////////////////////////////////
static BOOLEAN
ReconcileWithRegistry(PDRIVER_OBJECT DriverObject,
PCONFIG_DATA ConfigData)
{
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING valueName;
NTSTATUS status;
PCM_FULL_RESOURCE_DESCRIPTOR resourceDescriptor;
PKEY_VALUE_FULL_INFORMATION keyData;
PUCHAR buffer;
ULONG length;
ULONG numberOfDrives;
HANDLE biosKey;
PCM_INT13_DRIVE_PARAMETER int13ParamTable;
PDRIVE_DATA driveData = (&ConfigData->Disk);
//
// Initialize the object for the key.
//
InitializeObjectAttributes(&objectAttributes,
DriverObject->HardwareDatabase,
OBJ_CASE_INSENSITIVE,
NULL,
(PSECURITY_DESCRIPTOR) NULL);
//
// Create the key.
//
status = ZwOpenKey(&biosKey,
KEY_READ,
&objectAttributes);
//
// If the key's not there, then we dont' have much to do
//
if (!NT_SUCCESS(status)) {
return FALSE;
}
//
// Look for "Configuration Data" as the value
//
RtlInitUnicodeString(&valueName, L"Configuration Data");
//
// allocate memory for the expected information
//
keyData = ExAllocatePool(PagedPool, 2048);
//
// However, if we don't get any memory...
//
if (keyData == NULL) {
ZwClose(biosKey);
return(FALSE);
}
//
// query the registry for this guy
//
status = ZwQueryValueKey(biosKey,
&valueName,
KeyValueFullInformation,
keyData,
2048,
&length);
ZwClose(biosKey);
//
// if the key did not exist, then we're done
//
if (!NT_SUCCESS(status)) {
ExFreePool(keyData);
return(FALSE);
}
//
// key existed, so we need to decode the data
//
resourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR) keyData +
keyData->DataOffset);
//
// check the lengths
//
if (keyData->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR) ||
resourceDescriptor->PartialResourceList.Count == 0 ||
resourceDescriptor->PartialResourceList.PartialDescriptors[0].Type !=
CmResourceTypeDeviceSpecific ||
resourceDescriptor->PartialResourceList.PartialDescriptors[0]
.u.DeviceSpecificData.DataSize < sizeof(ULONG)
)
{
//
// the lenght didn't add up right, so we fail
//
ExFreePool(keyData);
return FALSE;
}
length = resourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize;
//
// Point to the BIOS data. The BIOS data is located after the first
// partial Resource list which should be device specific data.
//
buffer = (PUCHAR) keyData + keyData->DataOffset +
sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
//
// determine the number of CM_INT13_DRIVE_PARAMETER structures based
// on the length of the data
//
numberOfDrives = length / sizeof(CM_INT13_DRIVE_PARAMETER);
//
// Use the defaults if the drive number is greater than the
// number of drives detected by the BIOS.
//
if (numberOfDrives <= 0)
{
ExFreePool(keyData);
return FALSE;
}
//
// Point to the array of drive parameters.
//
int13ParamTable = (PCM_INT13_DRIVE_PARAMETER) buffer;
driveData->PretendNumberOfCylinders = (USHORT)(int13ParamTable->MaxCylinders + 1);
driveData->PretendTracksPerCylinder = (int13ParamTable->MaxHeads + 1);
driveData->PretendSectorsPerTrack = int13ParamTable->SectorsPerTrack;
//
// all done. Cleanup and go home
//
ExFreePool(keyData);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
//
// IssueIdentify
//
// This routine issues the IDENTIFY command to collect disk information
//
// INPUTS:
//
// ConfigData - pointer to the current configuration
// Buffer - buffer to store geometry information
//
// OUTPUTS:
//
// Buffer - geometry information
//
// RETURNS:
//
// TRUE if the IDENTIFY command succeeds
//
// IRQL:
//
// IRQL_PASSIVE_LEVEL
//
// NOTES:
//
// The majority of this routine is debug output...
//
///////////////////////////////////////////////////////////////////////////////
static BOOLEAN
IssueIdentify(PCONFIG_DATA ConfigData,
PUCHAR Buffer)
{
ULONG i;
UCHAR statusByte;
//
// Always drive 1
//
WRITE_PORT_UCHAR(ConfigData->ControllerBaseAddress + DRIVE_HEAD_REGISTER,
(DRIVE_1));
//
// If the second drive is selected but it doesn't exist the controller
// may behave randomly. Check that the status register makes sense.
//
statusByte = READ_PORT_UCHAR(ConfigData->ControllerBaseAddress + STATUS_REGISTER);
//
// Get rid of the IDX bit.
//
statusByte &= 0xfc;
if (statusByte != 0x50) {
//
// Select drive zero again so that the controller
// will return to normal behaviour.
//
WRITE_PORT_UCHAR(ConfigData->ControllerBaseAddress + DRIVE_HEAD_REGISTER,
DRIVE_1);
return FALSE;
}
//
// Send IDENTIFY command.
//
WRITE_PORT_UCHAR(ConfigData->ControllerBaseAddress + COMMAND_REGISTER,
IDENTIFY_COMMAND);
//
// Wait for up to 3 seconds for DRQ or ERROR.
//
for (i=0; i<300000; i++) {
statusByte = READ_PORT_UCHAR(ConfigData->ControllerBaseAddress + STATUS_REGISTER);
if (statusByte & ERROR_STATUS) {
return FALSE;
}
else if (statusByte & DATA_REQUEST_STATUS) {
break;
}
else {
KeStallExecutionProcessor(10L);
}
}
if (i == 10000) {
return FALSE;
}
//
// Get 256 words of information
//
READ_PORT_BUFFER_USHORT(
(PUSHORT)ConfigData->ControllerBaseAddress + DATA_REGISTER,
(PUSHORT)Buffer,
256);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -