3 Copyright (C) Microsoft Corporation, 1991 - 1999
11 SCSI disk class driver - this module contains all the code for generating
33 IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension
38 DiskUpdateRemovableGeometry (
39 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
44 DiskScanBusDetectInfo(
45 IN PDRIVER_OBJECT DriverObject
,
51 DiskSaveBusDetectInfo(
52 IN PDRIVER_OBJECT DriverObject
,
59 DiskSaveGeometryDetectInfo(
60 IN PDRIVER_OBJECT DriverObject
,
67 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
68 OUT PDISK_GEOMETRY Geometry
71 typedef struct _DISK_DETECT_INFO
{
76 PDEVICE_OBJECT Device
;
77 CM_INT13_DRIVE_PARAMETER DriveParameters
;
78 } DISK_DETECT_INFO
, *PDISK_DETECT_INFO
;
81 // Information about the disk geometries collected and saved into the registry
82 // by NTDETECT.COM or the system firmware.
85 PDISK_DETECT_INFO DetectInfoList
= NULL
;
86 ULONG DetectInfoCount
= 0;
87 ULONG DetectInfoUsedCount
= 0;
90 #pragma alloc_text(INIT, DiskSaveDetectInfo)
91 #pragma alloc_text(INIT, DiskScanBusDetectInfo)
92 #pragma alloc_text(INIT, DiskSaveBusDetectInfo)
93 #pragma alloc_text(INIT, DiskSaveGeometryDetectInfo)
95 #pragma alloc_text(PAGE, DiskUpdateGeometry)
96 #pragma alloc_text(PAGE, DiskUpdateRemovableGeometry)
97 #pragma alloc_text(PAGE, DiskGetPortGeometry)
98 #pragma alloc_text(PAGE, DiskGetDetectInfo)
99 #pragma alloc_text(PAGE, DiskReadSignature)
106 PDRIVER_OBJECT DriverObject
112 This routine saves away the firmware information about the disks which has
113 been saved in the registry. It generates a list (DetectInfoList) which
114 contains the disk geometries, signatures & checksums of all drives which
115 were examined by NtDetect. This list is later used to assign geometries
116 to disks as they are initialized.
120 DriverObject - the driver being initialized. This is used to get to the
130 OBJECT_ATTRIBUTES objectAttributes
;
133 UNICODE_STRING unicodeString
;
140 InitializeObjectAttributes(
142 DriverObject
->HardwareDatabase
,
143 OBJ_CASE_INSENSITIVE
,
148 // Create the hardware base key.
151 status
= ZwOpenKey(&hardwareKey
, KEY_READ
, &objectAttributes
);
153 if(!NT_SUCCESS(status
)) {
154 DebugPrint((1, "DiskSaveDetectInfo: Cannot open hardware data. "
156 DriverObject
->HardwareDatabase
));
160 status
= DiskSaveGeometryDetectInfo(DriverObject
, hardwareKey
);
162 if(!NT_SUCCESS(status
)) {
163 DebugPrint((1, "DiskSaveDetectInfo: Can't query configuration data "
166 ZwClose(hardwareKey
);
171 // Open EISA bus key.
174 RtlInitUnicodeString(&unicodeString
, L
"EisaAdapter");
175 InitializeObjectAttributes(&objectAttributes
,
177 OBJ_CASE_INSENSITIVE
,
181 status
= ZwOpenKey(&busKey
,
185 if(NT_SUCCESS(status
)) {
186 DebugPrint((1, "DiskSaveDetectInfo: Opened EisaAdapter key\n"));
187 DiskScanBusDetectInfo(DriverObject
, busKey
);
192 // Open MultiFunction bus key.
195 RtlInitUnicodeString(&unicodeString
, L
"MultifunctionAdapter");
196 InitializeObjectAttributes(&objectAttributes
,
198 OBJ_CASE_INSENSITIVE
,
202 status
= ZwOpenKey(&busKey
,
206 if(NT_SUCCESS(status
)) {
207 DebugPrint((1, "DiskSaveDetectInfo: Opened MultifunctionAdapter key\n"));
208 DiskScanBusDetectInfo(DriverObject
, busKey
);
212 ZwClose(hardwareKey
);
214 return STATUS_SUCCESS
;
219 DiskCleanupDetectInfo(
220 IN PDRIVER_OBJECT DriverObject
226 This routine will cleanup the data structure built by DiskSaveDetectInfo.
230 DriverObject - a pointer to the kernel object for this driver.
239 if(DetectInfoList
!= NULL
) {
240 ExFreePool(DetectInfoList
);
241 DetectInfoList
= NULL
;
248 DiskSaveGeometryDetectInfo(
249 IN PDRIVER_OBJECT DriverObject
,
250 IN HANDLE HardwareKey
253 UNICODE_STRING unicodeString
;
254 PKEY_VALUE_FULL_INFORMATION keyData
;
257 PCM_FULL_RESOURCE_DESCRIPTOR fullDescriptor
;
258 PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptor
;
260 PCM_INT13_DRIVE_PARAMETER driveParameters
;
261 ULONG numberOfDrives
;
270 // Get disk BIOS geometry information.
273 RtlInitUnicodeString(&unicodeString
, L
"Configuration Data");
275 keyData
= ExAllocatePoolWithTag(PagedPool
,
277 DISK_TAG_UPDATE_GEOM
);
279 if(keyData
== NULL
) {
280 DebugPrint((1, "DiskSaveGeometryDetectInfo: Can't allocate config "
282 return STATUS_INSUFFICIENT_RESOURCES
;
285 status
= ZwQueryValueKey(HardwareKey
,
287 KeyValueFullInformation
,
292 if(!NT_SUCCESS(status
)) {
293 DebugPrint((1, "DiskSaveGeometryDetectInfo: Can't query configuration "
301 // Extract the resource list out of the key data.
304 fullDescriptor
= (PCM_FULL_RESOURCE_DESCRIPTOR
)
305 (((PUCHAR
) keyData
) + keyData
->DataOffset
);
307 fullDescriptor
->PartialResourceList
.PartialDescriptors
;
308 length
= partialDescriptor
->u
.DeviceSpecificData
.DataSize
;
310 if((keyData
->DataLength
< sizeof(CM_FULL_RESOURCE_DESCRIPTOR
)) ||
311 (fullDescriptor
->PartialResourceList
.Count
== 0) ||
312 (partialDescriptor
->Type
!= CmResourceTypeDeviceSpecific
) ||
313 (length
< sizeof(ULONG
))) {
315 DebugPrint((1, "DiskSaveGeometryDetectInfo: BIOS header data too small "
318 return STATUS_INVALID_PARAMETER
;
322 // Point to the BIOS data. THe BIOS data is located after the first
323 // partial Resource list which should be device specific data.
327 PUCHAR buffer
= (PUCHAR
) keyData
;
328 buffer
+= keyData
->DataOffset
;
329 buffer
+= sizeof(CM_FULL_RESOURCE_DESCRIPTOR
);
330 driveParameters
= (PCM_INT13_DRIVE_PARAMETER
) buffer
;
333 numberOfDrives
= length
/ sizeof(CM_INT13_DRIVE_PARAMETER
);
336 // Allocate our detect info list now that we know how many entries there
337 // are going to be. No other routine allocates detect info and this is
338 // done out of DriverEntry so we don't need to synchronize it's creation.
341 length
= sizeof(DISK_DETECT_INFO
) * numberOfDrives
;
342 DetectInfoList
= ExAllocatePoolWithTag(PagedPool
,
344 DISK_TAG_UPDATE_GEOM
);
346 if(DetectInfoList
== NULL
) {
347 DebugPrint((1, "DiskSaveGeometryDetectInfo: Couldn't allocate %x bytes "
348 "for DetectInfoList\n",
352 return STATUS_INSUFFICIENT_RESOURCES
;
355 DetectInfoCount
= numberOfDrives
;
357 RtlZeroMemory(DetectInfoList
, length
);
360 // Copy the information out of the key data and into the list we've
364 for(i
= 0; i
< numberOfDrives
; i
++) {
365 DetectInfoList
[i
].DriveParameters
= driveParameters
[i
];
369 return STATUS_SUCCESS
;
374 DiskScanBusDetectInfo(
375 IN PDRIVER_OBJECT DriverObject
,
382 The routine queries the registry to determine which disks are visible to
383 the BIOS. If a disk is visable to the BIOS then the geometry information
384 is updated with the disk's signature and MBR checksum.
388 DriverObject - the object for this driver.
389 BusKey - handle to the bus key to be enumerated.
401 for(busNumber
= 0; ; busNumber
++) {
404 UNICODE_STRING unicodeString
;
406 OBJECT_ATTRIBUTES objectAttributes
;
413 DebugPrint((1, "DiskScanBusDetectInfo: Scanning bus %d\n", busNumber
));
416 // Open controller name key.
419 swprintf(buffer
, L
"%d", busNumber
);
420 RtlInitUnicodeString(&unicodeString
, buffer
);
422 InitializeObjectAttributes(&objectAttributes
,
424 OBJ_CASE_INSENSITIVE
,
428 status
= ZwOpenKey(&spareKey
, KEY_READ
, &objectAttributes
);
430 if(!NT_SUCCESS(status
)) {
431 DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening bus "
438 // Open up a controller ordinal key.
441 RtlInitUnicodeString(&unicodeString
, L
"DiskController");
442 InitializeObjectAttributes(&objectAttributes
,
444 OBJ_CASE_INSENSITIVE
,
448 status
= ZwOpenKey(&adapterKey
, KEY_READ
, &objectAttributes
);
451 if(!NT_SUCCESS(status
)) {
452 DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening "
453 "DiskController key\n",
458 for(adapterNumber
= 0; ; adapterNumber
++) {
467 DebugPrint((1, "DiskScanBusDetectInfo: Scanning disk key "
468 "%d\\DiskController\\%d\\DiskPeripheral\n",
469 busNumber
, adapterNumber
));
471 swprintf(buffer
, L
"%d\\DiskPeripheral", adapterNumber
);
472 RtlInitUnicodeString(&unicodeString
, buffer
);
474 InitializeObjectAttributes(&objectAttributes
,
476 OBJ_CASE_INSENSITIVE
,
480 status
= ZwOpenKey(&diskKey
, KEY_READ
, &objectAttributes
);
482 if(!NT_SUCCESS(status
)) {
483 DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx opening "
489 for(diskNumber
= 0; ; diskNumber
++) {
493 DebugPrint((1, "DiskScanBusDetectInfo: Scanning target key "
494 "%d\\DiskController\\%d\\DiskPeripheral\\%d\n",
495 busNumber
, adapterNumber
, diskNumber
));
497 swprintf(buffer
, L
"%d", diskNumber
);
498 RtlInitUnicodeString(&unicodeString
, buffer
);
500 InitializeObjectAttributes(&objectAttributes
,
502 OBJ_CASE_INSENSITIVE
,
506 status
= ZwOpenKey(&targetKey
, KEY_READ
, &objectAttributes
);
508 if(!NT_SUCCESS(status
)) {
509 DebugPrint((1, "DiskScanBusDetectInfo: Error %#08lx "
510 "opening target key\n",
515 status
= DiskSaveBusDetectInfo(DriverObject
,
531 DiskSaveBusDetectInfo(
532 IN PDRIVER_OBJECT DriverObject
,
540 This routine will transfer the firmware/ntdetect reported information
541 in the specified target key into the appropriate entry in the
546 DriverObject - the object for this driver.
548 TargetKey - the key for the disk being saved.
550 DiskNumber - the ordinal of the entry in the DiskPeripheral tree for this
559 PDISK_DETECT_INFO diskInfo
;
561 UNICODE_STRING unicodeString
;
563 PKEY_VALUE_FULL_INFORMATION keyData
;
570 diskInfo
= &(DetectInfoList
[DiskNumber
]);
572 if(diskInfo
->Initialized
) {
575 DebugPrint((1, "DiskSaveBusDetectInfo: disk entry %#x already has a "
576 "signature of %#08lx and mbr checksum of %#08lx\n",
579 diskInfo
->MbrCheckSum
));
580 return STATUS_UNSUCCESSFUL
;
583 RtlInitUnicodeString(&unicodeString
, L
"Identifier");
585 keyData
= ExAllocatePoolWithTag(PagedPool
,
587 DISK_TAG_UPDATE_GEOM
);
589 if(keyData
== NULL
) {
590 DebugPrint((1, "DiskSaveBusDetectInfo: Couldn't allocate space for "
592 return STATUS_INSUFFICIENT_RESOURCES
;
596 // Get disk peripheral identifier.
599 status
= ZwQueryValueKey(TargetKey
,
601 KeyValueFullInformation
,
606 if(!NT_SUCCESS(status
)) {
607 DebugPrint((1, "DiskSaveBusDetectInfo: Error %#08lx getting "
613 } else if (keyData
->DataLength
< 9*sizeof(WCHAR
)) {
616 // the data is too short to use (we subtract 9 chars in normal path)
618 DebugPrint((1, "DiskSaveBusDetectInfo: Saved data was invalid, "
619 "not enough data in registry!\n"));
621 return STATUS_UNSUCCESSFUL
;
625 UNICODE_STRING identifier
;
629 // Complete unicode string.
632 identifier
.Buffer
= (PWSTR
) ((PUCHAR
)keyData
+ keyData
->DataOffset
);
633 identifier
.Length
= (USHORT
) keyData
->DataLength
;
634 identifier
.MaximumLength
= (USHORT
) keyData
->DataLength
;
637 // Get the first value out of the identifier - this will be the MBR
641 status
= RtlUnicodeStringToInteger(&identifier
, 16, &value
);
643 if(!NT_SUCCESS(status
)) {
644 DebugPrint((1, "DiskSaveBusDetectInfo: Error %#08lx converting "
645 "identifier %wZ into MBR xsum\n",
652 diskInfo
->MbrCheckSum
= value
;
655 // Shift the string over to get the disk signature
658 identifier
.Buffer
+= 9;
659 identifier
.Length
-= 9 * sizeof(WCHAR
);
660 identifier
.MaximumLength
-= 9 * sizeof(WCHAR
);
662 status
= RtlUnicodeStringToInteger(&identifier
, 16, &value
);
664 if(!NT_SUCCESS(status
)) {
665 DebugPrint((1, "DiskSaveBusDetectInfo: Error %#08lx converting "
666 "identifier %wZ into disk signature\n",
673 diskInfo
->Signature
= value
;
677 // Here is where we would save away the extended int13 data.
681 // Mark this entry as initialized so we can make sure not to do it again.
684 diskInfo
->Initialized
= TRUE
;
687 return STATUS_SUCCESS
;
693 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
699 This routine checks the DetectInfoList saved away during disk driver init
700 to see if any geometry information was reported for this drive. If the
701 geometry data exists (determined by matching non-zero signatures or
702 non-zero MBR checksums) then it will be saved in the RealGeometry member
703 of the disk data block.
705 ClassReadDriveCapacity MUST be called after calling this routine to update
706 the cylinder count based on the size of the disk and the presence of any
707 disk management software.
711 DeviceExtension - Supplies a pointer to the device information for disk.
715 Inidicates whether the "RealGeometry" in the data block is now valid.
720 PDISK_DATA diskData
= FdoExtension
->CommonExtension
.DriverData
;
723 PDISK_DETECT_INFO diskInfo
;
725 BOOLEAN found
= FALSE
;
732 ASSERT(FdoExtension
->CommonExtension
.IsFdo
);
733 ASSERT((FdoExtension
->DeviceObject
->Characteristics
& FILE_REMOVABLE_MEDIA
) == 0);
736 // If we've already set a non-default geometry for this drive then there's
737 // no need to try and update again.
740 if(diskData
->GeometrySource
!= DiskGeometryUnknown
) {
741 return diskData
->GeometrySource
;
745 // Scan through the saved detect info to see if we can find a match
749 for(i
= 0; i
< DetectInfoCount
; i
++) {
751 ASSERT(DetectInfoList
!= NULL
);
753 diskInfo
= &(DetectInfoList
[i
]);
755 if((diskData
->Mbr
.Signature
!= 0) &&
756 (diskData
->Mbr
.Signature
== diskInfo
->Signature
)) {
757 DebugPrint((1, "DiskUpdateGeometry: found match for signature "
759 diskData
->Mbr
.Signature
));
762 } else if((diskData
->Mbr
.Signature
== 0) &&
763 (diskData
->Mbr
.MbrCheckSum
!= 0) &&
764 (diskData
->Mbr
.MbrCheckSum
== diskInfo
->MbrCheckSum
)) {
765 DebugPrint((1, "DiskUpdateGeometry: found match for xsum %#08lx\n",
766 diskData
->Mbr
.MbrCheckSum
));
775 ULONG sectorsPerTrack
;
776 ULONG tracksPerCylinder
;
782 // Point to the array of drive parameters.
785 cylinders
= diskInfo
->DriveParameters
.MaxCylinders
+ 1;
786 sectorsPerTrack
= diskInfo
->DriveParameters
.SectorsPerTrack
;
787 tracksPerCylinder
= diskInfo
->DriveParameters
.MaxHeads
+ 1;
790 // Since the BIOS may not report the full drive, recalculate the drive
791 // size based on the volume size and the BIOS values for tracks per
792 // cylinder and sectors per track..
795 length
= tracksPerCylinder
* sectorsPerTrack
;
800 // The BIOS information is bogus.
803 DebugPrint((1, "DiskUpdateGeometry: H (%d) or S(%d) is zero\n",
804 tracksPerCylinder
, sectorsPerTrack
));
809 // since we are copying the structure RealGeometry here, we should
810 // really initialize all the fields, especially since a zero'd
811 // BytesPerSector field would cause a trap in xHalReadPartitionTable()
814 diskData
->RealGeometry
= FdoExtension
->DiskGeometry
;
817 // Save the geometry information away in the disk data block and
818 // set the bit indicating that we found a valid one.
821 diskData
->RealGeometry
.SectorsPerTrack
= sectorsPerTrack
;
822 diskData
->RealGeometry
.TracksPerCylinder
= tracksPerCylinder
;
823 diskData
->RealGeometry
.Cylinders
.QuadPart
= (LONGLONG
)cylinders
;
825 DebugPrint((1, "DiskUpdateGeometry: BIOS spt %#x, #heads %#x, "
827 sectorsPerTrack
, tracksPerCylinder
, cylinders
));
829 diskData
->GeometrySource
= DiskGeometryFromBios
;
830 diskInfo
->Device
= FdoExtension
->DeviceObject
;
834 DebugPrint((1, "DiskUpdateGeometry: no match found for signature %#08lx\n", diskData
->Mbr
.Signature
));
837 if(diskData
->GeometrySource
== DiskGeometryUnknown
) {
840 // We couldn't find a geometry from the BIOS. Check with the port
841 // driver and see if it can provide one.
844 status
= DiskGetPortGeometry(FdoExtension
, &(diskData
->RealGeometry
));
846 if(NT_SUCCESS(status
)) {
849 // Check the geometry to make sure it's valid.
852 if((diskData
->RealGeometry
.TracksPerCylinder
*
853 diskData
->RealGeometry
.SectorsPerTrack
) != 0) {
855 diskData
->GeometrySource
= DiskGeometryFromPort
;
856 DebugPrint((1, "DiskUpdateGeometry: using Port geometry for disk %#p\n", FdoExtension
));
858 if (diskData
->RealGeometry
.BytesPerSector
== 0) {
860 DebugPrint((0, "DiskDriverReinit: Port driver failed to "
861 "set BytesPerSector in the RealGeometry\n"));
862 diskData
->RealGeometry
.BytesPerSector
=
863 FdoExtension
->DiskGeometry
.BytesPerSector
;
864 if (diskData
->RealGeometry
.BytesPerSector
== 0) {
865 ASSERT(!"BytesPerSector is still zero!");
874 // If we came up with a "real" geometry for this drive then set it in the
878 if(diskData
->GeometrySource
!= DiskGeometryUnknown
) {
879 FdoExtension
->DiskGeometry
= diskData
->RealGeometry
;
882 // Increment the count of used geometry entries.
885 InterlockedIncrement(&DetectInfoUsedCount
);
888 return diskData
->GeometrySource
;
893 DiskUpdateRemovableGeometry (
894 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
901 This routine updates the geometry of the disk. It will query the port
902 driver to see if it can provide any geometry info. If not it will use
903 the current head & sector count.
905 Based on these values & the capacity of the drive as reported by
906 ClassReadDriveCapacity it will determine a new cylinder count for the
911 Fdo - Supplies the functional device object whos size needs to be updated.
915 Returns the status of the opertion.
919 PCOMMON_DEVICE_EXTENSION commonExtension
= &(FdoExtension
->CommonExtension
);
920 PDISK_DATA diskData
= commonExtension
->DriverData
;
921 PDISK_GEOMETRY geometry
= &(diskData
->RealGeometry
);
927 ASSERT_FDO(commonExtension
->DeviceObject
);
928 if (FdoExtension
->DeviceDescriptor
) {
929 ASSERT(FdoExtension
->DeviceDescriptor
->RemovableMedia
);
931 ASSERT(TEST_FLAG(FdoExtension
->DeviceObject
->Characteristics
,
932 FILE_REMOVABLE_MEDIA
));
935 // Attempt to determine the disk geometry. First we'll check with the
936 // port driver to see what it suggests for a value.
939 status
= DiskGetPortGeometry(FdoExtension
, geometry
);
941 if(NT_SUCCESS(status
) &&
942 ((geometry
->TracksPerCylinder
* geometry
->SectorsPerTrack
) != 0)) {
944 FdoExtension
->DiskGeometry
= (*geometry
);
953 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
954 OUT PDISK_GEOMETRY Geometry
960 This routine will query the port driver for disk geometry. Some port
961 drivers (in particular IDEPORT) may be able to provide geometry for the
966 FdoExtension - the device object for the disk.
968 Geometry - a structure to save the geometry information into (if any is
973 STATUS_SUCCESS if geometry information can be provided or
974 error status indicating why it can't.
978 PCOMMON_DEVICE_EXTENSION commonExtension
= &(FdoExtension
->CommonExtension
);
980 PIO_STACK_LOCATION irpStack
;
988 // Build an irp to send IOCTL_DISK_GET_DRIVE_GEOMETRY to the lower driver.
991 irp
= IoAllocateIrp(commonExtension
->LowerDeviceObject
->StackSize
, FALSE
);
994 return STATUS_INSUFFICIENT_RESOURCES
;
997 irpStack
= IoGetNextIrpStackLocation(irp
);
999 irpStack
->MajorFunction
= IRP_MJ_DEVICE_CONTROL
;
1001 irpStack
->Parameters
.DeviceIoControl
.IoControlCode
=
1002 IOCTL_DISK_GET_DRIVE_GEOMETRY
;
1003 irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
=
1004 sizeof(DISK_GEOMETRY
);
1006 irp
->AssociatedIrp
.SystemBuffer
= Geometry
;
1008 KeInitializeEvent(&event
, SynchronizationEvent
, FALSE
);
1010 IoSetCompletionRoutine(irp
,
1011 (PIO_COMPLETION_ROUTINE
)ClassSignalCompletion
,
1017 status
= IoCallDriver(commonExtension
->LowerDeviceObject
, irp
);
1018 KeWaitForSingleObject(&event
, Executive
, KernelMode
, FALSE
, NULL
);
1020 ASSERT((status
== STATUS_PENDING
) || (status
== irp
->IoStatus
.Status
));
1021 status
= irp
->IoStatus
.Status
;
1030 DiskReadDriveCapacity(
1031 IN PDEVICE_OBJECT Fdo
1035 Routine Description:
1037 This routine is used by disk.sys as a wrapper for the classpnp API
1038 ClassReadDriveCapacity. It will perform some additional operations to
1039 attempt to determine drive geometry before it calls the classpnp version
1042 For fixed disks this involves calling DiskUpdateGeometry which will check
1043 various sources (the BIOS, the port driver) for geometry information.
1047 Fdo - a pointer to the device object to be checked.
1051 status of ClassReadDriveCapacity.
1056 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
1057 //PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData;
1058 //DISK_GEOMETRY_SOURCE diskGeometrySource = DiskGeometryUnknown;
1063 if (TEST_FLAG(Fdo
->Characteristics
, FILE_REMOVABLE_MEDIA
)) {
1064 DiskUpdateRemovableGeometry(fdoExtension
);
1066 /* diskGeometrySource =*/ DiskUpdateGeometry(fdoExtension
);
1069 status
= ClassReadDriveCapacity(Fdo
);
1076 DiskDriverReinitialization(
1077 IN PDRIVER_OBJECT DriverObject
,
1083 Routine Description:
1085 This routine will scan through the current list of disks and attempt to
1086 match them to any remaining geometry information. This will only be done
1087 on the first call to the routine.
1089 Note: This routine assumes that the system will not be adding or removing
1090 devices during this phase of the init process. This is very likely
1091 a bad assumption but it greatly simplifies the code.
1095 DriverObject - a pointer to the object for the disk driver.
1099 Count - an indication of how many times this routine has been called.
1108 PDEVICE_OBJECT deviceObject
;
1109 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
;
1110 PDISK_DATA diskData
;
1112 ULONG unmatchedDiskCount
;
1113 PDEVICE_OBJECT unmatchedDisk
= NULL
;
1116 PDISK_DETECT_INFO diskInfo
= NULL
;
1119 DebugPrint((1, "DiskDriverReinitialization: ignoring call %d\n",
1125 // Check to see how many entries in the detect info list have been matched.
1126 // If there's only one remaining we'll see if we can find a disk to go with
1130 if(DetectInfoCount
== 0) {
1131 DebugPrint((1, "DiskDriverReinitialization: no detect info saved\n"));
1135 if((DetectInfoCount
- DetectInfoUsedCount
) != 1) {
1136 DebugPrint((1, "DiskDriverReinitialization: %d of %d geometry entries "
1137 "used - will not attempt match\n"));
1142 // Scan through the list of disks and see if any of them are missing
1143 // geometry information. If there is only one such disk we'll try to
1144 // match it to the unmatched geometry.
1149 // ISSUE-2000/5/24-henrygab - figure out if there's a way to keep
1150 // removals from happening while doing this.
1153 for(deviceObject
= DriverObject
->DeviceObject
, unmatchedDiskCount
= 0;
1154 deviceObject
!= NULL
;
1155 deviceObject
= deviceObject
->NextDevice
) {
1158 // Make sure this is a disk and not a partition.
1161 fdoExtension
= deviceObject
->DeviceExtension
;
1162 if(fdoExtension
->CommonExtension
.IsFdo
== FALSE
) {
1163 DebugPrint((1, "DiskDriverReinit: DO %#p is not an FDO\n",
1169 // If the geometry for this one is already known then skip it.
1172 diskData
= fdoExtension
->CommonExtension
.DriverData
;
1173 if(diskData
->GeometrySource
!= DiskGeometryUnknown
) {
1174 DebugPrint((1, "DiskDriverReinit: FDO %#p has a geometry\n",
1179 DebugPrint((1, "DiskDriverReinit: FDO %#p has no geometry\n",
1183 // Mark this one as using the default. It's past the time when disk
1184 // might blunder across the geometry info. If we set the geometry
1185 // from the bios we'll reset this field down below.
1188 diskData
->GeometrySource
= DiskGeometryFromDefault
;
1191 // As long as we've only got one unmatched disk we're fine.
1194 unmatchedDiskCount
++;
1195 if(unmatchedDiskCount
> 1) {
1196 ASSERT(unmatchedDisk
!= NULL
);
1197 DebugPrint((1, "DiskDriverReinit: FDO %#p also has no geometry\n",
1199 unmatchedDisk
= NULL
;
1203 unmatchedDisk
= deviceObject
;
1207 // If there's more or less than one ungeometried disk then we can't do
1208 // anything about the geometry.
1211 if(unmatchedDiskCount
!= 1) {
1212 DebugPrint((1, "DiskDriverReinit: Unable to match geometry\n"));
1217 fdoExtension
= unmatchedDisk
->DeviceExtension
;
1218 diskData
= fdoExtension
->CommonExtension
.DriverData
;
1220 DebugPrint((1, "DiskDriverReinit: Found possible match\n"));
1223 // Find the geometry which wasn't assigned.
1226 for(i
= 0; i
< DetectInfoCount
; i
++) {
1227 if(DetectInfoList
[i
].Device
== NULL
) {
1228 diskInfo
= &(DetectInfoList
[i
]);
1233 ASSERT(diskInfo
!= NULL
);
1237 // Save the geometry information away in the disk data block and
1238 // set the bit indicating that we found a valid one.
1242 ULONG sectorsPerTrack
;
1243 ULONG tracksPerCylinder
;
1249 // Point to the array of drive parameters.
1252 cylinders
= diskInfo
->DriveParameters
.MaxCylinders
+ 1;
1253 sectorsPerTrack
= diskInfo
->DriveParameters
.SectorsPerTrack
;
1254 tracksPerCylinder
= diskInfo
->DriveParameters
.MaxHeads
+ 1;
1257 // Since the BIOS may not report the full drive, recalculate the drive
1258 // size based on the volume size and the BIOS values for tracks per
1259 // cylinder and sectors per track..
1262 length
= tracksPerCylinder
* sectorsPerTrack
;
1267 // The BIOS information is bogus.
1270 DebugPrint((1, "DiskDriverReinit: H (%d) or S(%d) is zero\n",
1271 tracksPerCylinder
, sectorsPerTrack
));
1276 // since we are copying the structure RealGeometry here, we should
1277 // really initialize all the fields, especially since a zero'd
1278 // BytesPerSector field would cause a trap in xHalReadPartitionTable()
1281 diskData
->RealGeometry
= fdoExtension
->DiskGeometry
;
1284 // Save the geometry information away in the disk data block and
1285 // set the bit indicating that we found a valid one.
1288 diskData
->RealGeometry
.SectorsPerTrack
= sectorsPerTrack
;
1289 diskData
->RealGeometry
.TracksPerCylinder
= tracksPerCylinder
;
1290 diskData
->RealGeometry
.Cylinders
.QuadPart
= (LONGLONG
)cylinders
;
1292 DebugPrint((1, "DiskDriverReinit: BIOS spt %#x, #heads %#x, "
1294 sectorsPerTrack
, tracksPerCylinder
, cylinders
));
1296 diskData
->GeometrySource
= DiskGeometryGuessedFromBios
;
1297 diskInfo
->Device
= unmatchedDisk
;
1300 // Now copy the geometry over to the fdo extension and call
1301 // classpnp to redetermine the disk size and cylinder count.
1304 fdoExtension
->DiskGeometry
= diskData
->RealGeometry
;
1307 // BUGBUG - why not call DiskReadDriveCapacity()?
1310 ClassReadDriveCapacity(unmatchedDisk
);
1312 if (diskData
->RealGeometry
.BytesPerSector
== 0) {
1315 // if the BytesPerSector field is set to zero for a disk
1316 // listed in the bios, then the system will bugcheck in
1317 // xHalReadPartitionTable(). assert here since it is
1318 // easier to determine what is happening this way.
1321 ASSERT(!"RealGeometry not set to non-zero bps\n");
1331 IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
,
1332 OUT PDISK_DETECTION_INFO DetectInfo
1336 Routine Description:
1338 Get the Int13 information from the BIOS DetectInfoList.
1342 FdoExtension - Supplies a pointer to the FDO extension that we want to
1343 obtain the detect information for.
1345 DetectInfo - A buffer where the detect information will be copied to.
1355 PDISK_DETECT_INFO diskInfo
= NULL
;
1356 PDISK_DATA diskData
= FdoExtension
->CommonExtension
.DriverData
;
1360 ASSERT(FdoExtension
->CommonExtension
.IsFdo
);
1363 // Fail for non-fixed drives.
1366 if (TEST_FLAG (FdoExtension
->DeviceObject
->Characteristics
, FILE_REMOVABLE_MEDIA
)) {
1367 return STATUS_NOT_SUPPORTED
;
1371 // There is no GPT detection info, so fail this.
1374 if (diskData
->PartitionStyle
== PARTITION_STYLE_GPT
) {
1375 return STATUS_NOT_SUPPORTED
;
1378 for(i
= 0; i
< DetectInfoCount
; i
++) {
1381 ASSERT(DetectInfoList
!= NULL
);
1383 diskInfo
= &(DetectInfoList
[i
]);
1385 if((diskData
->Mbr
.Signature
!= 0) &&
1386 (diskData
->Mbr
.Signature
== diskInfo
->Signature
)) {
1387 DebugPrint((1, "DiskGetDetectInfo: found match for signature "
1389 diskData
->Mbr
.Signature
));
1392 } else if((diskData
->Mbr
.Signature
== 0) &&
1393 (diskData
->Mbr
.MbrCheckSum
!= 0) &&
1394 (diskData
->Mbr
.MbrCheckSum
== diskInfo
->MbrCheckSum
)) {
1395 DebugPrint((1, "DiskGetDetectInfo: found match for xsum %#08lx\n",
1396 diskData
->Mbr
.MbrCheckSum
));
1403 DetectInfo
->DetectionType
= DetectInt13
;
1404 DetectInfo
->Int13
.DriveSelect
= diskInfo
->DriveParameters
.DriveSelect
;
1405 DetectInfo
->Int13
.MaxCylinders
= diskInfo
->DriveParameters
.MaxCylinders
;
1406 DetectInfo
->Int13
.SectorsPerTrack
= diskInfo
->DriveParameters
.SectorsPerTrack
;
1407 DetectInfo
->Int13
.MaxHeads
= diskInfo
->DriveParameters
.MaxHeads
;
1408 DetectInfo
->Int13
.NumberDrives
= diskInfo
->DriveParameters
.NumberDrives
;
1409 RtlZeroMemory (&DetectInfo
->ExInt13
, sizeof (DetectInfo
->ExInt13
));
1412 return (found
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
1418 IN PDEVICE_OBJECT Fdo
1423 Routine Description:
1425 Read the disks signature from the drive. The signature can be either
1426 a MBR signature or a GPT/EFI signature.
1428 The low-level signature reading is done by IoReadDiskSignature().
1432 Fdo - Pointer to the FDO of a disk to read the signature for.
1443 PFUNCTIONAL_DEVICE_EXTENSION fdoExtension
= Fdo
->DeviceExtension
;
1444 PDISK_DATA diskData
= fdoExtension
->CommonExtension
.DriverData
;
1445 DISK_SIGNATURE Signature
;
1449 Status
= IoReadDiskSignature (Fdo
,
1450 fdoExtension
->DiskGeometry
.BytesPerSector
,
1453 if (!NT_SUCCESS (Status
)) {
1457 if (Signature
.PartitionStyle
== PARTITION_STYLE_GPT
) {
1458 diskData
->PartitionStyle
= PARTITION_STYLE_GPT
;
1459 diskData
->Efi
.DiskId
= Signature
.Gpt
.DiskId
;
1460 } else if (Signature
.PartitionStyle
== PARTITION_STYLE_MBR
) {
1461 diskData
->PartitionStyle
= PARTITION_STYLE_MBR
;
1462 diskData
->Mbr
.Signature
= Signature
.Mbr
.Signature
;
1463 diskData
->Mbr
.MbrCheckSum
= Signature
.Mbr
.CheckSum
;
1466 Status
= STATUS_UNSUCCESSFUL
;
1472 #endif // defined(_X86_)