+++ /dev/null
-/*++
-
-Copyright (C) Microsoft Corporation, 1991 - 1999
-
-Module Name:
-
- geometry.c
-
-Abstract:
-
- SCSI disk class driver - this module contains all the code for generating
- disk geometries.
-
-Environment:
-
- kernel mode only
-
-Notes:
-
-Revision History:
-
---*/
-
-#include "disk.h"
-
-#if defined (_X86_)
-
-DISK_GEOMETRY_SOURCE
-NTAPI
-DiskUpdateGeometry(
- IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension
- );
-
-NTSTATUS
-NTAPI
-DiskUpdateRemovableGeometry (
- IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
- );
-
-VOID
-NTAPI
-DiskScanBusDetectInfo(
- IN PDRIVER_OBJECT DriverObject,
- IN HANDLE BusKey
- );
-
-NTSTATUS
-NTAPI
-DiskSaveBusDetectInfo(
- IN PDRIVER_OBJECT DriverObject,
- IN HANDLE TargetKey,
- IN ULONG DiskNumber
- );
-
-NTSTATUS
-NTAPI
-DiskSaveGeometryDetectInfo(
- IN PDRIVER_OBJECT DriverObject,
- IN HANDLE HardwareKey
- );
-
-NTSTATUS
-NTAPI
-DiskGetPortGeometry(
- IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
- OUT PDISK_GEOMETRY Geometry
- );
-
-typedef struct _DISK_DETECT_INFO {
- BOOLEAN Initialized;
- ULONG Style;
- ULONG Signature;
- ULONG MbrCheckSum;
- PDEVICE_OBJECT Device;
- CM_INT13_DRIVE_PARAMETER DriveParameters;
-} DISK_DETECT_INFO, *PDISK_DETECT_INFO;
-
-//
-// Information about the disk geometries collected and saved into the registry
-// by NTDETECT.COM or the system firmware.
-//
-
-PDISK_DETECT_INFO DetectInfoList = NULL;
-ULONG DetectInfoCount = 0;
-ULONG DetectInfoUsedCount = 0;
-
-#ifdef ALLOC_PRAGMA
-#pragma alloc_text(INIT, DiskSaveDetectInfo)
-#pragma alloc_text(INIT, DiskScanBusDetectInfo)
-#pragma alloc_text(INIT, DiskSaveBusDetectInfo)
-#pragma alloc_text(INIT, DiskSaveGeometryDetectInfo)
-
-#pragma alloc_text(PAGE, DiskUpdateGeometry)
-#pragma alloc_text(PAGE, DiskUpdateRemovableGeometry)
-#pragma alloc_text(PAGE, DiskGetPortGeometry)
-#pragma alloc_text(PAGE, DiskGetDetectInfo)
-#pragma alloc_text(PAGE, DiskReadSignature)
-#endif
-
-
-NTSTATUS
-NTAPI
-DiskSaveDetectInfo(
- PDRIVER_OBJECT DriverObject
- )
-/*++
-
-Routine Description:
-
- This routine saves away the firmware information about the disks which has
- been saved in the registry. It generates a list (DetectInfoList) which
- contains the disk geometries, signatures & checksums of all drives which
- were examined by NtDetect. This list is later used to assign geometries
- to disks as they are initialized.
-
-Arguments:
-
- DriverObject - the driver being initialized. This is used to get to the
- hardware database.
-
-Return Value:
-
- status.
-
---*/
-
-{
- OBJECT_ATTRIBUTES objectAttributes;
- HANDLE hardwareKey;
-
- UNICODE_STRING unicodeString;
- HANDLE busKey;
-
- NTSTATUS status;
-
- PAGED_CODE();
-
- InitializeObjectAttributes(
- &objectAttributes,
- DriverObject->HardwareDatabase,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- //
- // Create the hardware base key.
- //
-
- status = ZwOpenKey(&hardwareKey, KEY_READ, &objectAttributes);
-
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskSaveDetectInfo: Cannot open hardware data. "
- "Name: %wZ\n",
- DriverObject->HardwareDatabase));
- return status;
- }
-
- status = DiskSaveGeometryDetectInfo(DriverObject, hardwareKey);
-
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskSaveDetectInfo: Can't query configuration data "
- "(%#08lx)\n",
- status));
- ZwClose(hardwareKey);
- return status;
- }
-
- //
- // Open EISA bus key.
- //
-
- RtlInitUnicodeString(&unicodeString, L"EisaAdapter");
- InitializeObjectAttributes(&objectAttributes,
- &unicodeString,
- OBJ_CASE_INSENSITIVE,
- hardwareKey,
- NULL);
-
- status = ZwOpenKey(&busKey,
- KEY_READ,
- &objectAttributes);
-
- if(NT_SUCCESS(status)) {
- DebugPrint((1, "DiskSaveDetectInfo: Opened EisaAdapter key\n"));
- DiskScanBusDetectInfo(DriverObject, busKey);
- ZwClose(busKey);
- }
-
- //
- // Open MultiFunction bus key.
- //
-
- RtlInitUnicodeString(&unicodeString, L"MultifunctionAdapter");
- InitializeObjectAttributes(&objectAttributes,
- &unicodeString,
- OBJ_CASE_INSENSITIVE,
- hardwareKey,
- NULL);
-
- status = ZwOpenKey(&busKey,
- KEY_READ,
- &objectAttributes);
-
- if(NT_SUCCESS(status)) {
- DebugPrint((1, "DiskSaveDetectInfo: Opened MultifunctionAdapter key\n"));
- DiskScanBusDetectInfo(DriverObject, busKey);
- ZwClose(busKey);
- }
-
- ZwClose(hardwareKey);
-
- return STATUS_SUCCESS;
-}
-
-VOID
-NTAPI
-DiskCleanupDetectInfo(
- IN PDRIVER_OBJECT DriverObject
- )
-/*++
-
-Routine Description:
-
- This routine will cleanup the data structure built by DiskSaveDetectInfo.
-
-Arguments:
-
- DriverObject - a pointer to the kernel object for this driver.
-
-Return Value:
-
- none
-
---*/
-
-{
- if(DetectInfoList != NULL) {
- ExFreePool(DetectInfoList);
- DetectInfoList = NULL;
- }
- return;
-}
-
-NTSTATUS
-NTAPI
-DiskSaveGeometryDetectInfo(
- IN PDRIVER_OBJECT DriverObject,
- IN HANDLE HardwareKey
- )
-{
- UNICODE_STRING unicodeString;
- PKEY_VALUE_FULL_INFORMATION keyData;
- ULONG length;
-
- PCM_FULL_RESOURCE_DESCRIPTOR fullDescriptor;
- PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor;
-
- PCM_INT13_DRIVE_PARAMETER driveParameters;
- ULONG numberOfDrives;
-
- ULONG i;
-
- NTSTATUS status;
-
- PAGED_CODE();
-
- //
- // Get disk BIOS geometry information.
- //
-
- RtlInitUnicodeString(&unicodeString, L"Configuration Data");
-
- keyData = ExAllocatePoolWithTag(PagedPool,
- VALUE_BUFFER_SIZE,
- DISK_TAG_UPDATE_GEOM);
-
- if(keyData == NULL) {
- DebugPrint((1, "DiskSaveGeometryDetectInfo: Can't allocate config "
- "data buffer\n"));
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- status = ZwQueryValueKey(HardwareKey,
- &unicodeString,
- KeyValueFullInformation,
- keyData,
- VALUE_BUFFER_SIZE,
- &length);
-
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskSaveGeometryDetectInfo: Can't query configuration "
- "data (%#08lx)\n",
- status));
- ExFreePool(keyData);
- return status;
- }
-
- //
- // Extract the resource list out of the key data.
- //
-
- fullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
- (((PUCHAR) keyData) + keyData->DataOffset);
- partialDescriptor =
- fullDescriptor->PartialResourceList.PartialDescriptors;
- length = partialDescriptor->u.DeviceSpecificData.DataSize;
-
- if((keyData->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) ||
- (fullDescriptor->PartialResourceList.Count == 0) ||
- (partialDescriptor->Type != CmResourceTypeDeviceSpecific) ||
- (length < sizeof(ULONG))) {
-
- DebugPrint((1, "DiskSaveGeometryDetectInfo: BIOS header data too small "
- "or invalid\n"));
- ExFreePool(keyData);
- return STATUS_INVALID_PARAMETER;
- }
-
- //
- // Point to the BIOS data. THe BIOS data is located after the first
- // partial Resource list which should be device specific data.
- //
-
- {
- PUCHAR buffer = (PUCHAR) keyData;
- buffer += keyData->DataOffset;
- buffer += sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
- driveParameters = (PCM_INT13_DRIVE_PARAMETER) buffer;
- }
-
- numberOfDrives = length / sizeof(CM_INT13_DRIVE_PARAMETER);
-
- //
- // Allocate our detect info list now that we know how many entries there
- // are going to be. No other routine allocates detect info and this is
- // done out of DriverEntry so we don't need to synchronize it's creation.
- //
-
- length = sizeof(DISK_DETECT_INFO) * numberOfDrives;
- DetectInfoList = ExAllocatePoolWithTag(PagedPool,
- length,
- DISK_TAG_UPDATE_GEOM);
-
- if(DetectInfoList == NULL) {
- DebugPrint((1, "DiskSaveGeometryDetectInfo: Couldn't allocate %x bytes "
- "for DetectInfoList\n",
- length));
-
- ExFreePool(keyData);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- DetectInfoCount = numberOfDrives;
-
- RtlZeroMemory(DetectInfoList, length);
-
- //
- // Copy the information out of the key data and into the list we've
- // allocated.
- //
-
- for(i = 0; i < numberOfDrives; i++) {
- DetectInfoList[i].DriveParameters = driveParameters[i];
- }
-
- ExFreePool(keyData);
- return STATUS_SUCCESS;
-}
-
-VOID
-NTAPI
-DiskScanBusDetectInfo(
- IN PDRIVER_OBJECT DriverObject,
- IN HANDLE BusKey
- )
-/*++
-
-Routine Description:
-
- The routine queries the registry to determine which disks are visible to
- the BIOS. If a disk is visible to the BIOS then the geometry information
- is updated with the disk's signature and MBR checksum.
-
-Arguments:
-
- DriverObject - the object for this driver.
- BusKey - handle to the bus key to be enumerated.
-
-Return Value:
-
- status
-
---*/
-{
- ULONG busNumber;
-
- NTSTATUS status;
-
- for(busNumber = 0; ; busNumber++) {
-
- WCHAR buffer[32];
- UNICODE_STRING unicodeString;
-
- OBJECT_ATTRIBUTES objectAttributes;
-
- HANDLE spareKey;
- HANDLE adapterKey;
-
- ULONG adapterNumber;
-
- DebugPrint((1, "DiskScanBusDetectInfo: Scanning bus %d\n", busNumber));
-
- //
- // Open controller name key.
- //
-
- swprintf(buffer, L"%d", busNumber);
- RtlInitUnicodeString(&unicodeString, buffer);
-
- InitializeObjectAttributes(&objectAttributes,
- &unicodeString,
- OBJ_CASE_INSENSITIVE,
- BusKey,
- NULL);
-
- status = ZwOpenKey(&spareKey, KEY_READ, &objectAttributes);
-
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening bus "
- "key %#x\n",
- status, busNumber));
- break;
- }
-
- //
- // Open up a controller ordinal key.
- //
-
- RtlInitUnicodeString(&unicodeString, L"DiskController");
- InitializeObjectAttributes(&objectAttributes,
- &unicodeString,
- OBJ_CASE_INSENSITIVE,
- spareKey,
- NULL);
-
- status = ZwOpenKey(&adapterKey, KEY_READ, &objectAttributes);
- ZwClose(spareKey);
-
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening "
- "DiskController key\n",
- status));
- continue;
- }
-
- for(adapterNumber = 0; ; adapterNumber++) {
-
- HANDLE diskKey;
- ULONG diskNumber;
-
- //
- // Open disk key.
- //
-
- DebugPrint((1, "DiskScanBusDetectInfo: Scanning disk key "
- "%d\\DiskController\\%d\\DiskPeripheral\n",
- busNumber, adapterNumber));
-
- swprintf(buffer, L"%d\\DiskPeripheral", adapterNumber);
- RtlInitUnicodeString(&unicodeString, buffer);
-
- InitializeObjectAttributes(&objectAttributes,
- &unicodeString,
- OBJ_CASE_INSENSITIVE,
- adapterKey,
- NULL);
-
- status = ZwOpenKey(&diskKey, KEY_READ, &objectAttributes);
-
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening "
- "disk key\n",
- status));
- break;
- }
-
- for(diskNumber = 0; ; diskNumber++) {
-
- HANDLE targetKey;
-
- DebugPrint((1, "DiskScanBusDetectInfo: Scanning target key "
- "%d\\DiskController\\%d\\DiskPeripheral\\%d\n",
- busNumber, adapterNumber, diskNumber));
-
- swprintf(buffer, L"%d", diskNumber);
- RtlInitUnicodeString(&unicodeString, buffer);
-
- InitializeObjectAttributes(&objectAttributes,
- &unicodeString,
- OBJ_CASE_INSENSITIVE,
- diskKey,
- NULL);
-
- status = ZwOpenKey(&targetKey, KEY_READ, &objectAttributes);
-
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx "
- "opening target key\n",
- status));
- break;
- }
-
- status = DiskSaveBusDetectInfo(DriverObject,
- targetKey,
- diskNumber);
-
- ZwClose(targetKey);
- }
-
- ZwClose(diskKey);
- }
- ZwClose(adapterKey);
- }
- return;
-}
-
-NTSTATUS
-NTAPI
-DiskSaveBusDetectInfo(
- IN PDRIVER_OBJECT DriverObject,
- IN HANDLE TargetKey,
- IN ULONG DiskNumber
- )
-/*++
-
-Routine Description:
-
- This routine will transfer the firmware/ntdetect reported information
- in the specified target key into the appropriate entry in the
- DetectInfoList.
-
-Arguments:
-
- DriverObject - the object for this driver.
-
- TargetKey - the key for the disk being saved.
-
- DiskNumber - the ordinal of the entry in the DiskPeripheral tree for this
- entry
-
-Return Value:
-
- status
-
---*/
-{
- PDISK_DETECT_INFO diskInfo;
-
- UNICODE_STRING unicodeString;
-
- PKEY_VALUE_FULL_INFORMATION keyData;
- ULONG length;
-
- NTSTATUS status;
-
- PAGED_CODE();
-
- diskInfo = &(DetectInfoList[DiskNumber]);
-
- if(diskInfo->Initialized) {
-
- ASSERT(FALSE);
- DebugPrint((1, "DiskSaveBusDetectInfo: disk entry %#x already has a "
- "signature of %#08lx and mbr checksum of %#08lx\n",
- DiskNumber,
- diskInfo->Signature,
- diskInfo->MbrCheckSum));
- return STATUS_UNSUCCESSFUL;
- }
-
- RtlInitUnicodeString(&unicodeString, L"Identifier");
-
- keyData = ExAllocatePoolWithTag(PagedPool,
- VALUE_BUFFER_SIZE,
- DISK_TAG_UPDATE_GEOM);
-
- if(keyData == NULL) {
- DebugPrint((1, "DiskSaveBusDetectInfo: Couldn't allocate space for "
- "registry data\n"));
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- //
- // Get disk peripheral identifier.
- //
-
- status = ZwQueryValueKey(TargetKey,
- &unicodeString,
- KeyValueFullInformation,
- keyData,
- VALUE_BUFFER_SIZE,
- &length);
-
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskSaveBusDetectInfo: Error %#08lx getting "
- "Identifier\n",
- status));
- ExFreePool(keyData);
- return status;
-
- } else if (keyData->DataLength < 9*sizeof(WCHAR)) {
-
- //
- // the data is too short to use (we subtract 9 chars in normal path)
- //
- DebugPrint((1, "DiskSaveBusDetectInfo: Saved data was invalid, "
- "not enough data in registry!\n"));
- ExFreePool(keyData);
- return STATUS_UNSUCCESSFUL;
-
- } else {
-
- UNICODE_STRING identifier;
- ULONG value;
-
- //
- // Complete unicode string.
- //
-
- identifier.Buffer = (PWSTR) ((PUCHAR)keyData + keyData->DataOffset);
- identifier.Length = (USHORT) keyData->DataLength;
- identifier.MaximumLength = (USHORT) keyData->DataLength;
-
- //
- // Get the first value out of the identifier - this will be the MBR
- // checksum.
- //
-
- status = RtlUnicodeStringToInteger(&identifier, 16, &value);
-
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskSaveBusDetectInfo: Error %#08lx converting "
- "identifier %wZ into MBR xsum\n",
- status,
- &identifier));
- ExFreePool(keyData);
- return status;
- }
-
- diskInfo->MbrCheckSum = value;
-
- //
- // Shift the string over to get the disk signature
- //
-
- identifier.Buffer += 9;
- identifier.Length -= 9 * sizeof(WCHAR);
- identifier.MaximumLength -= 9 * sizeof(WCHAR);
-
- status = RtlUnicodeStringToInteger(&identifier, 16, &value);
-
- if(!NT_SUCCESS(status)) {
- DebugPrint((1, "DiskSaveBusDetectInfo: Error %#08lx converting "
- "identifier %wZ into disk signature\n",
- status,
- &identifier));
- ExFreePool(keyData);
- value = 0;
- }
-
- diskInfo->Signature = value;
- }
-
- //
- // Here is where we would save away the extended int13 data.
- //
-
- //
- // Mark this entry as initialized so we can make sure not to do it again.
- //
-
- diskInfo->Initialized = TRUE;
-
-
- return STATUS_SUCCESS;
-}
-
-DISK_GEOMETRY_SOURCE
-NTAPI
-DiskUpdateGeometry(
- IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
- )
-/*++
-
-Routine Description:
-
- This routine checks the DetectInfoList saved away during disk driver init
- to see if any geometry information was reported for this drive. If the
- geometry data exists (determined by matching non-zero signatures or
- non-zero MBR checksums) then it will be saved in the RealGeometry member
- of the disk data block.
-
- ClassReadDriveCapacity MUST be called after calling this routine to update
- the cylinder count based on the size of the disk and the presence of any
- disk management software.
-
-Arguments:
-
- DeviceExtension - Supplies a pointer to the device information for disk.
-
-Return Value:
-
- Indicates whether the "RealGeometry" in the data block is now valid.
-
---*/
-
-{
- PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData;
-
- ULONG i;
- PDISK_DETECT_INFO diskInfo;
-
- BOOLEAN found = FALSE;
-
- NTSTATUS status;
-
- PAGED_CODE();
-
-
- ASSERT(FdoExtension->CommonExtension.IsFdo);
- ASSERT((FdoExtension->DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0);
-
- //
- // If we've already set a non-default geometry for this drive then there's
- // no need to try and update again.
- //
-
- if(diskData->GeometrySource != DiskGeometryUnknown) {
- return diskData->GeometrySource;
- }
-
- //
- // Scan through the saved detect info to see if we can find a match
- // for this device.
- //
-
- for(i = 0; i < DetectInfoCount; i++) {
-
- ASSERT(DetectInfoList != NULL);
-
- diskInfo = &(DetectInfoList[i]);
-
- if((diskData->Mbr.Signature != 0) &&
- (diskData->Mbr.Signature == diskInfo->Signature)) {
- DebugPrint((1, "DiskUpdateGeometry: found match for signature "
- "%#08lx\n",
- diskData->Mbr.Signature));
- found = TRUE;
- break;
- } else if((diskData->Mbr.Signature == 0) &&
- (diskData->Mbr.MbrCheckSum != 0) &&
- (diskData->Mbr.MbrCheckSum == diskInfo->MbrCheckSum)) {
- DebugPrint((1, "DiskUpdateGeometry: found match for xsum %#08lx\n",
- diskData->Mbr.MbrCheckSum));
- found = TRUE;
- break;
- }
- }
-
- if(found) {
-
- ULONG cylinders;
- ULONG sectorsPerTrack;
- ULONG tracksPerCylinder;
-
- //ULONG sectors;
- ULONG length;
-
- //
- // Point to the array of drive parameters.
- //
-
- cylinders = diskInfo->DriveParameters.MaxCylinders + 1;
- sectorsPerTrack = diskInfo->DriveParameters.SectorsPerTrack;
- tracksPerCylinder = diskInfo->DriveParameters.MaxHeads + 1;
-
- //
- // Since the BIOS may not report the full drive, recalculate the drive
- // size based on the volume size and the BIOS values for tracks per
- // cylinder and sectors per track..
- //
-
- length = tracksPerCylinder * sectorsPerTrack;
-
- if (length == 0) {
-
- //
- // The BIOS information is bogus.
- //
-
- DebugPrint((1, "DiskUpdateGeometry: H (%d) or S(%d) is zero\n",
- tracksPerCylinder, sectorsPerTrack));
- return FALSE;
- }
-
- //
- // since we are copying the structure RealGeometry here, we should
- // really initialize all the fields, especially since a zero'd
- // BytesPerSector field would cause a trap in xHalReadPartitionTable()
- //
-
- diskData->RealGeometry = FdoExtension->DiskGeometry;
-
- //
- // Save the geometry information away in the disk data block and
- // set the bit indicating that we found a valid one.
- //
-
- diskData->RealGeometry.SectorsPerTrack = sectorsPerTrack;
- diskData->RealGeometry.TracksPerCylinder = tracksPerCylinder;
- diskData->RealGeometry.Cylinders.QuadPart = (LONGLONG)cylinders;
-
- DebugPrint((1, "DiskUpdateGeometry: BIOS spt %#x, #heads %#x, "
- "#cylinders %#x\n",
- sectorsPerTrack, tracksPerCylinder, cylinders));
-
- diskData->GeometrySource = DiskGeometryFromBios;
- diskInfo->Device = FdoExtension->DeviceObject;
-
- } else {
-
- DebugPrint((1, "DiskUpdateGeometry: no match found for signature %#08lx\n", diskData->Mbr.Signature));
- }
-
- if(diskData->GeometrySource == DiskGeometryUnknown) {
-
- //
- // We couldn't find a geometry from the BIOS. Check with the port
- // driver and see if it can provide one.
- //
-
- status = DiskGetPortGeometry(FdoExtension, &(diskData->RealGeometry));
-
- if(NT_SUCCESS(status)) {
-
- //
- // Check the geometry to make sure it's valid.
- //
-
- if((diskData->RealGeometry.TracksPerCylinder *
- diskData->RealGeometry.SectorsPerTrack) != 0) {
-
- diskData->GeometrySource = DiskGeometryFromPort;
- DebugPrint((1, "DiskUpdateGeometry: using Port geometry for disk %#p\n", FdoExtension));
-
- if (diskData->RealGeometry.BytesPerSector == 0) {
-
- DebugPrint((0, "DiskDriverReinit: Port driver failed to "
- "set BytesPerSector in the RealGeometry\n"));
- diskData->RealGeometry.BytesPerSector =
- FdoExtension->DiskGeometry.BytesPerSector;
- if (diskData->RealGeometry.BytesPerSector == 0) {
- ASSERT(!"BytesPerSector is still zero!");
- }
-
- }
- }
- }
- }
-
- //
- // If we came up with a "real" geometry for this drive then set it in the
- // device extension.
- //
-
- if(diskData->GeometrySource != DiskGeometryUnknown) {
- FdoExtension->DiskGeometry = diskData->RealGeometry;
-
- //
- // Increment the count of used geometry entries.
- //
-
- InterlockedIncrement(&DetectInfoUsedCount);
- }
-
- return diskData->GeometrySource;
-}
-
-NTSTATUS
-NTAPI
-DiskUpdateRemovableGeometry (
- IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
- )
-
-/*++
-
-Routine Description:
-
- This routine updates the geometry of the disk. It will query the port
- driver to see if it can provide any geometry info. If not it will use
- the current head & sector count.
-
- Based on these values & the capacity of the drive as reported by
- ClassReadDriveCapacity it will determine a new cylinder count for the
- device.
-
-Arguments:
-
- Fdo - Supplies the functional device object whos size needs to be updated.
-
-Return Value:
-
- Returns the status of the operation.
-
---*/
-{
- PCOMMON_DEVICE_EXTENSION commonExtension = &(FdoExtension->CommonExtension);
- PDISK_DATA diskData = commonExtension->DriverData;
- PDISK_GEOMETRY geometry = &(diskData->RealGeometry);
-
- NTSTATUS status;
-
- PAGED_CODE();
-
- ASSERT_FDO(commonExtension->DeviceObject);
- if (FdoExtension->DeviceDescriptor) {
- ASSERT(FdoExtension->DeviceDescriptor->RemovableMedia);
- }
- ASSERT(TEST_FLAG(FdoExtension->DeviceObject->Characteristics,
- FILE_REMOVABLE_MEDIA));
-
- //
- // Attempt to determine the disk geometry. First we'll check with the
- // port driver to see what it suggests for a value.
- //
-
- status = DiskGetPortGeometry(FdoExtension, geometry);
-
- if(NT_SUCCESS(status) &&
- ((geometry->TracksPerCylinder * geometry->SectorsPerTrack) != 0)) {
-
- FdoExtension->DiskGeometry = (*geometry);
- }
-
- return status;
-}
-
-NTSTATUS
-NTAPI
-DiskGetPortGeometry(
- IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
- OUT PDISK_GEOMETRY Geometry
- )
-/*++
-
-Routine Description:
-
- This routine will query the port driver for disk geometry. Some port
- drivers (in particular IDEPORT) may be able to provide geometry for the
- device.
-
-Arguments:
-
- FdoExtension - the device object for the disk.
-
- Geometry - a structure to save the geometry information into (if any is
- available)
-
-Return Value:
-
- STATUS_SUCCESS if geometry information can be provided or
- error status indicating why it can't.
-
---*/
-{
- PCOMMON_DEVICE_EXTENSION commonExtension = &(FdoExtension->CommonExtension);
- PIRP irp;
- PIO_STACK_LOCATION irpStack;
- KEVENT event;
-
- NTSTATUS status;
-
- PAGED_CODE();
-
- //
- // Build an irp to send IOCTL_DISK_GET_DRIVE_GEOMETRY to the lower driver.
- //
-
- irp = IoAllocateIrp(commonExtension->LowerDeviceObject->StackSize, FALSE);
-
- if(irp == NULL) {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
- irpStack = IoGetNextIrpStackLocation(irp);
-
- irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
-
- irpStack->Parameters.DeviceIoControl.IoControlCode =
- IOCTL_DISK_GET_DRIVE_GEOMETRY;
- irpStack->Parameters.DeviceIoControl.OutputBufferLength =
- sizeof(DISK_GEOMETRY);
-
- irp->AssociatedIrp.SystemBuffer = Geometry;
-
- KeInitializeEvent(&event, SynchronizationEvent, FALSE);
-
- IoSetCompletionRoutine(irp,
- (PIO_COMPLETION_ROUTINE)ClassSignalCompletion,
- &event,
- TRUE,
- TRUE,
- TRUE);
-
- status = IoCallDriver(commonExtension->LowerDeviceObject, irp);
- KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
-
- ASSERT((status == STATUS_PENDING) || (status == irp->IoStatus.Status));
- status = irp->IoStatus.Status;
-
- IoFreeIrp(irp);
-
- return status;
-}
-
-NTSTATUS
-NTAPI
-DiskReadDriveCapacity(
- IN PDEVICE_OBJECT Fdo
- )
-/*++
-
-Routine Description:
-
- This routine is used by disk.sys as a wrapper for the classpnp API
- ClassReadDriveCapacity. It will perform some additional operations to
- attempt to determine drive geometry before it calls the classpnp version
- of the routine.
-
- For fixed disks this involves calling DiskUpdateGeometry which will check
- various sources (the BIOS, the port driver) for geometry information.
-
-Arguments:
-
- Fdo - a pointer to the device object to be checked.
-
-Return Value:
-
- status of ClassReadDriveCapacity.
-
---*/
-
-{
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
- //PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData;
- //DISK_GEOMETRY_SOURCE diskGeometrySource = DiskGeometryUnknown;
- NTSTATUS status;
-
- ASSERT_FDO(Fdo);
-
- if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
- DiskUpdateRemovableGeometry(fdoExtension);
- } else {
- /* diskGeometrySource =*/ DiskUpdateGeometry(fdoExtension);
- }
-
- status = ClassReadDriveCapacity(Fdo);
-
- return status;
-}
-
-VOID
-NTAPI
-DiskDriverReinitialization(
- IN PDRIVER_OBJECT DriverObject,
- IN PVOID Nothing,
- IN ULONG Count
- )
-/*++
-
-Routine Description:
-
- This routine will scan through the current list of disks and attempt to
- match them to any remaining geometry information. This will only be done
- on the first call to the routine.
-
- Note: This routine assumes that the system will not be adding or removing
- devices during this phase of the init process. This is very likely
- a bad assumption but it greatly simplifies the code.
-
-Arguments:
-
- DriverObject - a pointer to the object for the disk driver.
-
- Nothing - unused
-
- Count - an indication of how many times this routine has been called.
-
-Return Value:
-
- none
-
---*/
-
-{
- PDEVICE_OBJECT deviceObject;
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
- PDISK_DATA diskData;
-
- ULONG unmatchedDiskCount;
- PDEVICE_OBJECT unmatchedDisk = NULL;
-
- ULONG i;
- PDISK_DETECT_INFO diskInfo = NULL;
-
- if(Count != 1) {
- DebugPrint((1, "DiskDriverReinitialization: ignoring call %d\n",
- Count));
- return;
- }
-
- //
- // Check to see how many entries in the detect info list have been matched.
- // If there's only one remaining we'll see if we can find a disk to go with
- // it.
- //
-
- if(DetectInfoCount == 0) {
- DebugPrint((1, "DiskDriverReinitialization: no detect info saved\n"));
- return;
- }
-
- if((DetectInfoCount - DetectInfoUsedCount) != 1) {
- DebugPrint((1, "DiskDriverReinitialization: %d of %d geometry entries "
- "used - will not attempt match\n"));
- return;
- }
-
- //
- // Scan through the list of disks and see if any of them are missing
- // geometry information. If there is only one such disk we'll try to
- // match it to the unmatched geometry.
- //
-
-
- //
- // ISSUE-2000/5/24-henrygab - figure out if there's a way to keep
- // removals from happening while doing this.
- //
-
- for(deviceObject = DriverObject->DeviceObject, unmatchedDiskCount = 0;
- deviceObject != NULL;
- deviceObject = deviceObject->NextDevice) {
-
- //
- // Make sure this is a disk and not a partition.
- //
-
- fdoExtension = deviceObject->DeviceExtension;
- if(fdoExtension->CommonExtension.IsFdo == FALSE) {
- DebugPrint((1, "DiskDriverReinit: DO %#p is not an FDO\n",
- deviceObject));
- continue;
- }
-
- //
- // If the geometry for this one is already known then skip it.
- //
-
- diskData = fdoExtension->CommonExtension.DriverData;
- if(diskData->GeometrySource != DiskGeometryUnknown) {
- DebugPrint((1, "DiskDriverReinit: FDO %#p has a geometry\n",
- deviceObject));
- continue;
- }
-
- DebugPrint((1, "DiskDriverReinit: FDO %#p has no geometry\n",
- deviceObject));
-
- //
- // Mark this one as using the default. It's past the time when disk
- // might blunder across the geometry info. If we set the geometry
- // from the bios we'll reset this field down below.
- //
-
- diskData->GeometrySource = DiskGeometryFromDefault;
-
- //
- // As long as we've only got one unmatched disk we're fine.
- //
-
- unmatchedDiskCount++;
- if(unmatchedDiskCount > 1) {
- ASSERT(unmatchedDisk != NULL);
- DebugPrint((1, "DiskDriverReinit: FDO %#p also has no geometry\n",
- unmatchedDisk));
- unmatchedDisk = NULL;
- break;
- }
-
- unmatchedDisk = deviceObject;
- }
-
- //
- // If there's more or less than one ungeometried disk then we can't do
- // anything about the geometry.
- //
-
- if(unmatchedDiskCount != 1) {
- DebugPrint((1, "DiskDriverReinit: Unable to match geometry\n"));
- return;
-
- }
-
- fdoExtension = unmatchedDisk->DeviceExtension;
- diskData = fdoExtension->CommonExtension.DriverData;
-
- DebugPrint((1, "DiskDriverReinit: Found possible match\n"));
-
- //
- // Find the geometry which wasn't assigned.
- //
-
- for(i = 0; i < DetectInfoCount; i++) {
- if(DetectInfoList[i].Device == NULL) {
- diskInfo = &(DetectInfoList[i]);
- break;
- }
- }
-
- ASSERT(diskInfo != NULL);
-
- {
- //
- // Save the geometry information away in the disk data block and
- // set the bit indicating that we found a valid one.
- //
-
- ULONG cylinders;
- ULONG sectorsPerTrack;
- ULONG tracksPerCylinder;
-
- //ULONG sectors;
- ULONG length;
-
- //
- // Point to the array of drive parameters.
- //
-
- cylinders = diskInfo->DriveParameters.MaxCylinders + 1;
- sectorsPerTrack = diskInfo->DriveParameters.SectorsPerTrack;
- tracksPerCylinder = diskInfo->DriveParameters.MaxHeads + 1;
-
- //
- // Since the BIOS may not report the full drive, recalculate the drive
- // size based on the volume size and the BIOS values for tracks per
- // cylinder and sectors per track..
- //
-
- length = tracksPerCylinder * sectorsPerTrack;
-
- if (length == 0) {
-
- //
- // The BIOS information is bogus.
- //
-
- DebugPrint((1, "DiskDriverReinit: H (%d) or S(%d) is zero\n",
- tracksPerCylinder, sectorsPerTrack));
- return;
- }
-
- //
- // since we are copying the structure RealGeometry here, we should
- // really initialize all the fields, especially since a zero'd
- // BytesPerSector field would cause a trap in xHalReadPartitionTable()
- //
-
- diskData->RealGeometry = fdoExtension->DiskGeometry;
-
- //
- // Save the geometry information away in the disk data block and
- // set the bit indicating that we found a valid one.
- //
-
- diskData->RealGeometry.SectorsPerTrack = sectorsPerTrack;
- diskData->RealGeometry.TracksPerCylinder = tracksPerCylinder;
- diskData->RealGeometry.Cylinders.QuadPart = (LONGLONG)cylinders;
-
- DebugPrint((1, "DiskDriverReinit: BIOS spt %#x, #heads %#x, "
- "#cylinders %#x\n",
- sectorsPerTrack, tracksPerCylinder, cylinders));
-
- diskData->GeometrySource = DiskGeometryGuessedFromBios;
- diskInfo->Device = unmatchedDisk;
-
- //
- // Now copy the geometry over to the fdo extension and call
- // classpnp to redetermine the disk size and cylinder count.
- //
-
- fdoExtension->DiskGeometry = diskData->RealGeometry;
-
- //
- // BUGBUG - why not call DiskReadDriveCapacity()?
- //
-
- ClassReadDriveCapacity(unmatchedDisk);
-
- if (diskData->RealGeometry.BytesPerSector == 0) {
-
- //
- // if the BytesPerSector field is set to zero for a disk
- // listed in the bios, then the system will bugcheck in
- // xHalReadPartitionTable(). assert here since it is
- // easier to determine what is happening this way.
- //
-
- ASSERT(!"RealGeometry not set to non-zero bps\n");
- }
- }
-
- return;
-}
-
-NTSTATUS
-NTAPI
-DiskGetDetectInfo(
- IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
- OUT PDISK_DETECTION_INFO DetectInfo
- )
-/*++
-
-Routine Description:
-
- Get the Int13 information from the BIOS DetectInfoList.
-
-Arguments:
-
- FdoExtension - Supplies a pointer to the FDO extension that we want to
- obtain the detect information for.
-
- DetectInfo - A buffer where the detect information will be copied to.
-
-Return Value:
-
- NTSTATUS code.
-
---*/
-{
- ULONG i;
- BOOLEAN found;
- PDISK_DETECT_INFO diskInfo = NULL;
- PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData;
-
- PAGED_CODE ();
-
- ASSERT(FdoExtension->CommonExtension.IsFdo);
-
- //
- // Fail for non-fixed drives.
- //
-
- if (TEST_FLAG (FdoExtension->DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA)) {
- return STATUS_NOT_SUPPORTED;
- }
-
- //
- // There is no GPT detection info, so fail this.
- //
-
- if (diskData->PartitionStyle == PARTITION_STYLE_GPT) {
- return STATUS_NOT_SUPPORTED;
- }
-
- for(i = 0; i < DetectInfoCount; i++) {
-
-
- ASSERT(DetectInfoList != NULL);
-
- diskInfo = &(DetectInfoList[i]);
-
- if((diskData->Mbr.Signature != 0) &&
- (diskData->Mbr.Signature == diskInfo->Signature)) {
- DebugPrint((1, "DiskGetDetectInfo: found match for signature "
- "%#08lx\n",
- diskData->Mbr.Signature));
- found = TRUE;
- break;
- } else if((diskData->Mbr.Signature == 0) &&
- (diskData->Mbr.MbrCheckSum != 0) &&
- (diskData->Mbr.MbrCheckSum == diskInfo->MbrCheckSum)) {
- DebugPrint((1, "DiskGetDetectInfo: found match for xsum %#08lx\n",
- diskData->Mbr.MbrCheckSum));
- found = TRUE;
- break;
- }
- }
-
- if ( found ) {
- DetectInfo->DetectionType = DetectInt13;
- DetectInfo->Int13.DriveSelect = diskInfo->DriveParameters.DriveSelect;
- DetectInfo->Int13.MaxCylinders = diskInfo->DriveParameters.MaxCylinders;
- DetectInfo->Int13.SectorsPerTrack = diskInfo->DriveParameters.SectorsPerTrack;
- DetectInfo->Int13.MaxHeads = diskInfo->DriveParameters.MaxHeads;
- DetectInfo->Int13.NumberDrives = diskInfo->DriveParameters.NumberDrives;
- RtlZeroMemory (&DetectInfo->ExInt13, sizeof (DetectInfo->ExInt13));
- }
-
- return (found ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
-}
-
-NTSTATUS
-NTAPI
-DiskReadSignature(
- IN PDEVICE_OBJECT Fdo
- )
-
-/*++
-
-Routine Description:
-
- Read the disks signature from the drive. The signature can be either
- a MBR signature or a GPT/EFI signature.
-
- The low-level signature reading is done by IoReadDiskSignature().
-
-Arguments:
-
- Fdo - Pointer to the FDO of a disk to read the signature for.
-
-Return Value:
-
- NTSTATUS code.
-
---*/
-
-
-{
- NTSTATUS Status;
- PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
- PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData;
- DISK_SIGNATURE Signature;
-
- PAGED_CODE ();
-
- Status = IoReadDiskSignature (Fdo,
- fdoExtension->DiskGeometry.BytesPerSector,
- &Signature);
-
- if (!NT_SUCCESS (Status)) {
- return Status;
- }
-
- if (Signature.PartitionStyle == PARTITION_STYLE_GPT) {
- diskData->PartitionStyle = PARTITION_STYLE_GPT;
- diskData->Efi.DiskId = Signature.Gpt.DiskId;
- } else if (Signature.PartitionStyle == PARTITION_STYLE_MBR) {
- diskData->PartitionStyle = PARTITION_STYLE_MBR;
- diskData->Mbr.Signature = Signature.Mbr.Signature;
- diskData->Mbr.MbrCheckSum = Signature.Mbr.CheckSum;
- } else {
- ASSERT (FALSE);
- Status = STATUS_UNSUCCESSFUL;
- }
-
- return Status;
-}
-
-#endif // defined(_X86_)