?? pnp.c
字號:
/*++
Copyright (C) Microsoft Corporation, 1991 - 1999
Module Name:
pnp.c
Abstract:
SCSI disk class driver
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include "disk.h"
extern PULONG InitSafeBootMode;
ULONG diskDeviceSequenceNumber = 0;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, DiskAddDevice)
#pragma alloc_text(PAGE, DiskInitFdo)
#pragma alloc_text(PAGE, DiskInitPdo)
#pragma alloc_text(PAGE, DiskStartFdo)
#pragma alloc_text(PAGE, DiskStartPdo)
#pragma alloc_text(PAGE, DiskQueryId)
#pragma alloc_text(PAGE, DiskGenerateDeviceName)
#pragma alloc_text(PAGE, DiskCreateSymbolicLinks)
#pragma alloc_text(PAGE, DiskDeleteSymbolicLinks)
#pragma alloc_text(PAGE, DiskRemoveDevice)
#endif
NTSTATUS
DiskAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
This routine gets a port drivers capabilities, obtains the
inquiry data, searches the SCSI bus for the port driver and creates
the device objects for the disks found.
Arguments:
DriverObject - Pointer to driver object created by system.
Pdo - Device object use to send requests to port driver.
Return Value:
True is returned if one disk was found and successfully created.
--*/
{
ULONG rootPartitionMountable = FALSE;
PCONFIGURATION_INFORMATION configurationInformation;
ULONG diskCount;
NTSTATUS status;
PAGED_CODE();
//
// See if we should be allowing file systems to mount on partition zero.
//
TRY {
HANDLE deviceKey;
UNICODE_STRING diskKeyName;
OBJECT_ATTRIBUTES objectAttributes = {0};
HANDLE diskKey;
RTL_QUERY_REGISTRY_TABLE queryTable[2] = { 0 };
status = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
PLUGPLAY_REGKEY_DEVICE,
KEY_READ,
&deviceKey);
if(!NT_SUCCESS(status)) {
DebugPrint((1, "DiskAddDevice: Error %#08lx opening device key "
"for pdo %#08lx\n",
status, PhysicalDeviceObject));
LEAVE;
}
RtlInitUnicodeString(&diskKeyName, L"Disk");
InitializeObjectAttributes(&objectAttributes,
&diskKeyName,
OBJ_CASE_INSENSITIVE,
deviceKey,
NULL);
status = ZwOpenKey(&diskKey, KEY_READ, &objectAttributes);
ZwClose(deviceKey);
if(!NT_SUCCESS(status)) {
DebugPrint((1, "DiskAddDevice: Error %#08lx opening disk key "
"for pdo %#08lx device key %#x\n",
status, PhysicalDeviceObject, deviceKey));
LEAVE;
}
queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
queryTable[0].Name = L"RootPartitionMountable";
queryTable[0].EntryContext = &(rootPartitionMountable);
status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
diskKey,
queryTable,
NULL,
NULL);
if(!NT_SUCCESS(status)) {
DebugPrint((1, "DiskAddDevice: Error %#08lx reading value from "
"disk key %#x for pdo %#08lx\n",
status, diskKey, PhysicalDeviceObject));
}
ZwClose(diskKey);
} FINALLY {
//
// Do nothing.
//
if(!NT_SUCCESS(status)) {
DebugPrint((1, "DiskAddDevice: Will %sallow file system to mount on "
"partition zero of disk %#08lx\n",
(rootPartitionMountable ? "" : "not "),
PhysicalDeviceObject));
}
}
//
// Create device objects for disk
//
diskCount = 0;
status = DiskCreateFdo(
DriverObject,
PhysicalDeviceObject,
&diskCount,
(BOOLEAN) !rootPartitionMountable
);
//
// Get the number of disks already initialized.
//
configurationInformation = IoGetConfigurationInformation();
if (NT_SUCCESS(status)) {
//
// Increment system disk device count.
//
configurationInformation->DiskCount++;
}
return status;
} // end DiskAddDevice()
NTSTATUS
DiskInitFdo(
IN PDEVICE_OBJECT Fdo
)
/*++
Routine Description:
This routine is called to do one-time initialization of new device objects
Arguments:
Fdo - a pointer to the functional device object for this device
Return Value:
status
--*/
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData;
ULONG srbFlags = 0;
ULONG timeOut = 0;
ULONG bytesPerSector;
PULONG dmSkew;
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
//
// Build the lookaside list for srb's for the physical disk. Should only
// need a couple. If this fails then we don't have an emergency SRB so
// fail the call to initialize.
//
ClassInitializeSrbLookasideList((PCOMMON_DEVICE_EXTENSION) fdoExtension,
PARTITION0_LIST_SIZE);
if (fdoExtension->DeviceDescriptor->RemovableMedia)
{
SET_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA);
}
//
// Initialize the srb flags.
//
//
// Because all requests share a common sense buffer, it is possible
// for the buffer to be overwritten if the port driver completes
// multiple failed requests that require a request sense before the
// class driver's completion routine can consume the data in the buffer.
// To prevent this, we allow the port driver to allocate a unique sense
// buffer each time it needs one. We are responsible for freeing this
// buffer. This also allows the adapter to be configured to support
// additional sense data beyond the minimum 18 bytes.
//
SET_FLAG(fdoExtension->SrbFlags, SRB_FLAGS_PORT_DRIVER_ALLOCSENSE);
if (fdoExtension->DeviceDescriptor->CommandQueueing &&
fdoExtension->AdapterDescriptor->CommandQueueing) {
SET_FLAG(fdoExtension->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
}
//
// Look for controllers that require special flags.
//
ClassScanForSpecial(fdoExtension, DiskBadControllers, DiskSetSpecialHacks);
srbFlags = fdoExtension->SrbFlags;
//
// Clear buffer for drive geometry.
//
RtlZeroMemory(&(fdoExtension->DiskGeometry),
sizeof(DISK_GEOMETRY));
//
// Allocate request sense buffer.
//
fdoExtension->SenseData = ExAllocatePoolWithTag(NonPagedPoolCacheAligned,
SENSE_BUFFER_SIZE,
DISK_TAG_START);
if (fdoExtension->SenseData == NULL) {
//
// The buffer can not be allocated.
//
DebugPrint((1, "DiskInitFdo: Can not allocate request sense buffer\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
return status;
}
//
// Physical device object will describe the entire
// device, starting at byte offset 0.
//
fdoExtension->CommonExtension.StartingOffset.QuadPart = (LONGLONG)(0);
//
// Set timeout value in seconds.
//
timeOut = ClassQueryTimeOutRegistryValue(Fdo);
if (timeOut) {
fdoExtension->TimeOutValue = timeOut;
} else {
fdoExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
}
//
// If this is a removable drive, build an entry in devicemap\scsi
// indicating it's physicaldriveN name, set up the appropriate
// update partitions routine and set the flags correctly.
// note: only do this after the timeout value is set, above.
//
if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
ClassUpdateInformationInRegistry( Fdo,
"PhysicalDrive",
fdoExtension->DeviceNumber,
NULL,
0);
//
// Enable media change notification for removable disks
//
ClassInitializeMediaChangeDetection(fdoExtension,
"Disk");
diskData->UpdatePartitionRoutine = DiskUpdateRemovablePartitions;
} else {
SET_FLAG(fdoExtension->DeviceFlags, DEV_SAFE_START_UNIT);
SET_FLAG(fdoExtension->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
diskData->UpdatePartitionRoutine = DiskUpdatePartitions;
}
//
// Read the drive capacity. Don't use the disk version of the routine here
// since we don't know the disk signature yet - the disk version will
// attempt to determine the BIOS reported geometry.
//
ClassReadDriveCapacity(Fdo);
//
// Set up sector size fields.
//
// Stack variables will be used to update
// the partition device extensions.
//
// The device extension field SectorShift is
// used to calculate sectors in I/O transfers.
//
// The DiskGeometry structure is used to service
// IOCTls used by the format utility.
//
bytesPerSector = fdoExtension->DiskGeometry.BytesPerSector;
//
// Make sure sector size is not zero.
//
if (bytesPerSector == 0) {
//
// Default sector size for disk is 512.
//
bytesPerSector = fdoExtension->DiskGeometry.BytesPerSector = 512;
fdoExtension->SectorShift = 9;
}
//
// Determine is DM Driver is loaded on an IDE drive that is
// under control of Atapi - this could be either a crashdump or
// an Atapi device is sharing the controller with an IDE disk.
//
HalExamineMBR(fdoExtension->CommonExtension.DeviceObject,
fdoExtension->DiskGeometry.BytesPerSector,
(ULONG)0x54,
&dmSkew);
if (dmSkew) {
//
// Update the device extension, so that the call to IoReadPartitionTable
// will get the correct information. Any I/O to this disk will have
// to be skewed by *dmSkew sectors aka DMByteSkew.
//
fdoExtension->DMSkew = *dmSkew;
fdoExtension->DMActive = TRUE;
fdoExtension->DMByteSkew = fdoExtension->DMSkew * bytesPerSector;
ExFreePool(dmSkew);
}
#if defined(_X86_) || defined(_AMD64_)
//
// Try to read the signature off the disk and determine the correct drive
// geometry based on that. This requires rereading the disk size to get
// the cylinder count updated correctly.
//
if(!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
DiskReadSignature(Fdo);
DiskReadDriveCapacity(Fdo);
if (diskData->GeometrySource == DiskGeometryUnknown)
{
//
// Neither the BIOS nor the port driver could provide us with a reliable
// geometry. Before we use the default, look to see if it was partitioned
// under Windows NT4 [or earlier] and apply the one that was used back then
//
if (DiskIsNT4Geometry(fdoExtension))
{
diskData->RealGeometry = fdoExtension->DiskGeometry;
diskData->RealGeometry.SectorsPerTrack = 0x20;
diskData->RealGeometry.TracksPerCylinder = 0x40;
fdoExtension->DiskGeometry = diskData->RealGeometry;
diskData->GeometrySource = DiskGeometryFromNT4;
}
}
}
#endif
//
// Register interfaces for this device
//
{
UNICODE_STRING interfaceName;
RtlInitUnicodeString(&interfaceName, NULL);
status = IoRegisterDeviceInterface(fdoExtension->LowerPdo,
(LPGUID) &DiskClassGuid,
NULL,
&interfaceName);
if(NT_SUCCESS(status)) {
diskData->DiskInterfaceString = interfaceName;
status = IoSetDeviceInterfaceState(&interfaceName, TRUE);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -