3 Copyright (C) Microsoft Corporation, 1991 - 1999
11 SCSI disk class driver - this module contains all the code for generating
31 IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension
36 DiskUpdateRemovableGeometry (
37 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
42 DiskScanBusDetectInfo(
43 IN PDRIVER_OBJECT DriverObject
,
49 DiskSaveBusDetectInfo(
50 IN PDRIVER_OBJECT DriverObject
,
57 DiskSaveGeometryDetectInfo(
58 IN PDRIVER_OBJECT DriverObject
,
65 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
66 OUT PDISK_GEOMETRY Geometry
69 typedef struct _DISK_DETECT_INFO
{
74 PDEVICE_OBJECT Device
;
75 CM_INT13_DRIVE_PARAMETER DriveParameters
;
76 } DISK_DETECT_INFO
, *PDISK_DETECT_INFO
;
79 // Information about the disk geometries collected and saved into the registry
80 // by NTDETECT.COM or the system firmware.
83 PDISK_DETECT_INFO DetectInfoList
= NULL
;
84 ULONG DetectInfoCount
= 0;
85 ULONG DetectInfoUsedCount
= 0;
88 #pragma alloc_text(INIT, DiskSaveDetectInfo)
89 #pragma alloc_text(INIT, DiskScanBusDetectInfo)
90 #pragma alloc_text(INIT, DiskSaveBusDetectInfo)
91 #pragma alloc_text(INIT, DiskSaveGeometryDetectInfo)
93 #pragma alloc_text(PAGE, DiskUpdateGeometry)
94 #pragma alloc_text(PAGE, DiskUpdateRemovableGeometry)
95 #pragma alloc_text(PAGE, DiskGetPortGeometry)
96 #pragma alloc_text(PAGE, DiskGetDetectInfo)
97 #pragma alloc_text(PAGE, DiskReadSignature)
104 PDRIVER_OBJECT DriverObject
110 This routine saves away the firmware information about the disks which has
111 been saved in the registry. It generates a list (DetectInfoList) which
112 contains the disk geometries, signatures & checksums of all drives which
113 were examined by NtDetect. This list is later used to assign geometries
114 to disks as they are initialized.
118 DriverObject - the driver being initialized. This is used to get to the
128 OBJECT_ATTRIBUTES objectAttributes
;
131 UNICODE_STRING unicodeString
;
138 InitializeObjectAttributes(
140 DriverObject
->HardwareDatabase
,
141 OBJ_CASE_INSENSITIVE
,
146 // Create the hardware base key.
149 status
= ZwOpenKey(&hardwareKey
, KEY_READ
, &objectAttributes
);
151 if(!NT_SUCCESS(status
)) {
152 DebugPrint((1, "DiskSaveDetectInfo: Cannot open hardware data. "
154 DriverObject
->HardwareDatabase
));
158 status
= DiskSaveGeometryDetectInfo(DriverObject
, hardwareKey
);
160 if(!NT_SUCCESS(status
)) {
161 DebugPrint((1, "DiskSaveDetectInfo: Can't query configuration data "
164 ZwClose(hardwareKey
);
169 // Open EISA bus key.
172 RtlInitUnicodeString(&unicodeString
, L
"EisaAdapter");
173 InitializeObjectAttributes(&objectAttributes
,
175 OBJ_CASE_INSENSITIVE
,
179 status
= ZwOpenKey(&busKey
,
183 if(NT_SUCCESS(status
)) {
184 DebugPrint((1, "DiskSaveDetectInfo: Opened EisaAdapter key\n"));
185 DiskScanBusDetectInfo(DriverObject
, busKey
);
190 // Open MultiFunction bus key.
193 RtlInitUnicodeString(&unicodeString
, L
"MultifunctionAdapter");
194 InitializeObjectAttributes(&objectAttributes
,
196 OBJ_CASE_INSENSITIVE
,
200 status
= ZwOpenKey(&busKey
,
204 if(NT_SUCCESS(status
)) {
205 DebugPrint((1, "DiskSaveDetectInfo: Opened MultifunctionAdapter key\n"));
206 DiskScanBusDetectInfo(DriverObject
, busKey
);
210 ZwClose(hardwareKey
);
212 return STATUS_SUCCESS
;
217 DiskCleanupDetectInfo(
218 IN PDRIVER_OBJECT DriverObject
224 This routine will cleanup the data structure built by DiskSaveDetectInfo.
228 DriverObject - a pointer to the kernel object for this driver.
237 if(DetectInfoList
!= NULL
) {
238 ExFreePool(DetectInfoList
);
239 DetectInfoList
= NULL
;
246 DiskSaveGeometryDetectInfo(
247 IN PDRIVER_OBJECT DriverObject
,
248 IN HANDLE HardwareKey
251 UNICODE_STRING unicodeString
;
252 PKEY_VALUE_FULL_INFORMATION keyData
;
255 PCM_FULL_RESOURCE_DESCRIPTOR fullDescriptor
;
256 PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor
;
258 PCM_INT13_DRIVE_PARAMETER driveParameters
;
259 ULONG numberOfDrives
;
268 // Get disk BIOS geometry information.
271 RtlInitUnicodeString(&unicodeString
, L
"Configuration Data");
273 keyData
= ExAllocatePoolWithTag(PagedPool
,
275 DISK_TAG_UPDATE_GEOM
);
277 if(keyData
== NULL
) {
278 DebugPrint((1, "DiskSaveGeometryDetectInfo: Can't allocate config "
280 return STATUS_INSUFFICIENT_RESOURCES
;
283 status
= ZwQueryValueKey(HardwareKey
,
285 KeyValueFullInformation
,
290 if(!NT_SUCCESS(status
)) {
291 DebugPrint((1, "DiskSaveGeometryDetectInfo: Can't query configuration "
299 // Extract the resource list out of the key data.
302 fullDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)
303 (((PUCHAR
) keyData
) + keyData
->DataOffset
);
305 fullDescriptor
->PartialResourceList
.PartialDescriptors
;
306 length
= partialDescriptor
->u
.DeviceSpecificData
.DataSize
;
308 if((keyData
->DataLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
)) ||
309 (fullDescriptor
->PartialResourceList
.Count
== 0) ||
310 (partialDescriptor
->Type
!= CmResourceTypeDeviceSpecific
) ||
311 (length
< sizeof(ULONG
))) {
313 DebugPrint((1, "DiskSaveGeometryDetectInfo: BIOS header data too small "
316 return STATUS_INVALID_PARAMETER
;
320 // Point to the BIOS data. THe BIOS data is located after the first
321 // partial Resource list which should be device specific data.
325 PUCHAR buffer
= (PUCHAR
) keyData
;
326 buffer
+= keyData
->DataOffset
;
327 buffer
+= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
);
328 driveParameters
= (PCM_INT13_DRIVE_PARAMETER
) buffer
;
331 numberOfDrives
= length
/ sizeof(CM_INT13_DRIVE_PARAMETER
);
334 // Allocate our detect info list now that we know how many entries there
335 // are going to be. No other routine allocates detect info and this is
336 // done out of DriverEntry so we don't need to synchronize it's creation.
339 length
= sizeof(DISK_DETECT_INFO
) * numberOfDrives
;
340 DetectInfoList
= ExAllocatePoolWithTag(PagedPool
,
342 DISK_TAG_UPDATE_GEOM
);
344 if(DetectInfoList
== NULL
) {
345 DebugPrint((1, "DiskSaveGeometryDetectInfo: Couldn't allocate %x bytes "
346 "for DetectInfoList\n",
350 return STATUS_INSUFFICIENT_RESOURCES
;
353 DetectInfoCount
= numberOfDrives
;
355 RtlZeroMemory(DetectInfoList
, length
);
358 // Copy the information out of the key data and into the list we've
362 for(i
= 0; i
< numberOfDrives
; i
++) {
363 DetectInfoList
[i
].DriveParameters
= driveParameters
[i
];
367 return STATUS_SUCCESS
;
372 DiskScanBusDetectInfo(
373 IN PDRIVER_OBJECT DriverObject
,
380 The routine queries the registry to determine which disks are visible to
381 the BIOS. If a disk is visible to the BIOS then the geometry information
382 is updated with the disk's signature and MBR checksum.
386 DriverObject - the object for this driver.
387 BusKey - handle to the bus key to be enumerated.
399 for(busNumber
= 0; ; busNumber
++) {
402 UNICODE_STRING unicodeString
;
404 OBJECT_ATTRIBUTES objectAttributes
;
411 DebugPrint((1, "DiskScanBusDetectInfo: Scanning bus %d\n", busNumber
));
414 // Open controller name key.
417 swprintf(buffer
, L
"%d", busNumber
);
418 RtlInitUnicodeString(&unicodeString
, buffer
);
420 InitializeObjectAttributes(&objectAttributes
,
422 OBJ_CASE_INSENSITIVE
,
426 status
= ZwOpenKey(&spareKey
, KEY_READ
, &objectAttributes
);
428 if(!NT_SUCCESS(status
)) {
429 DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening bus "
436 // Open up a controller ordinal key.
439 RtlInitUnicodeString(&unicodeString
, L
"DiskController");
440 InitializeObjectAttributes(&objectAttributes
,
442 OBJ_CASE_INSENSITIVE
,
446 status
= ZwOpenKey(&adapterKey
, KEY_READ
, &objectAttributes
);
449 if(!NT_SUCCESS(status
)) {
450 DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening "
451 "DiskController key\n",
456 for(adapterNumber
= 0; ; adapterNumber
++) {
465 DebugPrint((1, "DiskScanBusDetectInfo: Scanning disk key "
466 "%d\\DiskController\\%d\\DiskPeripheral\n",
467 busNumber
, adapterNumber
));
469 swprintf(buffer
, L
"%d\\DiskPeripheral", adapterNumber
);
470 RtlInitUnicodeString(&unicodeString
, buffer
);
472 InitializeObjectAttributes(&objectAttributes
,
474 OBJ_CASE_INSENSITIVE
,
478 status
= ZwOpenKey(&diskKey
, KEY_READ
, &objectAttributes
);
480 if(!NT_SUCCESS(status
)) {
481 DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening "
487 for(diskNumber
= 0; ; diskNumber
++) {
491 DebugPrint((1, "DiskScanBusDetectInfo: Scanning target key "
492 "%d\\DiskController\\%d\\DiskPeripheral\\%d\n",
493 busNumber
, adapterNumber
, diskNumber
));
495 swprintf(buffer
, L
"%d", diskNumber
);
496 RtlInitUnicodeString(&unicodeString
, buffer
);
498 InitializeObjectAttributes(&objectAttributes
,
500 OBJ_CASE_INSENSITIVE
,
504 status
= ZwOpenKey(&targetKey
, KEY_READ
, &objectAttributes
);
506 if(!NT_SUCCESS(status
)) {
507 DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx "
508 "opening target key\n",
513 status
= DiskSaveBusDetectInfo(DriverObject
,
529 DiskSaveBusDetectInfo(
530 IN PDRIVER_OBJECT DriverObject
,
538 This routine will transfer the firmware/ntdetect reported information
539 in the specified target key into the appropriate entry in the
544 DriverObject - the object for this driver.
546 TargetKey - the key for the disk being saved.
548 DiskNumber - the ordinal of the entry in the DiskPeripheral tree for this
557 PDISK_DETECT_INFO diskInfo
;
559 UNICODE_STRING unicodeString
;
561 PKEY_VALUE_FULL_INFORMATION keyData
;
568 diskInfo
= &(DetectInfoList
[DiskNumber
]);
570 if(diskInfo
->Initialized
) {
573 DebugPrint((1, "DiskSaveBusDetectInfo: disk entry %#x already has a "
574 "signature of %#08lx and mbr checksum of %#08lx\n",
577 diskInfo
->MbrCheckSum
));
578 return STATUS_UNSUCCESSFUL
;
581 RtlInitUnicodeString(&unicodeString
, L
"Identifier");
583 keyData
= ExAllocatePoolWithTag(PagedPool
,
585 DISK_TAG_UPDATE_GEOM
);
587 if(keyData
== NULL
) {
588 DebugPrint((1, "DiskSaveBusDetectInfo: Couldn't allocate space for "
590 return STATUS_INSUFFICIENT_RESOURCES
;
594 // Get disk peripheral identifier.
597 status
= ZwQueryValueKey(TargetKey
,
599 KeyValueFullInformation
,
604 if(!NT_SUCCESS(status
)) {
605 DebugPrint((1, "DiskSaveBusDetectInfo: Error %#08lx getting "
611 } else if (keyData
->DataLength
< 9*sizeof(WCHAR
)) {
614 // the data is too short to use (we subtract 9 chars in normal path)
616 DebugPrint((1, "DiskSaveBusDetectInfo: Saved data was invalid, "
617 "not enough data in registry!\n"));
619 return STATUS_UNSUCCESSFUL
;
623 UNICODE_STRING identifier
;
627 // Complete unicode string.
630 identifier
.Buffer
= (PWSTR
) ((PUCHAR
)keyData
+ keyData
->DataOffset
);
631 identifier
.Length
= (USHORT
) keyData
->DataLength
;
632 identifier
.MaximumLength
= (USHORT
) keyData
->DataLength
;
635 // Get the first value out of the identifier - this will be the MBR
639 status
= RtlUnicodeStringToInteger(&identifier
, 16, &value
);
641 if(!NT_SUCCESS(status
)) {
642 DebugPrint((1, "DiskSaveBusDetectInfo: Error %#08lx converting "
643 "identifier %wZ into MBR xsum\n",
650 diskInfo
->MbrCheckSum
= value
;
653 // Shift the string over to get the disk signature
656 identifier
.Buffer
+= 9;
657 identifier
.Length
-= 9 * sizeof(WCHAR
);
658 identifier
.MaximumLength
-= 9 * sizeof(WCHAR
);
660 status
= RtlUnicodeStringToInteger(&identifier
, 16, &value
);
662 if(!NT_SUCCESS(status
)) {
663 DebugPrint((1, "DiskSaveBusDetectInfo: Error %#08lx converting "
664 "identifier %wZ into disk signature\n",
671 diskInfo
->Signature
= value
;
675 // Here is where we would save away the extended int13 data.
679 // Mark this entry as initialized so we can make sure not to do it again.
682 diskInfo
->Initialized
= TRUE
;
685 return STATUS_SUCCESS
;
691 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
697 This routine checks the DetectInfoList saved away during disk driver init
698 to see if any geometry information was reported for this drive. If the
699 geometry data exists (determined by matching non-zero signatures or
700 non-zero MBR checksums) then it will be saved in the RealGeometry member
701 of the disk data block.
703 ClassReadDriveCapacity MUST be called after calling this routine to update
704 the cylinder count based on the size of the disk and the presence of any
705 disk management software.
709 DeviceExtension - Supplies a pointer to the device information for disk.
713 Indicates whether the "RealGeometry" in the data block is now valid.
718 PDISK_DATA diskData
= FdoExtension
->CommonExtension
.DriverData
;
721 PDISK_DETECT_INFO diskInfo
;
723 BOOLEAN found
= FALSE
;
730 ASSERT(FdoExtension
->CommonExtension
.IsFdo
);
731 ASSERT((FdoExtension
->DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
) == 0);
734 // If we've already set a non-default geometry for this drive then there's
735 // no need to try and update again.
738 if(diskData
->GeometrySource
!= DiskGeometryUnknown
) {
739 return diskData
->GeometrySource
;
743 // Scan through the saved detect info to see if we can find a match
747 for(i
= 0; i
< DetectInfoCount
; i
++) {
749 ASSERT(DetectInfoList
!= NULL
);
751 diskInfo
= &(DetectInfoList
[i
]);
753 if((diskData
->Mbr
.Signature
!= 0) &&
754 (diskData
->Mbr
.Signature
== diskInfo
->Signature
)) {
755 DebugPrint((1, "DiskUpdateGeometry: found match for signature "
757 diskData
->Mbr
.Signature
));
760 } else if((diskData
->Mbr
.Signature
== 0) &&
761 (diskData
->Mbr
.MbrCheckSum
!= 0) &&
762 (diskData
->Mbr
.MbrCheckSum
== diskInfo
->MbrCheckSum
)) {
763 DebugPrint((1, "DiskUpdateGeometry: found match for xsum %#08lx\n",
764 diskData
->Mbr
.MbrCheckSum
));
773 ULONG sectorsPerTrack
;
774 ULONG tracksPerCylinder
;
780 // Point to the array of drive parameters.
783 cylinders
= diskInfo
->DriveParameters
.MaxCylinders
+ 1;
784 sectorsPerTrack
= diskInfo
->DriveParameters
.SectorsPerTrack
;
785 tracksPerCylinder
= diskInfo
->DriveParameters
.MaxHeads
+ 1;
788 // Since the BIOS may not report the full drive, recalculate the drive
789 // size based on the volume size and the BIOS values for tracks per
790 // cylinder and sectors per track..
793 length
= tracksPerCylinder
* sectorsPerTrack
;
798 // The BIOS information is bogus.
801 DebugPrint((1, "DiskUpdateGeometry: H (%d) or S(%d) is zero\n",
802 tracksPerCylinder
, sectorsPerTrack
));
807 // since we are copying the structure RealGeometry here, we should
808 // really initialize all the fields, especially since a zero'd
809 // BytesPerSector field would cause a trap in xHalReadPartitionTable()
812 diskData
->RealGeometry
= FdoExtension
->DiskGeometry
;
815 // Save the geometry information away in the disk data block and
816 // set the bit indicating that we found a valid one.
819 diskData
->RealGeometry
.SectorsPerTrack
= sectorsPerTrack
;
820 diskData
->RealGeometry
.TracksPerCylinder
= tracksPerCylinder
;
821 diskData
->RealGeometry
.Cylinders
.QuadPart
= (LONGLONG
)cylinders
;
823 DebugPrint((1, "DiskUpdateGeometry: BIOS spt %#x, #heads %#x, "
825 sectorsPerTrack
, tracksPerCylinder
, cylinders
));
827 diskData
->GeometrySource
= DiskGeometryFromBios
;
828 diskInfo
->Device
= FdoExtension
->DeviceObject
;
832 DebugPrint((1, "DiskUpdateGeometry: no match found for signature %#08lx\n", diskData
->Mbr
.Signature
));
835 if(diskData
->GeometrySource
== DiskGeometryUnknown
) {
838 // We couldn't find a geometry from the BIOS. Check with the port
839 // driver and see if it can provide one.
842 status
= DiskGetPortGeometry(FdoExtension
, &(diskData
->RealGeometry
));
844 if(NT_SUCCESS(status
)) {
847 // Check the geometry to make sure it's valid.
850 if((diskData
->RealGeometry
.TracksPerCylinder
*
851 diskData
->RealGeometry
.SectorsPerTrack
) != 0) {
853 diskData
->GeometrySource
= DiskGeometryFromPort
;
854 DebugPrint((1, "DiskUpdateGeometry: using Port geometry for disk %#p\n", FdoExtension
));
856 if (diskData
->RealGeometry
.BytesPerSector
== 0) {
858 DebugPrint((0, "DiskDriverReinit: Port driver failed to "
859 "set BytesPerSector in the RealGeometry\n"));
860 diskData
->RealGeometry
.BytesPerSector
=
861 FdoExtension
->DiskGeometry
.BytesPerSector
;
862 if (diskData
->RealGeometry
.BytesPerSector
== 0) {
863 ASSERT(!"BytesPerSector is still zero!");
872 // If we came up with a "real" geometry for this drive then set it in the
876 if(diskData
->GeometrySource
!= DiskGeometryUnknown
) {
877 FdoExtension
->DiskGeometry
= diskData
->RealGeometry
;
880 // Increment the count of used geometry entries.
883 InterlockedIncrement(&DetectInfoUsedCount
);
886 return diskData
->GeometrySource
;
891 DiskUpdateRemovableGeometry (
892 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
899 This routine updates the geometry of the disk. It will query the port
900 driver to see if it can provide any geometry info. If not it will use
901 the current head & sector count.
903 Based on these values & the capacity of the drive as reported by
904 ClassReadDriveCapacity it will determine a new cylinder count for the
909 Fdo - Supplies the functional device object whos size needs to be updated.
913 Returns the status of the operation.
917 PCOMMON_DEVICE_EXTENSION commonExtension
= &(FdoExtension
->CommonExtension
);
918 PDISK_DATA diskData
= commonExtension
->DriverData
;
919 PDISK_GEOMETRY geometry
= &(diskData
->RealGeometry
);
925 ASSERT_FDO(commonExtension
->DeviceObject
);
926 if (FdoExtension
->DeviceDescriptor
) {
927 ASSERT(FdoExtension
->DeviceDescriptor
->RemovableMedia
);
929 ASSERT(TEST_FLAG(FdoExtension
->DeviceObject
->Characteristics
,
930 FILE_REMOVABLE_MEDIA
));
933 // Attempt to determine the disk geometry. First we'll check with the
934 // port driver to see what it suggests for a value.
937 status
= DiskGetPortGeometry(FdoExtension
, geometry
);
939 if(NT_SUCCESS(status
) &&
940 ((geometry
->TracksPerCylinder
* geometry
->SectorsPerTrack
) != 0)) {
942 FdoExtension
->DiskGeometry
= (*geometry
);
951 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
952 OUT PDISK_GEOMETRY Geometry
958 This routine will query the port driver for disk geometry. Some port
959 drivers (in particular IDEPORT) may be able to provide geometry for the
964 FdoExtension - the device object for the disk.
966 Geometry - a structure to save the geometry information into (if any is
971 STATUS_SUCCESS if geometry information can be provided or
972 error status indicating why it can't.
976 PCOMMON_DEVICE_EXTENSION commonExtension
= &(FdoExtension
->CommonExtension
);
978 PIO_STACK_LOCATION irpStack
;
986 // Build an irp to send IOCTL_DISK_GET_DRIVE_GEOMETRY to the lower driver.
989 irp
= IoAllocateIrp(commonExtension
->LowerDeviceObject
->StackSize
, FALSE
);
992 return STATUS_INSUFFICIENT_RESOURCES
;
995 irpStack
= IoGetNextIrpStackLocation(irp
);
997 irpStack
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
999 irpStack
->Parameters
.DeviceIoControl
.IoControlCode
=
1000 IOCTL_DISK_GET_DRIVE_GEOMETRY
;
1001 irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
=
1002 sizeof(DISK_GEOMETRY
);
1004 irp
->AssociatedIrp
.SystemBuffer
= Geometry
;
1006 KeInitializeEvent(&event
, SynchronizationEvent
, FALSE
);
1008 IoSetCompletionRoutine(irp
,
1009 (PIO_COMPLETION_ROUTINE
)ClassSignalCompletion
,
1015 status
= IoCallDriver(commonExtension
->LowerDeviceObject
, irp
);
1016 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
1018 ASSERT((status
== STATUS_PENDING
) || (status
== irp
->IoStatus
.Status
));
1019 status
= irp
->IoStatus
.Status
;
1028 DiskReadDriveCapacity(
1029 IN PDEVICE_OBJECT Fdo
1033 Routine Description:
1035 This routine is used by disk.sys as a wrapper for the classpnp API
1036 ClassReadDriveCapacity. It will perform some additional operations to
1037 attempt to determine drive geometry before it calls the classpnp version
1040 For fixed disks this involves calling DiskUpdateGeometry which will check
1041 various sources (the BIOS, the port driver) for geometry information.
1045 Fdo - a pointer to the device object to be checked.
1049 status of ClassReadDriveCapacity.
1054 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
1055 //PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData;
1056 //DISK_GEOMETRY_SOURCE diskGeometrySource = DiskGeometryUnknown;
1061 if (TEST_FLAG(Fdo
->Characteristics
, FILE_REMOVABLE_MEDIA
)) {
1062 DiskUpdateRemovableGeometry(fdoExtension
);
1064 /* diskGeometrySource =*/ DiskUpdateGeometry(fdoExtension
);
1067 status
= ClassReadDriveCapacity(Fdo
);
1074 DiskDriverReinitialization(
1075 IN PDRIVER_OBJECT DriverObject
,
1081 Routine Description:
1083 This routine will scan through the current list of disks and attempt to
1084 match them to any remaining geometry information. This will only be done
1085 on the first call to the routine.
1087 Note: This routine assumes that the system will not be adding or removing
1088 devices during this phase of the init process. This is very likely
1089 a bad assumption but it greatly simplifies the code.
1093 DriverObject - a pointer to the object for the disk driver.
1097 Count - an indication of how many times this routine has been called.
1106 PDEVICE_OBJECT deviceObject
;
1107 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
;
1108 PDISK_DATA diskData
;
1110 ULONG unmatchedDiskCount
;
1111 PDEVICE_OBJECT unmatchedDisk
= NULL
;
1114 PDISK_DETECT_INFO diskInfo
= NULL
;
1117 DebugPrint((1, "DiskDriverReinitialization: ignoring call %d\n",
1123 // Check to see how many entries in the detect info list have been matched.
1124 // If there's only one remaining we'll see if we can find a disk to go with
1128 if(DetectInfoCount
== 0) {
1129 DebugPrint((1, "DiskDriverReinitialization: no detect info saved\n"));
1133 if((DetectInfoCount
- DetectInfoUsedCount
) != 1) {
1134 DebugPrint((1, "DiskDriverReinitialization: %d of %d geometry entries "
1135 "used - will not attempt match\n"));
1140 // Scan through the list of disks and see if any of them are missing
1141 // geometry information. If there is only one such disk we'll try to
1142 // match it to the unmatched geometry.
1147 // ISSUE-2000/5/24-henrygab - figure out if there's a way to keep
1148 // removals from happening while doing this.
1151 for(deviceObject
= DriverObject
->DeviceObject
, unmatchedDiskCount
= 0;
1152 deviceObject
!= NULL
;
1153 deviceObject
= deviceObject
->NextDevice
) {
1156 // Make sure this is a disk and not a partition.
1159 fdoExtension
= deviceObject
->DeviceExtension
;
1160 if(fdoExtension
->CommonExtension
.IsFdo
== FALSE
) {
1161 DebugPrint((1, "DiskDriverReinit: DO %#p is not an FDO\n",
1167 // If the geometry for this one is already known then skip it.
1170 diskData
= fdoExtension
->CommonExtension
.DriverData
;
1171 if(diskData
->GeometrySource
!= DiskGeometryUnknown
) {
1172 DebugPrint((1, "DiskDriverReinit: FDO %#p has a geometry\n",
1177 DebugPrint((1, "DiskDriverReinit: FDO %#p has no geometry\n",
1181 // Mark this one as using the default. It's past the time when disk
1182 // might blunder across the geometry info. If we set the geometry
1183 // from the bios we'll reset this field down below.
1186 diskData
->GeometrySource
= DiskGeometryFromDefault
;
1189 // As long as we've only got one unmatched disk we're fine.
1192 unmatchedDiskCount
++;
1193 if(unmatchedDiskCount
> 1) {
1194 ASSERT(unmatchedDisk
!= NULL
);
1195 DebugPrint((1, "DiskDriverReinit: FDO %#p also has no geometry\n",
1197 unmatchedDisk
= NULL
;
1201 unmatchedDisk
= deviceObject
;
1205 // If there's more or less than one ungeometried disk then we can't do
1206 // anything about the geometry.
1209 if(unmatchedDiskCount
!= 1) {
1210 DebugPrint((1, "DiskDriverReinit: Unable to match geometry\n"));
1215 fdoExtension
= unmatchedDisk
->DeviceExtension
;
1216 diskData
= fdoExtension
->CommonExtension
.DriverData
;
1218 DebugPrint((1, "DiskDriverReinit: Found possible match\n"));
1221 // Find the geometry which wasn't assigned.
1224 for(i
= 0; i
< DetectInfoCount
; i
++) {
1225 if(DetectInfoList
[i
].Device
== NULL
) {
1226 diskInfo
= &(DetectInfoList
[i
]);
1231 ASSERT(diskInfo
!= NULL
);
1235 // Save the geometry information away in the disk data block and
1236 // set the bit indicating that we found a valid one.
1240 ULONG sectorsPerTrack
;
1241 ULONG tracksPerCylinder
;
1247 // Point to the array of drive parameters.
1250 cylinders
= diskInfo
->DriveParameters
.MaxCylinders
+ 1;
1251 sectorsPerTrack
= diskInfo
->DriveParameters
.SectorsPerTrack
;
1252 tracksPerCylinder
= diskInfo
->DriveParameters
.MaxHeads
+ 1;
1255 // Since the BIOS may not report the full drive, recalculate the drive
1256 // size based on the volume size and the BIOS values for tracks per
1257 // cylinder and sectors per track..
1260 length
= tracksPerCylinder
* sectorsPerTrack
;
1265 // The BIOS information is bogus.
1268 DebugPrint((1, "DiskDriverReinit: H (%d) or S(%d) is zero\n",
1269 tracksPerCylinder
, sectorsPerTrack
));
1274 // since we are copying the structure RealGeometry here, we should
1275 // really initialize all the fields, especially since a zero'd
1276 // BytesPerSector field would cause a trap in xHalReadPartitionTable()
1279 diskData
->RealGeometry
= fdoExtension
->DiskGeometry
;
1282 // Save the geometry information away in the disk data block and
1283 // set the bit indicating that we found a valid one.
1286 diskData
->RealGeometry
.SectorsPerTrack
= sectorsPerTrack
;
1287 diskData
->RealGeometry
.TracksPerCylinder
= tracksPerCylinder
;
1288 diskData
->RealGeometry
.Cylinders
.QuadPart
= (LONGLONG
)cylinders
;
1290 DebugPrint((1, "DiskDriverReinit: BIOS spt %#x, #heads %#x, "
1292 sectorsPerTrack
, tracksPerCylinder
, cylinders
));
1294 diskData
->GeometrySource
= DiskGeometryGuessedFromBios
;
1295 diskInfo
->Device
= unmatchedDisk
;
1298 // Now copy the geometry over to the fdo extension and call
1299 // classpnp to redetermine the disk size and cylinder count.
1302 fdoExtension
->DiskGeometry
= diskData
->RealGeometry
;
1305 // BUGBUG - why not call DiskReadDriveCapacity()?
1308 ClassReadDriveCapacity(unmatchedDisk
);
1310 if (diskData
->RealGeometry
.BytesPerSector
== 0) {
1313 // if the BytesPerSector field is set to zero for a disk
1314 // listed in the bios, then the system will bugcheck in
1315 // xHalReadPartitionTable(). assert here since it is
1316 // easier to determine what is happening this way.
1319 ASSERT(!"RealGeometry not set to non-zero bps\n");
1329 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
1330 OUT PDISK_DETECTION_INFO DetectInfo
1334 Routine Description:
1336 Get the Int13 information from the BIOS DetectInfoList.
1340 FdoExtension - Supplies a pointer to the FDO extension that we want to
1341 obtain the detect information for.
1343 DetectInfo - A buffer where the detect information will be copied to.
1353 PDISK_DETECT_INFO diskInfo
= NULL
;
1354 PDISK_DATA diskData
= FdoExtension
->CommonExtension
.DriverData
;
1358 ASSERT(FdoExtension
->CommonExtension
.IsFdo
);
1361 // Fail for non-fixed drives.
1364 if (TEST_FLAG (FdoExtension
->DeviceObject
->Characteristics
, FILE_REMOVABLE_MEDIA
)) {
1365 return STATUS_NOT_SUPPORTED
;
1369 // There is no GPT detection info, so fail this.
1372 if (diskData
->PartitionStyle
== PARTITION_STYLE_GPT
) {
1373 return STATUS_NOT_SUPPORTED
;
1376 for(i
= 0; i
< DetectInfoCount
; i
++) {
1379 ASSERT(DetectInfoList
!= NULL
);
1381 diskInfo
= &(DetectInfoList
[i
]);
1383 if((diskData
->Mbr
.Signature
!= 0) &&
1384 (diskData
->Mbr
.Signature
== diskInfo
->Signature
)) {
1385 DebugPrint((1, "DiskGetDetectInfo: found match for signature "
1387 diskData
->Mbr
.Signature
));
1390 } else if((diskData
->Mbr
.Signature
== 0) &&
1391 (diskData
->Mbr
.MbrCheckSum
!= 0) &&
1392 (diskData
->Mbr
.MbrCheckSum
== diskInfo
->MbrCheckSum
)) {
1393 DebugPrint((1, "DiskGetDetectInfo: found match for xsum %#08lx\n",
1394 diskData
->Mbr
.MbrCheckSum
));
1401 DetectInfo
->DetectionType
= DetectInt13
;
1402 DetectInfo
->Int13
.DriveSelect
= diskInfo
->DriveParameters
.DriveSelect
;
1403 DetectInfo
->Int13
.MaxCylinders
= diskInfo
->DriveParameters
.MaxCylinders
;
1404 DetectInfo
->Int13
.SectorsPerTrack
= diskInfo
->DriveParameters
.SectorsPerTrack
;
1405 DetectInfo
->Int13
.MaxHeads
= diskInfo
->DriveParameters
.MaxHeads
;
1406 DetectInfo
->Int13
.NumberDrives
= diskInfo
->DriveParameters
.NumberDrives
;
1407 RtlZeroMemory (&DetectInfo
->ExInt13
, sizeof (DetectInfo
->ExInt13
));
1410 return (found
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
1416 IN PDEVICE_OBJECT Fdo
1421 Routine Description:
1423 Read the disks signature from the drive. The signature can be either
1424 a MBR signature or a GPT/EFI signature.
1426 The low-level signature reading is done by IoReadDiskSignature().
1430 Fdo - Pointer to the FDO of a disk to read the signature for.
1441 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
1442 PDISK_DATA diskData
= fdoExtension
->CommonExtension
.DriverData
;
1443 DISK_SIGNATURE Signature
;
1447 Status
= IoReadDiskSignature (Fdo
,
1448 fdoExtension
->DiskGeometry
.BytesPerSector
,
1451 if (!NT_SUCCESS (Status
)) {
1455 if (Signature
.PartitionStyle
== PARTITION_STYLE_GPT
) {
1456 diskData
->PartitionStyle
= PARTITION_STYLE_GPT
;
1457 diskData
->Efi
.DiskId
= Signature
.Gpt
.DiskId
;
1458 } else if (Signature
.PartitionStyle
== PARTITION_STYLE_MBR
) {
1459 diskData
->PartitionStyle
= PARTITION_STYLE_MBR
;
1460 diskData
->Mbr
.Signature
= Signature
.Mbr
.Signature
;
1461 diskData
->Mbr
.MbrCheckSum
= Signature
.Mbr
.CheckSum
;
1464 Status
= STATUS_UNSUCCESSFUL
;
1470 #endif // defined(_X86_)