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

📄 config.c

📁 一个硬盘驱动的例子
💻 C
📖 第 1 页 / 共 2 页
字号:
            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 + -