📄 config.c
字号:
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 1995 - 1998 OSR Open Systems Resources, Inc.
// All Rights Reserved
// Based on a previous work by Microsoft Corporation
// Copyright (c) 1991, 1992, 1993 Microsoft Corporation
//
// This sofware is supplied for instructional purposes only.
//
// OSR Open Systems Resources, Inc. (OSR) expressly disclaims any warranty
// for this software. THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION,
// THE IMPLIED WARRANTIES OF MECHANTABILITY OR FITNESS FOR A PARTICULAR
// PURPOSE. THE ENTIRE RISK ARISING FROM THE USE OF THIS SOFTWARE REMAINS
// WITH YOU. OSR's entire liability and your exclusive remedy shall not
// exceed the price paid for this material. In no event shall OSR or its
// suppliers be liable for any damages whatsoever (including, without
// limitation, damages for loss of business profit, business interruption,
// loss of business information, or any other pecuniary loss) arising out
// of the use or inability to use this software, even if OSR has been
// advised of the possibility of such damages. Because some states/
// jurisdictions do not allow the exclusion or limitation of liability for
// consequential or incidental damages, the above limitation may not apply
// to you.
//
// This driver is the example Programmed I/O device driver that
// accompanies the book Windows NT Device Driver Development, by
// Peter Viscarola and W. Anthony Mason, (c) 1998 OSR Open Systems
// Resources, Inc. and published by MacMillan Technical Publishing
// ISBN 1578700582.
//
//
// MODULE:
//
// $Workfile: config.c $
//
// ABSTRACT:
//
// This module handles the gathering of the configruation information
// for the IDE sample driver
//
// AUTHOR:
//
// Open Systems Resources, Inc.
//
// REVISION:
//
//
///////////////////////////////////////////////////////////////////////////////
#include "ntddk.h" // main NT include
#include "ntdddisk.h" // disk driver IOCTL definitions
#include "hw.h" // the access macro/definitions
#include "ide.h" // general declarations/structures
#include "config.h" // configuration declarations
//
// device defaults
//
#define DEFAULT_INTERFACE_TYPE Isa
#define DEFAULT_BUS_NUMBER 0
#define DEFAULT_IRQL 14
#define DEFAULT_BASE_ADDRESS 0x01f0;
#define DEFAULT_PORT_ADDRESS 0x03f6;
//
// forward delcarations of static routines
//
static VOID
UpdateWithBios(
PCONFIG_DATA ConfigData,
ULONG ParameterTableOffset
);
static BOOLEAN
ReconcileWithRegistry(
PDRIVER_OBJECT DriverObject,
PCONFIG_DATA ConfigData
);
static BOOLEAN
IssueIdentify(
PCONFIG_DATA ConfigData,
PUCHAR Buffer
);
//
// This is the structure of the information returned after an
// IDENTIFY command has been issued on the IDE drive
//
typedef struct _IDENTIFY_DATA {
USHORT GeneralConfiguration; // 00
USHORT NumberOfCylinders; // 01
USHORT Reserved1; // 02
USHORT NumberOfHeads; // 03
USHORT UnformattedBytesPerTrack; // 04
USHORT UnformattedBytesPerSector; // 05
USHORT SectorsPerTrack; // 06
USHORT VendorUnique1[3]; // 07
USHORT SerialNumber[10]; // 10
USHORT BufferType; // 20
USHORT BufferSectorSize; // 21
USHORT NumberOfEccBytes; // 22
USHORT FirmwareRevision[4]; // 23
USHORT ModelNumber[20]; // 27
UCHAR MaximumBlockTransfer; // 47 low byte
UCHAR VendorUnique2; // 47 high byte
USHORT DoubleWordIo; // 48
USHORT Capabilities; // 49
USHORT Reserved2; // 50
UCHAR VendorUnique3; // 51 low byte
UCHAR PioCycleTimingMode; // 51 high byte
UCHAR VendorUnique4; // 52 low byte
UCHAR DmaCycleTimingMode; // 52 high byte
USHORT TranslationFieldsValid; // 53 (low bit)
USHORT NumberOfCurrentCylinders; // 54
USHORT NumberOfCurrentHeads; // 55
USHORT CurrentSectorsPerTrack; // 56
ULONG CurrentSectorCapacity; // 57 & 58
UCHAR MultiSectorCount; // 59 low
UCHAR MultiSectorSettingValid; // 59 high (low bit)
ULONG TotalUserAddressableSectors; // 60 & 61
UCHAR SingleDmaModesSupported; // 62 low byte
UCHAR SingleDmaTransferActive; // 62 high byte
UCHAR MultiDmaModesSupported; // 63 low byte
UCHAR MultiDmaTransferActive; // 63 high byte
USHORT Reserved4[192]; // 64
}
IDENTIFY_DATA, *PIDENTIFY_DATA;
///////////////////////////////////////////////////////////////////////////////
//
// IdeGetConfigData
//
// This routine obtains the primary configuration information for the
// device, including the bus and port addresses. Note that many of
// the values are assumed, as #defin'ed by the DEFAULT_ values, while
// some are actually defined by checking into the ROM (some geometry).
//
// INPUTS:
//
// DriverObject - driver object for this driver
// RegistryPath - this driver's service node in the registry
// ConfigData - allocated, zero'ed buffer that describes the
// controller and disk
//
// OUTPUTS:
//
// ConfigData - filled up with info
//
// RETURNS:
//
// STATUS_SUCCESS if we have a disk, otherwise STATUS_NO_SUCH_DEVICE
//
// IRQL:
//
// IRQL_PASSIVE_LEVEL
//
// NOTES:
//
// The steps followed are:
//
// - call IoGetConfigurationInformation to get the primary AtDisk Address
// - translate the ControllerBase and ControlPort addresses
// - connect the interrupt
// - make sure our controller is really there
// - claim the AtDisk primary address
// - issue an IDENTIFY to get retrieve disk information from the contoller
// - map the BIOS and get more configruation information
// - check the configuration information with the registry
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
IdeGetConfigData(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN OUT PCONFIG_DATA ConfigData)
{
PCONFIGURATION_INFORMATION configurationInformation;
UCHAR driveTypes, tmp;
UCHAR buffer[512]; // for IssueIdentify
LARGE_INTEGER tmpPtr; // for BIOS delving
PUSHORT paramVector; // for BIOS delving
PHYSICAL_ADDRESS translatedAddress; // for address translation
ULONG addressSpace; // for address translation
PHYSICAL_ADDRESS phys_tmp;
NTSTATUS ntStatus;
//
// Get the current configuration manager information.
//
configurationInformation = IoGetConfigurationInformation();
//
// store the pointer to the hard disk count
//
ConfigData->HardDiskCount = &configurationInformation->DiskCount;
//
// We grab the primary AtDisk address at all costs. If we can't have it,
// we just take our disk and go home... I mean, we refuse to load.
//
if (configurationInformation->AtDiskPrimaryAddressClaimed) {
#if DBG
DbgPrint("IdeGetDiskConfig: Primary address already claimed!\n");
#endif
return(STATUS_DEVICE_CONFIGURATION_ERROR);
}
//
// Fill in some controller information.
//
ConfigData->InterfaceType = DEFAULT_INTERFACE_TYPE;
ConfigData->BusNumber = DEFAULT_BUS_NUMBER;
ConfigData->OriginalControllerIrql = DEFAULT_IRQL;
phys_tmp.QuadPart = 0;
//
// store the default ControllerBase address and range
//
phys_tmp.LowPart = DEFAULT_BASE_ADDRESS;
ConfigData->OriginalControllerBaseAddress = phys_tmp;
ConfigData->RangeOfControllerBase = 8;
//
// store the default ControlPortAddress and range
//
phys_tmp.LowPart = DEFAULT_PORT_ADDRESS;
ConfigData->OriginalControlPortAddress = phys_tmp;
ConfigData->RangeOfControlPort = 1;
//
// set the interrupt vector to the same as the irql
//
ConfigData->OriginalControllerVector = ConfigData->OriginalControllerIrql;
//
// Translate the ControllerBase address
//
//
// First, note that this is a port address
//
addressSpace = 0x01;
//
// Translate the Controller Base Address
//
if (!HalTranslateBusAddress(DEFAULT_INTERFACE_TYPE,
DEFAULT_BUS_NUMBER,
ConfigData->OriginalControllerBaseAddress,
&addressSpace,
&translatedAddress)) {
//
// We couldn't do the translation, so bail
//
#if DBG
DbgPrint("IdeGetDiskConfig: HalTranslateBusAddress failure for ControllerBase\n");
#endif
return(STATUS_NO_SUCH_DEVICE);
}
//
// The address was translated, so now check if the mapping
// of the addreess puts the address in memory space or I/O space
//
if (addressSpace == 0x0) {
//
// We're in memory space, so we have to Map this address into
// system space
//
ConfigData->ControllerBaseAddress = MmMapIoSpace(translatedAddress,
ConfigData->RangeOfControllerBase,
FALSE);
//
// if we didn't get an address, we have to quit
//
if (!ConfigData->ControllerBaseAddress) {
#if DBG
DbgPrint("IdeGetDiskConfig: MmMapIoSpace failure for ControllerBase\n");
#endif
return STATUS_NO_SUCH_DEVICE;
}
//
// note that the ControllerBase is mapped
//
ConfigData->ControllerBaseMapped = TRUE;
} else {
//
// The addresss is in I/O space, so we just need the low part
// of the translated address
//
ConfigData->ControllerBaseMapped = FALSE;
ConfigData->ControllerBaseAddress = (PVOID)translatedAddress.LowPart;
}
//
// Next, Translate the ControlPort address
//
addressSpace = 0x01;
//
// Translate the address
//
if (!HalTranslateBusAddress( DEFAULT_INTERFACE_TYPE,
DEFAULT_BUS_NUMBER,
ConfigData->OriginalControlPortAddress,
&addressSpace,
&translatedAddress)) {
//
// We couldn't do the translation, so bail out
//
#if DBG
DbgPrint("IdeGetDiskConfig: HalTranslateBusAddress failure for ControlPort\n");
#endif
//
// If the controller's base address was mapped, we need to unmap it
// before we leave.
//
if(ConfigData->ControllerBaseMapped) {
MmUnmapIoSpace(ConfigData->ControllerBaseAddress,
ConfigData->RangeOfControllerBase);
}
//
// return error status
//
return(STATUS_NO_SUCH_DEVICE);
}
//
// The address was translated, so now check if the mapping
// of the addreess puts the address in memory space or I/O space
//
if (addressSpace == 0x0) {
//
// We in memory space, so we have to Map this address into
// system space
//
ConfigData->ControlPortAddress = MmMapIoSpace(translatedAddress,
ConfigData->RangeOfControlPort,
FALSE);
//
// if we didn't get an address, we have to quit
//
if (!ConfigData->ControlPortAddress) {
#if DBG
DbgPrint("IdeGetDiskConfig: MmMapIoSpace failure for ControlPort\n");
#endif
//
// Unmap the controllerBase
//
if (ConfigData->ControllerBaseMapped) {
MmUnmapIoSpace(ConfigData->ControllerBaseAddress,
ConfigData->RangeOfControllerBase);
}
//
// return failure status
//
return(STATUS_NO_SUCH_DEVICE);
}
//
// note that the ControlPort is mapped
//
ConfigData->ControlPortMapped = TRUE;
} else {
//
// The addresss is in I/O space, so we just need the
// translated address
//
ConfigData->ControlPortMapped = FALSE;
ConfigData->ControlPortAddress = (PVOID)translatedAddress.LowPart;
}
//
// get the interrupt vector
//
ConfigData->ControllerVector = HalGetInterruptVector(ConfigData->InterfaceType,
ConfigData->BusNumber,
ConfigData->OriginalControllerIrql,
ConfigData->OriginalControllerVector,
&ConfigData->ControllerIrql,
&ConfigData->ProcessorNumber);
//
// Check if the controller exists by writing 0xaa to the COUNT register and
// attempting to read it back. Crude, but effective.
//
WRITE_PORT_UCHAR(ConfigData->ControllerBaseAddress + SECTOR_COUNT_REGISTER, 0xaa);
tmp = READ_PORT_UCHAR(ConfigData->ControllerBaseAddress + SECTOR_COUNT_REGISTER);
//
// Did we get 0xaa back from the count register?
//
if (tmp != 0xaa) {
//
// No, we didn't. Hmmmmm... I don't know what we've got, but it's
// either an IDE controller that's not there or something else.
//
// We're outa here in either case.
//
#if DBG
DbgPrint("IdeGetDiskConfig: Unable to verify controller existance\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 status
//
return(STATUS_NO_SUCH_DEVICE);
}
//
// The controller exists, so claim the AtDisk primary IO
// address range.
//
configurationInformation->AtDiskPrimaryAddressClaimed = TRUE;
ConfigData->OkToUseThisController = TRUE;
//
// Check CMOS for drive types for the disk
//
WRITE_PORT_UCHAR(CFGMEM_QUERY_PORT, CFGMEM_FIRST_CONTROLLER_DRIVE_TYPES);
KeStallExecutionProcessor(1L);
driveTypes = READ_PORT_UCHAR(CFGMEM_DATA_PORT);
ConfigData->Disk.DriveType = (UCHAR)
(driveTypes & CFGMEM_DRIVES_FIRST_DRIVE_MASK);
//
// If there is no drive, then we have to quit.
//
if (!ConfigData->Disk.DriveType) {
#if DBG
DbgPrint("IdeGetDiskConfig: Unable to read drive configuration\n");
#endif
//
// Unmap the ControllerBase
//
if (ConfigData->ControllerBaseMapped) {
MmUnmapIoSpace(ConfigData->ControllerBaseAddress,
ConfigData->RangeOfControllerBase);
}
//
// Unmap the ControlPort
//
if (ConfigData->ControlPortMapped) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -