3 * Copyright (C) 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/storage/disk/disk.c
24 * PURPOSE: disk class driver
25 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
28 /* INCLUDES *****************************************************************/
30 #include <ddk/ntddk.h>
32 #include <ddk/class2.h>
33 #include <ddk/ntddscsi.h>
38 #define VERSION "0.0.1"
41 typedef struct _DISK_DATA
43 PDEVICE_EXTENSION NextPartition;
47 ULONG PartitionNumber;
48 ULONG PartitionOrdinal;
50 BOOLEAN BootIndicator;
51 BOOLEAN DriveNotReady;
52 } DISK_DATA, *PDISK_DATA;
56 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
57 PUNICODE_STRING RegistryPath,
58 PCLASS_INIT_DATA InitializationData,
59 PDEVICE_OBJECT PortDeviceObject,
63 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData);
66 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
71 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
72 IN PUNICODE_STRING RegistryPath, /* what's this used for? */
73 IN PDEVICE_OBJECT PortDeviceObject,
76 IN PIO_SCSI_CAPABILITIES Capabilities,
77 IN PSCSI_INQUIRY_DATA InquiryData,
78 IN PCLASS_INIT_DATA InitializationData);
81 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
85 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
89 ScsiDiskSearchForDisk(IN PDEVICE_EXTENSION DeviceExtension,
91 OUT PULONG DetectedDiskNumber);
94 DiskClassUpdatePartitionDeviceObjects (IN PDEVICE_OBJECT DeviceObject,
98 ScsiDiskUpdateFixedDiskGeometry(IN PDEVICE_EXTENSION DeviceExtension);
101 ScsiDiskCalcMbrCheckSum(IN PDEVICE_EXTENSION DeviceExtension,
102 OUT PULONG Checksum);
105 /* FUNCTIONS ****************************************************************/
107 /**********************************************************************
112 * This function initializes the driver, locates and claims
113 * hardware resources, and creates various NT objects needed
114 * to process I/O requests.
121 * System allocated Driver Object for this driver
124 * Name of registry driver service key
131 DriverEntry(IN PDRIVER_OBJECT DriverObject,
132 IN PUNICODE_STRING RegistryPath)
134 CLASS_INIT_DATA InitData;
136 DPRINT("Disk Class Driver %s\n",
138 DPRINT("RegistryPath '%wZ'\n",
141 RtlZeroMemory(&InitData,
142 sizeof(CLASS_INIT_DATA));
144 InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
145 InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA);
146 InitData.DeviceType = FILE_DEVICE_DISK;
147 InitData.DeviceCharacteristics = 0;
149 InitData.ClassError = NULL; // DiskClassProcessError;
150 InitData.ClassReadWriteVerification = DiskClassCheckReadWrite;
151 InitData.ClassFindDeviceCallBack = DiskClassCheckDevice;
152 InitData.ClassFindDevices = DiskClassFindDevices;
153 InitData.ClassDeviceControl = DiskClassDeviceControl;
154 InitData.ClassShutdownFlush = DiskClassShutdownFlush;
155 InitData.ClassCreateClose = NULL;
156 InitData.ClassStartIo = NULL;
158 return(ScsiClassInitialize(DriverObject,
164 /**********************************************************************
166 * DiskClassFindDevices
169 * This function searches for device that are attached to the
177 * System allocated Driver Object for this driver
180 * Name of registry driver service key
183 * Pointer to the main initialization data
186 * Pointer to the port Device Object
192 * TRUE: At least one disk drive was found
193 * FALSE: No disk drive found
197 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
198 PUNICODE_STRING RegistryPath,
199 PCLASS_INIT_DATA InitializationData,
200 PDEVICE_OBJECT PortDeviceObject,
203 PCONFIGURATION_INFORMATION ConfigInfo;
204 PIO_SCSI_CAPABILITIES PortCapabilities;
205 PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
206 PSCSI_INQUIRY_DATA UnitInfo;
207 PINQUIRYDATA InquiryData;
214 DPRINT("DiskClassFindDevices() called.\n");
216 /* Get port capabilities */
217 Status = ScsiClassGetCapabilities(PortDeviceObject,
219 if (!NT_SUCCESS(Status))
221 DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status);
225 DPRINT("PortCapabilities: %p\n", PortCapabilities);
226 DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength);
227 DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities->MaximumPhysicalPages);
229 /* Get inquiry data */
230 Status = ScsiClassGetInquiryData(PortDeviceObject,
231 (PSCSI_ADAPTER_BUS_INFO *)&Buffer);
232 if (!NT_SUCCESS(Status))
234 DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status);
238 /* Check whether there are unclaimed devices */
239 AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
240 DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData,
242 if (DeviceCount == 0)
244 DPRINT("No unclaimed devices!\n");
248 DPRINT("Found %lu unclaimed devices!\n", DeviceCount);
250 ConfigInfo = IoGetConfigurationInformation();
252 /* Search each bus of this adapter */
253 for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++)
255 DPRINT("Searching bus %lu\n", Bus);
257 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset);
259 while (AdapterBusInfo->BusData[Bus].InquiryDataOffset)
261 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
263 if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
264 (InquiryData->DeviceType == OPTICAL_DEVICE)) &&
265 (InquiryData->DeviceTypeQualifier == 0) &&
266 (UnitInfo->DeviceClaimed == FALSE))
268 DPRINT("Vendor: '%.24s'\n",
269 InquiryData->VendorId);
271 /* Create device objects for disk */
272 Status = DiskClassCreateDeviceObject(DriverObject,
276 ConfigInfo->DiskCount,
280 if (NT_SUCCESS(Status))
282 ConfigInfo->DiskCount++;
287 if (UnitInfo->NextInquiryDataOffset == 0)
290 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset);
296 DPRINT("DiskClassFindDevices() done\n");
302 /**********************************************************************
304 * DiskClassCheckDevice
307 * This function checks the InquiryData for the correct device
308 * type and qualifier.
315 * Pointer to the inquiry data for the device in question.
318 * TRUE: A disk device was found.
323 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData)
325 return((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE ||
326 InquiryData->DeviceType == OPTICAL_DEVICE) &&
327 InquiryData->DeviceTypeQualifier == 0);
331 /**********************************************************************
333 * DiskClassCheckReadWrite
336 * This function checks the given IRP for correct data.
343 * Pointer to the device.
349 * STATUS_SUCCESS: The IRP matches the requirements of the given device.
354 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
357 PDEVICE_EXTENSION DeviceExtension;
360 DPRINT("DiskClassCheckReadWrite() called\n");
362 DeviceExtension = DeviceObject->DeviceExtension;
363 DiskData = (PDISK_DATA)(DeviceExtension + 1);
365 if (DiskData->DriveNotReady == TRUE)
367 Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
368 IoSetHardErrorOrVerifyDevice(Irp,
370 return(STATUS_INVALID_PARAMETER);
373 return(STATUS_SUCCESS);
377 /**********************************************************************
379 * DiskClassCreateDeviceObject
382 * Create the raw device and any partition devices on this drive
389 * The system created driver object
399 * STATUS_SUCCESS: Device objects for disk and partitions were created.
404 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
405 IN PUNICODE_STRING RegistryPath, /* what's this used for? */
406 IN PDEVICE_OBJECT PortDeviceObject,
409 IN PIO_SCSI_CAPABILITIES Capabilities,
410 IN PSCSI_INQUIRY_DATA InquiryData,
411 IN PCLASS_INIT_DATA InitializationData)
413 OBJECT_ATTRIBUTES ObjectAttributes;
414 UNICODE_STRING UnicodeDeviceDirName;
415 WCHAR NameBuffer[80];
416 CHAR NameBuffer2[80];
417 PDEVICE_OBJECT DiskDeviceObject;
418 PDEVICE_OBJECT PartitionDeviceObject;
419 PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */
420 PDEVICE_EXTENSION PartitionDeviceExtension; /* defined in class2.h */
421 PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
423 PPARTITION_INFORMATION PartitionEntry;
425 ULONG PartitionNumber;
429 DPRINT("DiskClassCreateDeviceObject() called\n");
431 /* Create the harddisk device directory */
433 L"\\Device\\Harddisk%lu",
435 RtlInitUnicodeString(&UnicodeDeviceDirName,
437 InitializeObjectAttributes(&ObjectAttributes,
438 &UnicodeDeviceDirName,
442 Status = ZwCreateDirectoryObject(&Handle,
445 if (!NT_SUCCESS(Status))
447 DbgPrint("Could not create device dir object\n");
451 /* Claim the disk device */
452 Status = ScsiClassClaimDevice(PortDeviceObject,
456 if (!NT_SUCCESS(Status))
458 DbgPrint("Could not claim disk device\n");
460 ZwMakeTemporaryObject(Handle);
466 /* Create disk device (Partition 0) */
468 "\\Device\\Harddisk%lu\\Partition0",
471 Status = ScsiClassCreateDeviceObject(DriverObject,
476 if (!NT_SUCCESS(Status))
478 DPRINT("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status);
480 /* Release (unclaim) the disk */
481 ScsiClassClaimDevice(PortDeviceObject,
486 /* Delete the harddisk device directory */
487 ZwMakeTemporaryObject(Handle);
493 DiskDeviceObject->Flags |= DO_DIRECT_IO;
494 if (((PINQUIRYDATA)InquiryData->InquiryData)->RemovableMedia)
496 DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
498 DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;
500 if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement)
502 DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
505 DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
506 DiskDeviceExtension->LockCount = 0;
507 DiskDeviceExtension->DeviceNumber = DiskNumber;
508 DiskDeviceExtension->DeviceObject = DiskDeviceObject;
509 DiskDeviceExtension->PortDeviceObject = PortDeviceObject;
510 DiskDeviceExtension->PhysicalDevice = DiskDeviceObject;
511 DiskDeviceExtension->PortCapabilities = Capabilities;
512 DiskDeviceExtension->StartingOffset.QuadPart = 0;
513 DiskDeviceExtension->PortNumber = (UCHAR)PortNumber;
514 DiskDeviceExtension->PathId = InquiryData->PathId;
515 DiskDeviceExtension->TargetId = InquiryData->TargetId;
516 DiskDeviceExtension->Lun = InquiryData->Lun;
518 /* Initialize the lookaside list for SRBs */
519 ScsiClassInitializeSrbLookasideList(DiskDeviceExtension,
522 /* zero-out disk data */
523 DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);
524 RtlZeroMemory(DiskData,
527 /* Get disk geometry */
528 DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
529 sizeof(DISK_GEOMETRY));
530 if (DiskDeviceExtension->DiskGeometry == NULL)
532 DPRINT("Failed to allocate geometry buffer!\n");
534 ExDeleteNPagedLookasideList(&DiskDeviceExtension->SrbLookasideListHead);
536 IoDeleteDevice(DiskDeviceObject);
538 /* Release (unclaim) the disk */
539 ScsiClassClaimDevice(PortDeviceObject,
544 /* Delete the harddisk device directory */
545 ZwMakeTemporaryObject(Handle);
548 return(STATUS_INSUFFICIENT_RESOURCES);
551 /* Read the drive's capacity */
552 Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
553 if (!NT_SUCCESS(Status) &&
554 (DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0)
556 DPRINT1("Failed to retrieve drive capacity!\n");
557 return(STATUS_SUCCESS);
561 /* Clear the verify flag for removable media drives. */
562 DiskDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
565 DPRINT("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector);
567 /* Check disk for presence of a disk manager */
568 HalExamineMBR(DiskDeviceObject,
569 DiskDeviceExtension->DiskGeometry->BytesPerSector,
572 if (MbrBuffer != NULL)
574 /* Start disk at sector 63 if the Ontrack Disk Manager was found */
575 DPRINT("Found 'Ontrack Disk Manager'!\n");
577 DiskDeviceExtension->DMSkew = 63;
578 DiskDeviceExtension->DMByteSkew =
579 63 * DiskDeviceExtension->DiskGeometry->BytesPerSector;
580 DiskDeviceExtension->DMActive = TRUE;
582 ExFreePool(MbrBuffer);
586 if ((DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
587 (DiskDeviceExtension->DiskGeometry->MediaType == RemovableMedia))
589 /* Allocate a partition list for a single entry. */
590 PartitionList = ExAllocatePool(NonPagedPool,
591 sizeof(DRIVE_LAYOUT_INFORMATION));
592 if (PartitionList != NULL)
594 RtlZeroMemory(PartitionList,
595 sizeof(DRIVE_LAYOUT_INFORMATION));
596 PartitionList->PartitionCount = 1;
598 DiskData->DriveNotReady = TRUE;
599 Status = STATUS_SUCCESS;
604 /* Read partition table */
605 Status = IoReadPartitionTable(DiskDeviceObject,
606 DiskDeviceExtension->DiskGeometry->BytesPerSector,
610 DPRINT("IoReadPartitionTable(): Status: %lx\n", Status);
612 if ((!NT_SUCCESS(Status) || PartitionList->PartitionCount == 0) &&
613 DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
615 if (!NT_SUCCESS(Status))
617 /* Drive is not ready. */
618 DPRINT("Drive not ready\n");
619 DiskData->DriveNotReady = TRUE;
623 ExFreePool(PartitionList);
626 /* Allocate a partition list for a single entry. */
627 PartitionList = ExAllocatePool(NonPagedPool,
628 sizeof(DRIVE_LAYOUT_INFORMATION));
629 if (PartitionList != NULL)
631 RtlZeroMemory(PartitionList,
632 sizeof(DRIVE_LAYOUT_INFORMATION));
633 PartitionList->PartitionCount = 1;
635 Status = STATUS_SUCCESS;
640 if (NT_SUCCESS(Status))
642 DPRINT("Read partition table!\n");
643 DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount);
645 /* Set disk signature */
646 DiskData->Signature = PartitionList->Signature;
648 /* Calculate MBR checksum if disk got no signature */
649 if (DiskData->Signature == 0)
651 if (!ScsiDiskCalcMbrCheckSum(DiskDeviceExtension,
652 &DiskData->MbrCheckSum))
654 DPRINT("MBR checksum calculation failed for disk %lu\n",
655 DiskDeviceExtension->DeviceNumber);
659 DPRINT("MBR checksum for disk %lu is %lx\n",
660 DiskDeviceExtension->DeviceNumber,
661 DiskData->MbrCheckSum);
666 DPRINT("Signature on disk %lu is %lx\n",
667 DiskDeviceExtension->DeviceNumber,
668 DiskData->Signature);
671 /* Update disk geometry if disk is visible to the BIOS */
672 ScsiDiskUpdateFixedDiskGeometry(DiskDeviceExtension);
674 for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
676 PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];
678 DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
680 PartitionEntry->PartitionNumber,
681 PartitionEntry->BootIndicator,
682 PartitionEntry->PartitionType,
683 PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
684 PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
686 /* Create partition device object */
688 "\\Device\\Harddisk%lu\\Partition%lu",
690 PartitionNumber + 1);
692 Status = ScsiClassCreateDeviceObject(DriverObject,
695 &PartitionDeviceObject,
697 DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status);
698 if (NT_SUCCESS(Status))
700 PartitionDeviceObject->Flags = DiskDeviceObject->Flags;
701 PartitionDeviceObject->Characteristics = DiskDeviceObject->Characteristics;
702 PartitionDeviceObject->StackSize = DiskDeviceObject->StackSize;
703 PartitionDeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
705 PartitionDeviceExtension = PartitionDeviceObject->DeviceExtension;
706 PartitionDeviceExtension->LockCount = 0;
707 PartitionDeviceExtension->DeviceNumber = DiskNumber;
708 PartitionDeviceExtension->DeviceObject = PartitionDeviceObject;
709 PartitionDeviceExtension->PortDeviceObject = PortDeviceObject;
710 PartitionDeviceExtension->DiskGeometry = DiskDeviceExtension->DiskGeometry;
711 PartitionDeviceExtension->PhysicalDevice = DiskDeviceExtension->PhysicalDevice;
712 PartitionDeviceExtension->PortCapabilities = Capabilities;
713 PartitionDeviceExtension->StartingOffset.QuadPart =
714 PartitionEntry->StartingOffset.QuadPart;
715 PartitionDeviceExtension->PartitionLength.QuadPart =
716 PartitionEntry->PartitionLength.QuadPart;
717 PartitionDeviceExtension->DMSkew = DiskDeviceExtension->DMSkew;
718 PartitionDeviceExtension->DMByteSkew = DiskDeviceExtension->DMByteSkew;
719 PartitionDeviceExtension->DMActive = DiskDeviceExtension->DMActive;
720 PartitionDeviceExtension->PortNumber = (UCHAR)PortNumber;
721 PartitionDeviceExtension->PathId = InquiryData->PathId;
722 PartitionDeviceExtension->TargetId = InquiryData->TargetId;
723 PartitionDeviceExtension->Lun = InquiryData->Lun;
724 PartitionDeviceExtension->SectorShift = DiskDeviceExtension->SectorShift;
726 /* Initialize lookaside list for SRBs */
727 ScsiClassInitializeSrbLookasideList(PartitionDeviceExtension,
730 /* Link current partition device extension to previous disk data */
731 DiskData->NextPartition = PartitionDeviceExtension;
733 /* Initialize current disk data */
734 DiskData = (PDISK_DATA)(PartitionDeviceExtension + 1);
735 DiskData->NextPartition = NULL;
736 DiskData->PartitionType = PartitionEntry->PartitionType;
737 DiskData->PartitionNumber = PartitionNumber + 1;
738 DiskData->PartitionOrdinal = PartitionNumber + 1;
739 DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
740 DiskData->BootIndicator = PartitionEntry->BootIndicator;
741 DiskData->DriveNotReady = FALSE;
745 DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status);
752 if (PartitionList != NULL)
753 ExFreePool(PartitionList);
755 DPRINT("DiskClassCreateDeviceObjects() done\n");
757 return(STATUS_SUCCESS);
761 /**********************************************************************
763 * DiskClassDeviceControl
766 * Answer requests for device control calls
772 * Standard dispatch arguments
779 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
782 PDEVICE_EXTENSION DeviceExtension;
783 PIO_STACK_LOCATION IrpStack;
784 ULONG ControlCode, InputLength, OutputLength;
789 DPRINT("DiskClassDeviceControl() called!\n");
791 Status = STATUS_INVALID_DEVICE_REQUEST;
793 IrpStack = IoGetCurrentIrpStackLocation(Irp);
794 ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
795 InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
796 OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
797 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
798 DiskData = (PDISK_DATA)(DeviceExtension + 1);
802 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
803 DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
804 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
806 Status = STATUS_INVALID_PARAMETER;
810 PDISK_GEOMETRY Geometry;
812 if (DeviceExtension->DiskGeometry == NULL)
814 DPRINT("No disk geometry available!\n");
815 DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
816 sizeof(DISK_GEOMETRY));
818 Status = ScsiClassReadDriveCapacity(DeviceObject);
819 DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status);
820 if (NT_SUCCESS(Status))
822 Geometry = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer;
823 RtlMoveMemory(Geometry,
824 DeviceExtension->DiskGeometry,
825 sizeof(DISK_GEOMETRY));
827 Status = STATUS_SUCCESS;
828 Information = sizeof(DISK_GEOMETRY);
833 case IOCTL_DISK_GET_PARTITION_INFO:
834 DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n");
835 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
836 sizeof(PARTITION_INFORMATION))
838 Status = STATUS_INFO_LENGTH_MISMATCH;
840 else if (DiskData->PartitionNumber == 0)
842 Status = STATUS_INVALID_DEVICE_REQUEST;
846 PPARTITION_INFORMATION PartitionInfo;
848 PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
850 PartitionInfo->PartitionType = DiskData->PartitionType;
851 PartitionInfo->StartingOffset = DeviceExtension->StartingOffset;
852 PartitionInfo->PartitionLength = DeviceExtension->PartitionLength;
853 PartitionInfo->HiddenSectors = DiskData->HiddenSectors;
854 PartitionInfo->PartitionNumber = DiskData->PartitionNumber;
855 PartitionInfo->BootIndicator = DiskData->BootIndicator;
856 PartitionInfo->RewritePartition = FALSE;
857 PartitionInfo->RecognizedPartition =
858 IsRecognizedPartition(DiskData->PartitionType);
860 Status = STATUS_SUCCESS;
861 Information = sizeof(PARTITION_INFORMATION);
865 case IOCTL_DISK_SET_PARTITION_INFO:
866 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
867 sizeof(SET_PARTITION_INFORMATION))
869 Status = STATUS_INFO_LENGTH_MISMATCH;
871 else if (DiskData->PartitionNumber == 0)
873 Status = STATUS_INVALID_DEVICE_REQUEST;
877 PSET_PARTITION_INFORMATION PartitionInfo;
879 PartitionInfo = (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
881 Status = IoSetPartitionInformation(DeviceExtension->PhysicalDevice,
882 DeviceExtension->DiskGeometry->BytesPerSector,
883 DiskData->PartitionOrdinal,
884 PartitionInfo->PartitionType);
885 if (NT_SUCCESS(Status))
887 DiskData->PartitionType = PartitionInfo->PartitionType;
892 case IOCTL_DISK_GET_DRIVE_LAYOUT:
893 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
894 sizeof(DRIVE_LAYOUT_INFORMATION))
896 Status = STATUS_BUFFER_TOO_SMALL;
900 PDRIVE_LAYOUT_INFORMATION PartitionList;
902 Status = IoReadPartitionTable(DeviceExtension->PhysicalDevice,
903 DeviceExtension->DiskGeometry->BytesPerSector,
906 if (NT_SUCCESS(Status))
910 BufferSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,
912 BufferSize += PartitionList->PartitionCount * sizeof(PARTITION_INFORMATION);
914 if (BufferSize > IrpStack->Parameters.DeviceIoControl.OutputBufferLength)
916 Status = STATUS_BUFFER_TOO_SMALL;
920 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
923 Status = STATUS_SUCCESS;
924 Information = BufferSize;
926 ExFreePool(PartitionList);
931 case IOCTL_DISK_SET_DRIVE_LAYOUT:
932 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
933 sizeof(DRIVE_LAYOUT_INFORMATION))
935 Status = STATUS_INFO_LENGTH_MISMATCH;
937 else if (DeviceExtension->PhysicalDevice->DeviceExtension != DeviceExtension)
939 Status = STATUS_INVALID_PARAMETER;
943 PDRIVE_LAYOUT_INFORMATION PartitionList;
946 PartitionList = Irp->AssociatedIrp.SystemBuffer;
947 TableSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
948 ((PartitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
950 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < TableSize)
952 Status = STATUS_BUFFER_TOO_SMALL;
956 /* Update partition device objects */
957 DiskClassUpdatePartitionDeviceObjects (DeviceObject,
960 /* Write partition table */
961 Status = IoWritePartitionTable(DeviceExtension->PhysicalDevice,
962 DeviceExtension->DiskGeometry->BytesPerSector,
963 DeviceExtension->DiskGeometry->SectorsPerTrack,
964 DeviceExtension->DiskGeometry->TracksPerCylinder,
966 if (NT_SUCCESS(Status))
968 Information = TableSize;
974 case IOCTL_DISK_VERIFY:
975 case IOCTL_DISK_FORMAT_TRACKS:
976 case IOCTL_DISK_PERFORMANCE:
977 case IOCTL_DISK_IS_WRITABLE:
978 case IOCTL_DISK_LOGGING:
979 case IOCTL_DISK_FORMAT_TRACKS_EX:
980 case IOCTL_DISK_HISTOGRAM_STRUCTURE:
981 case IOCTL_DISK_HISTOGRAM_DATA:
982 case IOCTL_DISK_HISTOGRAM_RESET:
983 case IOCTL_DISK_REQUEST_STRUCTURE:
984 case IOCTL_DISK_REQUEST_DATA:
985 /* If we get here, something went wrong. Inform the requestor */
986 DPRINT1("Unhandled control code: %lx\n", ControlCode);
987 Status = STATUS_INVALID_DEVICE_REQUEST;
992 /* Call the common device control function */
993 return(ScsiClassDeviceControl(DeviceObject, Irp));
996 /* Verify the device if the user caused the error */
997 if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status))
999 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
1002 Irp->IoStatus.Status = Status;
1003 Irp->IoStatus.Information = Information;
1004 IoCompleteRequest(Irp,
1011 /**********************************************************************
1013 * DiskClassShutdownFlush
1016 * Answer requests for shutdown and flush calls.
1023 * Pointer to the device.
1026 * Pointer to the IRP
1033 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
1036 PDEVICE_EXTENSION DeviceExtension;
1037 PIO_STACK_LOCATION IrpStack;
1038 PSCSI_REQUEST_BLOCK Srb;
1040 DPRINT("DiskClassShutdownFlush() called!\n");
1042 DeviceExtension = DeviceObject->DeviceExtension;
1045 Srb = ExAllocatePool(NonPagedPool,
1046 sizeof(SCSI_REQUEST_BLOCK));
1049 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1050 Irp->IoStatus.Information = 0;
1051 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1053 return(STATUS_INSUFFICIENT_RESOURCES);
1056 /* Initialize SRB */
1057 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
1058 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
1060 /* Set device IDs */
1061 Srb->PathId = DeviceExtension->PathId;
1062 Srb->TargetId = DeviceExtension->TargetId;
1063 Srb->Lun = DeviceExtension->Lun;
1065 /* Flush write cache */
1066 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1067 Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
1068 Srb->CdbLength = 10;
1069 Srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
1070 ScsiClassSendSrbSynchronous(DeviceObject,
1076 /* Get current stack location */
1077 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1079 /* FIXME: Unlock removable media upon shutdown */
1083 IrpStack->Parameters.Others.Argument4 = (PVOID)0;
1085 /* Send shutdown or flush request to the port driver */
1087 if (IrpStack->MajorFunction == IRP_MJ_SHUTDOWN)
1088 Srb->Function = SRB_FUNCTION_SHUTDOWN;
1090 Srb->Function = SRB_FUNCTION_FLUSH;
1092 /* Init completion routine */
1093 IoSetCompletionRoutine(Irp,
1094 ScsiClassIoComplete,
1100 /* Prepare next stack location for a call to the port driver */
1101 IrpStack = IoGetNextIrpStackLocation(Irp);
1102 IrpStack->MajorFunction = IRP_MJ_SCSI;
1103 IrpStack->Parameters.Scsi.Srb = Srb;
1104 Srb->OriginalRequest = Irp;
1106 /* Call port driver */
1107 return(IoCallDriver(DeviceExtension->PortDeviceObject, Irp));
1111 /**********************************************************************
1113 * DiskClassUpdatePartitionDeviceObjects
1116 * Deletes, modifies or creates partition device objects.
1123 * Pointer to the device.
1126 * Pointer to the IRP
1133 DiskClassUpdatePartitionDeviceObjects(IN PDEVICE_OBJECT DiskDeviceObject,
1136 PDRIVE_LAYOUT_INFORMATION PartitionList;
1137 PPARTITION_INFORMATION PartitionEntry;
1138 PDEVICE_EXTENSION DeviceExtension;
1139 PDEVICE_EXTENSION DiskDeviceExtension;
1140 PDISK_DATA DiskData;
1141 ULONG PartitionCount;
1142 ULONG PartitionOrdinal;
1143 ULONG PartitionNumber;
1144 ULONG LastPartitionNumber;
1147 WCHAR NameBuffer[MAX_PATH];
1148 UNICODE_STRING DeviceName;
1149 PDEVICE_OBJECT DeviceObject;
1152 DPRINT("ScsiDiskUpdatePartitionDeviceObjects() called\n");
1154 /* Get partition list */
1155 PartitionList = Irp->AssociatedIrp.SystemBuffer;
1157 /* Round partition count up by 4 */
1158 PartitionCount = ((PartitionList->PartitionCount + 3) / 4) * 4;
1160 /* Remove the partition numbers from the partition list */
1161 for (i = 0; i < PartitionCount; i++)
1163 PartitionList->PartitionEntry[i].PartitionNumber = 0;
1166 DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
1168 /* Traverse on-disk partition list */
1169 LastPartitionNumber = 0;
1170 DeviceExtension = DiskDeviceExtension;
1171 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1174 DeviceExtension = DiskData->NextPartition;
1175 if (DeviceExtension == NULL)
1179 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1181 /* Update last partition number */
1182 if (DiskData->PartitionNumber > LastPartitionNumber)
1183 LastPartitionNumber = DiskData->PartitionNumber;
1185 /* Ignore unused on-disk partitions */
1186 if (DeviceExtension->PartitionLength.QuadPart == 0ULL)
1190 PartitionOrdinal = 0;
1191 for (i = 0; i < PartitionCount; i++)
1193 /* Get current partition entry */
1194 PartitionEntry = &PartitionList->PartitionEntry[i];
1196 /* Ignore empty (aka unused) or extended partitions */
1197 if (PartitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
1198 IsContainerPartition (PartitionEntry->PartitionType))
1203 /* Check for matching partition start offset and length */
1204 if ((PartitionEntry->StartingOffset.QuadPart !=
1205 DeviceExtension->StartingOffset.QuadPart) ||
1206 (PartitionEntry->PartitionLength.QuadPart !=
1207 DeviceExtension->PartitionLength.QuadPart))
1210 DPRINT1("Found matching partition entry for partition %lu\n",
1211 DiskData->PartitionNumber);
1213 /* Found matching partition */
1216 /* Update partition number in partition list */
1217 PartitionEntry->PartitionNumber = DiskData->PartitionNumber;
1223 /* Get disk data for current partition */
1224 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1226 /* Update partition type if partiton will be rewritten */
1227 if (PartitionEntry->RewritePartition == TRUE)
1228 DiskData->PartitionType = PartitionEntry->PartitionType;
1230 /* Assign new partiton ordinal */
1231 DiskData->PartitionOrdinal = PartitionOrdinal;
1233 DPRINT("Partition ordinal %lu was assigned to partition %lu\n",
1234 DiskData->PartitionOrdinal,
1235 DiskData->PartitionNumber);
1239 /* Delete this partition */
1240 DeviceExtension->PartitionLength.QuadPart = 0ULL;
1242 DPRINT("Deleting partition %lu\n",
1243 DiskData->PartitionNumber);
1247 /* Traverse partiton list and create new partiton devices */
1248 PartitionOrdinal = 0;
1249 for (i = 0; i < PartitionCount; i++)
1251 /* Get current partition entry */
1252 PartitionEntry = &PartitionList->PartitionEntry[i];
1254 /* Ignore empty (aka unused) or extended partitions */
1255 if (PartitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
1256 IsContainerPartition (PartitionEntry->PartitionType))
1261 /* Ignore unchanged partition entries */
1262 if (PartitionEntry->RewritePartition == FALSE)
1265 /* Check for an unused device object */
1266 PartitionNumber = 0;
1267 DeviceExtension = DiskDeviceExtension;
1268 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1271 DeviceExtension = DiskData->NextPartition;
1272 if (DeviceExtension == NULL)
1275 /* Get partition disk data */
1276 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1278 /* Found a free (unused) partition (device object) */
1279 if (DeviceExtension->PartitionLength.QuadPart == 0ULL)
1281 PartitionNumber = DiskData->PartitionNumber;
1286 if (PartitionNumber == 0)
1288 /* Create a new partition device object */
1289 DPRINT("Create new partition device object\n");
1291 /* Get new partiton number */
1292 LastPartitionNumber++;
1293 PartitionNumber = LastPartitionNumber;
1295 /* Create partition device object */
1296 swprintf(NameBuffer,
1297 L"\\Device\\Harddisk%lu\\Partition%lu",
1298 DiskDeviceExtension->DeviceNumber,
1300 RtlInitUnicodeString(&DeviceName,
1303 Status = IoCreateDevice(DiskDeviceObject->DriverObject,
1304 sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA),
1310 if (!NT_SUCCESS(Status))
1312 DPRINT1("IoCreateDevice() failed (Status %lx)\n", Status);
1316 DeviceObject->Flags |= DO_DIRECT_IO;
1317 DeviceObject->StackSize = DiskDeviceObject->StackSize;
1318 DeviceObject->Characteristics = DiskDeviceObject->Characteristics;
1319 DeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
1321 /* Initialize device extension */
1322 DeviceExtension = DeviceObject->DeviceExtension;
1323 RtlCopyMemory(DeviceExtension,
1324 DiskDeviceObject->DeviceExtension,
1325 sizeof(DEVICE_EXTENSION));
1326 DeviceExtension->DeviceObject = DeviceObject;
1328 /* Initialize lookaside list for SRBs */
1329 ScsiClassInitializeSrbLookasideList(DeviceExtension,
1332 /* Link current partition device extension to previous disk data */
1333 DiskData->NextPartition = DeviceExtension;
1334 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1335 DiskData->NextPartition = NULL;
1339 /* Reuse an existing partition device object */
1340 DPRINT("Reuse an exisiting partition device object\n");
1341 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1344 /* Update partition data and device extension */
1345 DiskData->PartitionNumber = PartitionNumber;
1346 DiskData->PartitionOrdinal = PartitionOrdinal;
1347 DiskData->PartitionType = PartitionEntry->PartitionType;
1348 DiskData->BootIndicator = PartitionEntry->BootIndicator;
1349 DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
1350 DeviceExtension->StartingOffset = PartitionEntry->StartingOffset;
1351 DeviceExtension->PartitionLength = PartitionEntry->PartitionLength;
1353 /* Update partition number in the partition list */
1354 PartitionEntry->PartitionNumber = PartitionNumber;
1356 DPRINT("Partition ordinal %lu was assigned to partition %lu\n",
1357 DiskData->PartitionOrdinal,
1358 DiskData->PartitionNumber);
1361 DPRINT("ScsiDiskUpdatePartitionDeviceObjects() done\n");
1365 /**********************************************************************
1367 * ScsiDiskSearchForDisk
1370 * Searches the hardware tree for the given disk.
1377 * Disk device extension.
1380 * Handle to the hardware bus key.
1382 * DetectedDiskNumber
1383 * Returned disk number.
1386 * TRUE: Disk was found.
1387 * FALSE: Search failed.
1391 ScsiDiskSearchForDisk(IN PDEVICE_EXTENSION DeviceExtension,
1393 OUT PULONG DetectedDiskNumber)
1395 PKEY_VALUE_FULL_INFORMATION ValueData;
1396 OBJECT_ATTRIBUTES ObjectAttributes;
1397 PDISK_DATA DiskData;
1398 UNICODE_STRING IdentifierString;
1399 UNICODE_STRING NameString;
1400 HANDLE BusInstanceKey;
1401 HANDLE ControllerKey;
1403 HANDLE DiskInstanceKey;
1405 ULONG ControllerNumber;
1412 DPRINT("ScsiDiskSearchForDiskData() called\n");
1416 /* Enumerate buses */
1417 for (BusNumber = 0; ; BusNumber++)
1419 /* Open bus instance subkey */
1424 RtlInitUnicodeString(&NameString,
1427 InitializeObjectAttributes(&ObjectAttributes,
1429 OBJ_CASE_INSENSITIVE,
1433 Status = ZwOpenKey(&BusInstanceKey,
1436 if (!NT_SUCCESS(Status))
1441 /* Open 'DiskController' subkey */
1442 RtlInitUnicodeString(&NameString,
1445 InitializeObjectAttributes(&ObjectAttributes,
1447 OBJ_CASE_INSENSITIVE,
1451 Status = ZwOpenKey(&ControllerKey,
1454 if (!NT_SUCCESS(Status))
1456 ZwClose(BusInstanceKey);
1460 /* Enumerate controllers */
1461 for (ControllerNumber = 0; ; ControllerNumber++)
1463 /* Open 'DiskPeripheral' subkey */
1465 L"%lu\\DiskPeripheral",
1468 RtlInitUnicodeString(&NameString,
1471 InitializeObjectAttributes(&ObjectAttributes,
1473 OBJ_CASE_INSENSITIVE,
1477 Status = ZwOpenKey(&DiskKey,
1480 if (!NT_SUCCESS(Status))
1485 /* Enumerate disks */
1486 for (DiskNumber = 0; ; DiskNumber++)
1488 /* Open disk instance subkey */
1493 RtlInitUnicodeString(&NameString,
1496 InitializeObjectAttributes(&ObjectAttributes,
1498 OBJ_CASE_INSENSITIVE,
1502 Status = ZwOpenKey(&DiskInstanceKey,
1505 if (!NT_SUCCESS(Status))
1510 DPRINT("Found disk key: bus %lu controller %lu disk %lu\n",
1515 /* Allocate data buffer */
1516 ValueData = ExAllocatePool(PagedPool,
1518 if (ValueData == NULL)
1520 ZwClose(DiskInstanceKey);
1524 /* Get the 'Identifier' value */
1525 RtlInitUnicodeString(&NameString,
1527 Status = ZwQueryValueKey(DiskInstanceKey,
1529 KeyValueFullInformation,
1534 ZwClose(DiskInstanceKey);
1535 if (!NT_SUCCESS(Status))
1537 ExFreePool(ValueData);
1541 IdentifierString.Buffer =
1542 (PWSTR)((PUCHAR)ValueData + ValueData->DataOffset);
1543 IdentifierString.Length = (USHORT)ValueData->DataLength - 2;
1544 IdentifierString.MaximumLength = (USHORT)ValueData->DataLength;
1546 DPRINT("DiskIdentifier: %wZ\n",
1549 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1550 if (DiskData->Signature != 0)
1552 /* Comapre disk signature */
1555 DiskData->Signature);
1556 if (!_wcsnicmp(Buffer, &IdentifierString.Buffer[9], 8))
1558 DPRINT("Found disk %lu\n", DiskNumber);
1560 *DetectedDiskNumber = DiskNumber;
1565 /* Comapre mbr checksum */
1568 DiskData->MbrCheckSum);
1569 if (!_wcsnicmp(Buffer, &IdentifierString.Buffer[0], 8))
1571 DPRINT("Found disk %lu\n", DiskNumber);
1573 *DetectedDiskNumber = DiskNumber;
1577 ExFreePool(ValueData);
1579 ZwClose(DiskInstanceKey);
1581 if (DiskFound == TRUE)
1588 ZwClose(ControllerKey);
1589 ZwClose(BusInstanceKey);
1592 DPRINT("ScsiDiskSearchForDisk() done\n");
1598 /**********************************************************************
1600 * DiskClassUpdateFixedDiskGeometry
1603 * Updated the geometry of a disk if the disk can be accessed
1611 * Disk device extension.
1618 ScsiDiskUpdateFixedDiskGeometry(IN PDEVICE_EXTENSION DeviceExtension)
1620 PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor;
1621 PCM_INT13_DRIVE_PARAMETER DriveParameters;
1622 PKEY_VALUE_FULL_INFORMATION ValueBuffer;
1623 OBJECT_ATTRIBUTES ObjectAttributes;
1624 UNICODE_STRING KeyName;
1625 UNICODE_STRING ValueName;
1633 ULONG SectorsPerTrack;
1634 ULONG TracksPerCylinder;
1637 DPRINT("ScsiDiskUpdateFixedDiskGeometry() called\n");
1639 RtlInitUnicodeString(&KeyName,
1640 L"\\Registry\\Machine\\Hardware\\Description\\System");
1642 InitializeObjectAttributes(&ObjectAttributes,
1644 OBJ_CASE_INSENSITIVE,
1648 /* Open the adapter key */
1649 Status = ZwOpenKey(&SystemKey,
1652 if (!NT_SUCCESS(Status))
1654 DPRINT("ZwOpenKey() failed (Status %lx)\n", Status);
1658 /* Allocate value buffer */
1659 ValueBuffer = ExAllocatePool(PagedPool,
1661 if (ValueBuffer == NULL)
1663 DPRINT1("Failed to allocate value buffer\n");
1668 RtlInitUnicodeString(&ValueName,
1669 L"Configuration Data");
1671 /* Query 'Configuration Data' value */
1672 Status = ZwQueryValueKey(SystemKey,
1674 KeyValueFullInformation,
1678 if (!NT_SUCCESS(Status))
1680 DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status);
1681 ExFreePool(ValueBuffer);
1686 /* Open the 'MultifunctionAdapter' subkey */
1687 RtlInitUnicodeString(&KeyName,
1688 L"MultifunctionAdapter");
1690 InitializeObjectAttributes(&ObjectAttributes,
1692 OBJ_CASE_INSENSITIVE,
1696 Status = ZwOpenKey(&BusKey,
1700 if (!NT_SUCCESS(Status))
1702 DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status);
1703 ExFreePool(ValueBuffer);
1707 if (!ScsiDiskSearchForDisk(DeviceExtension, BusKey, &DiskNumber))
1709 DPRINT("ScsiDiskSearchForDisk() failed\n");
1711 ExFreePool(ValueBuffer);
1717 ResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
1718 ((PUCHAR)ValueBuffer + ValueBuffer->DataOffset);
1720 DriveParameters = (PCM_INT13_DRIVE_PARAMETER)
1721 ((PUCHAR)ResourceDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1724 for (i = 0; i< DriveParameters[0].NumberDrives; i++)
1726 DPRINT1("Drive %lu: %lu Cylinders %hu Heads %hu Sectors\n",
1728 DriveParameters[i].MaxCylinders,
1729 DriveParameters[i].MaxHeads,
1730 DriveParameters[i].SectorsPerTrack);
1734 Cylinders = DriveParameters[DiskNumber].MaxCylinders + 1;
1735 TracksPerCylinder = DriveParameters[DiskNumber].MaxHeads +1;
1736 SectorsPerTrack = DriveParameters[DiskNumber].SectorsPerTrack;
1738 DPRINT("BIOS geometry: %lu Cylinders %hu Heads %hu Sectors\n",
1744 (DeviceExtension->PartitionLength.QuadPart >> DeviceExtension->SectorShift);
1746 DPRINT("Physical sectors: %lu\n",
1749 Length = TracksPerCylinder * SectorsPerTrack;
1752 DPRINT1("Invalid track length 0\n");
1753 ExFreePool(ValueBuffer);
1757 Cylinders = Sectors / Length;
1759 DPRINT("Logical geometry: %lu Cylinders %hu Heads %hu Sectors\n",
1764 /* Update the disk geometry */
1765 DeviceExtension->DiskGeometry->SectorsPerTrack = SectorsPerTrack;
1766 DeviceExtension->DiskGeometry->TracksPerCylinder = TracksPerCylinder;
1767 DeviceExtension->DiskGeometry->Cylinders.QuadPart = (ULONGLONG)Cylinders;
1769 if (DeviceExtension->DMActive)
1771 DPRINT1("FIXME: Update geometry with respect to the installed disk manager!\n");
1773 /* FIXME: Update geometry for disk managers */
1777 ExFreePool(ValueBuffer);
1779 DPRINT("ScsiDiskUpdateFixedDiskGeometry() done\n");
1783 /**********************************************************************
1785 * ScsiDiskCalcMbrCheckSum
1788 * Calculates the Checksum from drives MBR.
1795 * Disk device extension.
1798 * Pointer to the caller supplied cecksum variable.
1801 * TRUE: Checksum was calculated.
1802 * FALSE: Calculation failed.
1806 ScsiDiskCalcMbrCheckSum(IN PDEVICE_EXTENSION DeviceExtension,
1807 OUT PULONG Checksum)
1809 IO_STATUS_BLOCK IoStatusBlock;
1810 LARGE_INTEGER SectorOffset;
1819 KeInitializeEvent(&Event,
1823 /* Get the disk sector size */
1824 SectorSize = DeviceExtension->DiskGeometry->BytesPerSector;
1825 if (SectorSize < 512)
1830 /* Allocate MBR buffer */
1831 MbrBuffer = ExAllocatePool(NonPagedPool,
1833 if (MbrBuffer == NULL)
1838 /* Allocate an IRP */
1839 SectorOffset.QuadPart = 0ULL;
1840 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
1841 DeviceExtension->DeviceObject,
1849 ExFreePool(MbrBuffer);
1853 /* Call the miniport driver */
1854 Status = IoCallDriver(DeviceExtension->DeviceObject,
1856 if (Status == STATUS_PENDING)
1858 KeWaitForSingleObject(&Event,
1863 Status = IoStatusBlock.Status;
1866 if (!NT_SUCCESS(Status))
1868 ExFreePool(MbrBuffer);
1872 /* Calculate MBR checksum */
1874 for (i = 0; i < 128; i++)
1876 Sum += MbrBuffer[i];
1878 *Checksum = ~Sum + 1;
1880 ExFreePool(MbrBuffer);