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"
40 #define SCSI_DISK_TIMEOUT 10 /* Default timeout: 10 seconds */
41 #define MODE_DATA_SIZE 192
44 typedef struct _DISK_DATA
46 PDEVICE_EXTENSION NextPartition;
50 ULONG PartitionNumber;
51 ULONG PartitionOrdinal;
53 BOOLEAN BootIndicator;
54 BOOLEAN DriveNotReady;
55 } DISK_DATA, *PDISK_DATA;
59 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
60 PUNICODE_STRING RegistryPath,
61 PCLASS_INIT_DATA InitializationData,
62 PDEVICE_OBJECT PortDeviceObject,
66 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData);
69 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
74 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
75 IN PUNICODE_STRING RegistryPath, /* what's this used for? */
76 IN PDEVICE_OBJECT PortDeviceObject,
79 IN PIO_SCSI_CAPABILITIES Capabilities,
80 IN PSCSI_INQUIRY_DATA InquiryData,
81 IN PCLASS_INIT_DATA InitializationData);
84 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
88 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
92 ScsiDiskSearchForDisk(IN PDEVICE_EXTENSION DeviceExtension,
94 OUT PULONG DetectedDiskNumber);
97 DiskClassUpdatePartitionDeviceObjects (IN PDEVICE_OBJECT DeviceObject,
101 ScsiDiskUpdateFixedDiskGeometry(IN PDEVICE_EXTENSION DeviceExtension);
104 ScsiDiskCalcMbrCheckSum(IN PDEVICE_EXTENSION DeviceExtension,
105 OUT PULONG Checksum);
108 /* FUNCTIONS ****************************************************************/
110 /**********************************************************************
115 * This function initializes the driver, locates and claims
116 * hardware resources, and creates various NT objects needed
117 * to process I/O requests.
124 * System allocated Driver Object for this driver
127 * Name of registry driver service key
134 DriverEntry(IN PDRIVER_OBJECT DriverObject,
135 IN PUNICODE_STRING RegistryPath)
137 CLASS_INIT_DATA InitData;
139 DPRINT("Disk Class Driver %s\n",
141 DPRINT("RegistryPath '%wZ'\n",
144 RtlZeroMemory(&InitData,
145 sizeof(CLASS_INIT_DATA));
147 InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
148 InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA);
149 InitData.DeviceType = FILE_DEVICE_DISK;
150 InitData.DeviceCharacteristics = 0;
152 InitData.ClassError = NULL; // DiskClassProcessError;
153 InitData.ClassReadWriteVerification = DiskClassCheckReadWrite;
154 InitData.ClassFindDeviceCallBack = DiskClassCheckDevice;
155 InitData.ClassFindDevices = DiskClassFindDevices;
156 InitData.ClassDeviceControl = DiskClassDeviceControl;
157 InitData.ClassShutdownFlush = DiskClassShutdownFlush;
158 InitData.ClassCreateClose = NULL;
159 InitData.ClassStartIo = NULL;
161 return(ScsiClassInitialize(DriverObject,
167 /**********************************************************************
169 * DiskClassFindDevices
172 * This function searches for device that are attached to the
180 * System allocated Driver Object for this driver
183 * Name of registry driver service key
186 * Pointer to the main initialization data
189 * Pointer to the port Device Object
195 * TRUE: At least one disk drive was found
196 * FALSE: No disk drive found
200 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
201 PUNICODE_STRING RegistryPath,
202 PCLASS_INIT_DATA InitializationData,
203 PDEVICE_OBJECT PortDeviceObject,
206 PCONFIGURATION_INFORMATION ConfigInfo;
207 PIO_SCSI_CAPABILITIES PortCapabilities;
208 PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
209 PSCSI_INQUIRY_DATA UnitInfo;
210 PINQUIRYDATA InquiryData;
217 DPRINT("DiskClassFindDevices() called.\n");
219 /* Get port capabilities */
220 Status = ScsiClassGetCapabilities(PortDeviceObject,
222 if (!NT_SUCCESS(Status))
224 DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status);
228 DPRINT("PortCapabilities: %p\n", PortCapabilities);
229 DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength);
230 DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities->MaximumPhysicalPages);
232 /* Get inquiry data */
233 Status = ScsiClassGetInquiryData(PortDeviceObject,
234 (PSCSI_ADAPTER_BUS_INFO *)&Buffer);
235 if (!NT_SUCCESS(Status))
237 DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status);
241 /* Check whether there are unclaimed devices */
242 AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
243 DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData,
245 if (DeviceCount == 0)
247 DPRINT("No unclaimed devices!\n");
251 DPRINT("Found %lu unclaimed devices!\n", DeviceCount);
253 ConfigInfo = IoGetConfigurationInformation();
255 /* Search each bus of this adapter */
256 for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++)
258 DPRINT("Searching bus %lu\n", Bus);
260 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset);
262 while (AdapterBusInfo->BusData[Bus].InquiryDataOffset)
264 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
266 DPRINT("Device type %u\n", InquiryData->DeviceType);
268 if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
269 (InquiryData->DeviceType == OPTICAL_DEVICE)) &&
270 (InquiryData->DeviceTypeQualifier == 0) &&
271 (UnitInfo->DeviceClaimed == FALSE))
273 DPRINT("Vendor: '%.24s'\n",
274 InquiryData->VendorId);
276 /* Create device objects for disk */
277 Status = DiskClassCreateDeviceObject(DriverObject,
281 ConfigInfo->DiskCount,
285 if (NT_SUCCESS(Status))
287 ConfigInfo->DiskCount++;
292 if (UnitInfo->NextInquiryDataOffset == 0)
295 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset);
301 DPRINT("DiskClassFindDevices() done\n");
307 /**********************************************************************
309 * DiskClassCheckDevice
312 * This function checks the InquiryData for the correct device
313 * type and qualifier.
320 * Pointer to the inquiry data for the device in question.
323 * TRUE: A disk device was found.
328 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData)
330 return((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE ||
331 InquiryData->DeviceType == OPTICAL_DEVICE) &&
332 InquiryData->DeviceTypeQualifier == 0);
336 /**********************************************************************
338 * DiskClassCheckReadWrite
341 * This function checks the given IRP for correct data.
348 * Pointer to the device.
354 * STATUS_SUCCESS: The IRP matches the requirements of the given device.
359 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
362 PDEVICE_EXTENSION DeviceExtension;
365 DPRINT("DiskClassCheckReadWrite() called\n");
367 DeviceExtension = DeviceObject->DeviceExtension;
368 DiskData = (PDISK_DATA)(DeviceExtension + 1);
370 if (DiskData->DriveNotReady == TRUE)
372 Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
373 IoSetHardErrorOrVerifyDevice(Irp,
375 return(STATUS_INVALID_PARAMETER);
378 return(STATUS_SUCCESS);
382 /**********************************************************************
384 * DiskClassCreateDeviceObject
387 * Create the raw device and any partition devices on this drive
394 * The system created driver object
404 * STATUS_SUCCESS: Device objects for disk and partitions were created.
409 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
410 IN PUNICODE_STRING RegistryPath,
411 IN PDEVICE_OBJECT PortDeviceObject,
414 IN PIO_SCSI_CAPABILITIES Capabilities,
415 IN PSCSI_INQUIRY_DATA InquiryData,
416 IN PCLASS_INIT_DATA InitializationData)
418 OBJECT_ATTRIBUTES ObjectAttributes;
419 UNICODE_STRING UnicodeDeviceDirName;
420 WCHAR NameBuffer[80];
421 CHAR NameBuffer2[80];
422 PDEVICE_OBJECT DiskDeviceObject;
423 PDEVICE_OBJECT PartitionDeviceObject;
424 PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */
425 PDEVICE_EXTENSION PartitionDeviceExtension; /* defined in class2.h */
426 PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
428 PPARTITION_INFORMATION PartitionEntry;
430 ULONG PartitionNumber;
434 DPRINT("DiskClassCreateDeviceObject() called\n");
436 /* Create the harddisk device directory */
438 L"\\Device\\Harddisk%lu",
440 RtlInitUnicodeString(&UnicodeDeviceDirName,
442 InitializeObjectAttributes(&ObjectAttributes,
443 &UnicodeDeviceDirName,
447 Status = ZwCreateDirectoryObject(&Handle,
450 if (!NT_SUCCESS(Status))
452 DbgPrint("Could not create device dir object\n");
456 /* Claim the disk device */
457 Status = ScsiClassClaimDevice(PortDeviceObject,
461 if (!NT_SUCCESS(Status))
463 DbgPrint("Could not claim disk device\n");
465 ZwMakeTemporaryObject(Handle);
471 /* Create disk device (Partition 0) */
473 "\\Device\\Harddisk%lu\\Partition0",
476 Status = ScsiClassCreateDeviceObject(DriverObject,
481 if (!NT_SUCCESS(Status))
483 DPRINT("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status);
485 /* Release (unclaim) the disk */
486 ScsiClassClaimDevice(PortDeviceObject,
491 /* Delete the harddisk device directory */
492 ZwMakeTemporaryObject(Handle);
498 DiskDeviceObject->Flags |= DO_DIRECT_IO;
499 if (((PINQUIRYDATA)InquiryData->InquiryData)->RemovableMedia)
501 DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
503 DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;
505 if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement)
507 DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
510 DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
511 DiskDeviceExtension->LockCount = 0;
512 DiskDeviceExtension->DeviceNumber = DiskNumber;
513 DiskDeviceExtension->DeviceObject = DiskDeviceObject;
514 DiskDeviceExtension->PortDeviceObject = PortDeviceObject;
515 DiskDeviceExtension->PhysicalDevice = DiskDeviceObject;
516 DiskDeviceExtension->PortCapabilities = Capabilities;
517 DiskDeviceExtension->StartingOffset.QuadPart = 0;
518 DiskDeviceExtension->PortNumber = (UCHAR)PortNumber;
519 DiskDeviceExtension->PathId = InquiryData->PathId;
520 DiskDeviceExtension->TargetId = InquiryData->TargetId;
521 DiskDeviceExtension->Lun = InquiryData->Lun;
523 /* Get timeout value */
524 DiskDeviceExtension->TimeOutValue =
525 ScsiClassQueryTimeOutRegistryValue(RegistryPath);
526 if (DiskDeviceExtension->TimeOutValue == 0)
527 DiskDeviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
529 /* Initialize the lookaside list for SRBs */
530 ScsiClassInitializeSrbLookasideList(DiskDeviceExtension,
533 /* zero-out disk data */
534 DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);
535 RtlZeroMemory(DiskData,
538 /* Get disk geometry */
539 DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
540 sizeof(DISK_GEOMETRY));
541 if (DiskDeviceExtension->DiskGeometry == NULL)
543 DPRINT("Failed to allocate geometry buffer!\n");
545 ExDeleteNPagedLookasideList(&DiskDeviceExtension->SrbLookasideListHead);
547 IoDeleteDevice(DiskDeviceObject);
549 /* Release (unclaim) the disk */
550 ScsiClassClaimDevice(PortDeviceObject,
555 /* Delete the harddisk device directory */
556 ZwMakeTemporaryObject(Handle);
559 return(STATUS_INSUFFICIENT_RESOURCES);
562 /* Allocate sense data buffer */
563 DiskDeviceExtension->SenseData = ExAllocatePool(NonPagedPool,
564 sizeof(SENSE_BUFFER_SIZE));
565 if (DiskDeviceExtension->SenseData == NULL)
567 DPRINT("Failed to allocate sense data buffer!\n");
569 ExFreePool (DiskDeviceExtension->DiskGeometry);
571 ExDeleteNPagedLookasideList(&DiskDeviceExtension->SrbLookasideListHead);
573 IoDeleteDevice(DiskDeviceObject);
575 /* Release (unclaim) the disk */
576 ScsiClassClaimDevice(PortDeviceObject,
581 /* Delete the harddisk device directory */
582 ZwMakeTemporaryObject(Handle);
585 return(STATUS_INSUFFICIENT_RESOURCES);
588 /* Read the drive's capacity */
589 Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
590 if (!NT_SUCCESS(Status) &&
591 (DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0)
593 DPRINT1("Failed to retrieve drive capacity!\n");
594 return(STATUS_SUCCESS);
598 /* Clear the verify flag for removable media drives. */
599 DiskDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
602 DPRINT("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector);
604 /* Check disk for presence of a disk manager */
605 HalExamineMBR(DiskDeviceObject,
606 DiskDeviceExtension->DiskGeometry->BytesPerSector,
609 if (MbrBuffer != NULL)
611 /* Start disk at sector 63 if the Ontrack Disk Manager was found */
612 DPRINT("Found 'Ontrack Disk Manager'!\n");
614 DiskDeviceExtension->DMSkew = 63;
615 DiskDeviceExtension->DMByteSkew =
616 63 * DiskDeviceExtension->DiskGeometry->BytesPerSector;
617 DiskDeviceExtension->DMActive = TRUE;
619 ExFreePool(MbrBuffer);
623 if ((DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
624 (DiskDeviceExtension->DiskGeometry->MediaType == RemovableMedia))
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 DiskData->DriveNotReady = TRUE;
636 Status = STATUS_SUCCESS;
641 /* Read partition table */
642 Status = IoReadPartitionTable(DiskDeviceObject,
643 DiskDeviceExtension->DiskGeometry->BytesPerSector,
647 DPRINT("IoReadPartitionTable(): Status: %lx\n", Status);
649 if ((!NT_SUCCESS(Status) || PartitionList->PartitionCount == 0) &&
650 DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
652 if (!NT_SUCCESS(Status))
654 /* Drive is not ready. */
655 DPRINT("Drive not ready\n");
656 DiskData->DriveNotReady = TRUE;
660 ExFreePool(PartitionList);
663 /* Allocate a partition list for a single entry. */
664 PartitionList = ExAllocatePool(NonPagedPool,
665 sizeof(DRIVE_LAYOUT_INFORMATION));
666 if (PartitionList != NULL)
668 RtlZeroMemory(PartitionList,
669 sizeof(DRIVE_LAYOUT_INFORMATION));
670 PartitionList->PartitionCount = 1;
672 Status = STATUS_SUCCESS;
677 if (NT_SUCCESS(Status))
679 DPRINT("Read partition table!\n");
680 DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount);
682 /* Set disk signature */
683 DiskData->Signature = PartitionList->Signature;
685 /* Calculate MBR checksum if disk got no signature */
686 if (DiskData->Signature == 0)
688 if (!ScsiDiskCalcMbrCheckSum(DiskDeviceExtension,
689 &DiskData->MbrCheckSum))
691 DPRINT("MBR checksum calculation failed for disk %lu\n",
692 DiskDeviceExtension->DeviceNumber);
696 DPRINT("MBR checksum for disk %lu is %lx\n",
697 DiskDeviceExtension->DeviceNumber,
698 DiskData->MbrCheckSum);
703 DPRINT("Signature on disk %lu is %lx\n",
704 DiskDeviceExtension->DeviceNumber,
705 DiskData->Signature);
708 /* Update disk geometry if disk is visible to the BIOS */
709 ScsiDiskUpdateFixedDiskGeometry(DiskDeviceExtension);
711 for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
713 PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];
715 DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
717 PartitionEntry->PartitionNumber,
718 PartitionEntry->BootIndicator,
719 PartitionEntry->PartitionType,
720 PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
721 PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
723 /* Create partition device object */
725 "\\Device\\Harddisk%lu\\Partition%lu",
727 PartitionNumber + 1);
729 Status = ScsiClassCreateDeviceObject(DriverObject,
732 &PartitionDeviceObject,
734 DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status);
735 if (NT_SUCCESS(Status))
737 PartitionDeviceObject->Flags = DiskDeviceObject->Flags;
738 PartitionDeviceObject->Characteristics = DiskDeviceObject->Characteristics;
739 PartitionDeviceObject->StackSize = DiskDeviceObject->StackSize;
740 PartitionDeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
742 PartitionDeviceExtension = PartitionDeviceObject->DeviceExtension;
743 PartitionDeviceExtension->SenseData = DiskDeviceExtension->SenseData;
744 PartitionDeviceExtension->LockCount = 0;
745 PartitionDeviceExtension->DeviceNumber = DiskNumber;
746 PartitionDeviceExtension->DeviceObject = PartitionDeviceObject;
747 PartitionDeviceExtension->PortDeviceObject = PortDeviceObject;
748 PartitionDeviceExtension->DiskGeometry = DiskDeviceExtension->DiskGeometry;
749 PartitionDeviceExtension->PhysicalDevice = DiskDeviceExtension->PhysicalDevice;
750 PartitionDeviceExtension->PortCapabilities = Capabilities;
751 PartitionDeviceExtension->StartingOffset.QuadPart =
752 PartitionEntry->StartingOffset.QuadPart;
753 PartitionDeviceExtension->PartitionLength.QuadPart =
754 PartitionEntry->PartitionLength.QuadPart;
755 PartitionDeviceExtension->DMSkew = DiskDeviceExtension->DMSkew;
756 PartitionDeviceExtension->DMByteSkew = DiskDeviceExtension->DMByteSkew;
757 PartitionDeviceExtension->DMActive = DiskDeviceExtension->DMActive;
758 PartitionDeviceExtension->PortNumber = (UCHAR)PortNumber;
759 PartitionDeviceExtension->PathId = InquiryData->PathId;
760 PartitionDeviceExtension->TargetId = InquiryData->TargetId;
761 PartitionDeviceExtension->Lun = InquiryData->Lun;
762 PartitionDeviceExtension->SectorShift = DiskDeviceExtension->SectorShift;
763 PartitionDeviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;
765 /* Initialize lookaside list for SRBs */
766 ScsiClassInitializeSrbLookasideList(PartitionDeviceExtension,
769 /* Link current partition device extension to previous disk data */
770 DiskData->NextPartition = PartitionDeviceExtension;
772 /* Initialize current disk data */
773 DiskData = (PDISK_DATA)(PartitionDeviceExtension + 1);
774 DiskData->NextPartition = NULL;
775 DiskData->PartitionType = PartitionEntry->PartitionType;
776 DiskData->PartitionNumber = PartitionNumber + 1;
777 DiskData->PartitionOrdinal = PartitionNumber + 1;
778 DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
779 DiskData->BootIndicator = PartitionEntry->BootIndicator;
780 DiskData->DriveNotReady = FALSE;
784 DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status);
791 if (PartitionList != NULL)
792 ExFreePool(PartitionList);
794 DPRINT("DiskClassCreateDeviceObjects() done\n");
796 return(STATUS_SUCCESS);
800 /**********************************************************************
802 * DiskClassDeviceControl
805 * Answer requests for device control calls
811 * Standard dispatch arguments
818 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
821 PDEVICE_EXTENSION DeviceExtension;
822 PIO_STACK_LOCATION IrpStack;
823 ULONG ControlCode, InputLength, OutputLength;
828 DPRINT("DiskClassDeviceControl() called!\n");
830 Status = STATUS_INVALID_DEVICE_REQUEST;
832 IrpStack = IoGetCurrentIrpStackLocation(Irp);
833 ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
834 InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
835 OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
836 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
837 DiskData = (PDISK_DATA)(DeviceExtension + 1);
841 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
842 DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
843 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
845 Status = STATUS_INVALID_PARAMETER;
849 if (DeviceExtension->DiskGeometry == NULL)
851 DPRINT("No disk geometry available!\n");
852 DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
853 sizeof(DISK_GEOMETRY));
856 if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
858 Status = ScsiClassReadDriveCapacity(DeviceObject);
859 DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status);
860 if (!NT_SUCCESS(Status))
862 /* Drive is not ready */
863 DiskData->DriveNotReady = FALSE;
868 DiskData->DriveNotReady = FALSE;
871 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
872 DeviceExtension->DiskGeometry,
873 sizeof(DISK_GEOMETRY));
875 Status = STATUS_SUCCESS;
876 Information = sizeof(DISK_GEOMETRY);
879 case IOCTL_DISK_GET_PARTITION_INFO:
880 DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n");
881 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
882 sizeof(PARTITION_INFORMATION))
884 Status = STATUS_INFO_LENGTH_MISMATCH;
886 else if (DiskData->PartitionNumber == 0)
888 Status = STATUS_INVALID_DEVICE_REQUEST;
892 PPARTITION_INFORMATION PartitionInfo;
894 PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
896 PartitionInfo->PartitionType = DiskData->PartitionType;
897 PartitionInfo->StartingOffset = DeviceExtension->StartingOffset;
898 PartitionInfo->PartitionLength = DeviceExtension->PartitionLength;
899 PartitionInfo->HiddenSectors = DiskData->HiddenSectors;
900 PartitionInfo->PartitionNumber = DiskData->PartitionNumber;
901 PartitionInfo->BootIndicator = DiskData->BootIndicator;
902 PartitionInfo->RewritePartition = FALSE;
903 PartitionInfo->RecognizedPartition =
904 IsRecognizedPartition(DiskData->PartitionType);
906 Status = STATUS_SUCCESS;
907 Information = sizeof(PARTITION_INFORMATION);
911 case IOCTL_DISK_SET_PARTITION_INFO:
912 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
913 sizeof(SET_PARTITION_INFORMATION))
915 Status = STATUS_INFO_LENGTH_MISMATCH;
917 else if (DiskData->PartitionNumber == 0)
919 Status = STATUS_INVALID_DEVICE_REQUEST;
923 PSET_PARTITION_INFORMATION PartitionInfo;
925 PartitionInfo = (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
927 Status = IoSetPartitionInformation(DeviceExtension->PhysicalDevice,
928 DeviceExtension->DiskGeometry->BytesPerSector,
929 DiskData->PartitionOrdinal,
930 PartitionInfo->PartitionType);
931 if (NT_SUCCESS(Status))
933 DiskData->PartitionType = PartitionInfo->PartitionType;
938 case IOCTL_DISK_GET_DRIVE_LAYOUT:
939 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
940 sizeof(DRIVE_LAYOUT_INFORMATION))
942 Status = STATUS_BUFFER_TOO_SMALL;
946 PDRIVE_LAYOUT_INFORMATION PartitionList;
948 Status = IoReadPartitionTable(DeviceExtension->PhysicalDevice,
949 DeviceExtension->DiskGeometry->BytesPerSector,
952 if (NT_SUCCESS(Status))
956 BufferSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,
958 BufferSize += PartitionList->PartitionCount * sizeof(PARTITION_INFORMATION);
960 if (BufferSize > IrpStack->Parameters.DeviceIoControl.OutputBufferLength)
962 Status = STATUS_BUFFER_TOO_SMALL;
966 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
969 Status = STATUS_SUCCESS;
970 Information = BufferSize;
972 ExFreePool(PartitionList);
977 case IOCTL_DISK_SET_DRIVE_LAYOUT:
978 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
979 sizeof(DRIVE_LAYOUT_INFORMATION))
981 Status = STATUS_INFO_LENGTH_MISMATCH;
983 else if (DeviceExtension->PhysicalDevice->DeviceExtension != DeviceExtension)
985 Status = STATUS_INVALID_PARAMETER;
989 PDRIVE_LAYOUT_INFORMATION PartitionList;
992 PartitionList = Irp->AssociatedIrp.SystemBuffer;
993 TableSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
994 ((PartitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
996 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < TableSize)
998 Status = STATUS_BUFFER_TOO_SMALL;
1002 /* Update partition device objects */
1003 DiskClassUpdatePartitionDeviceObjects (DeviceObject,
1006 /* Write partition table */
1007 Status = IoWritePartitionTable(DeviceExtension->PhysicalDevice,
1008 DeviceExtension->DiskGeometry->BytesPerSector,
1009 DeviceExtension->DiskGeometry->SectorsPerTrack,
1010 DeviceExtension->DiskGeometry->TracksPerCylinder,
1012 if (NT_SUCCESS(Status))
1014 Information = TableSize;
1020 case IOCTL_DISK_IS_WRITABLE:
1022 PMODE_PARAMETER_HEADER ModeData;
1025 ModeData = ExAllocatePool (NonPagedPool,
1027 if (ModeData == NULL)
1029 Status = STATUS_INSUFFICIENT_RESOURCES;
1032 RtlZeroMemory (ModeData,
1035 Length = ScsiClassModeSense (DeviceObject,
1038 MODE_SENSE_RETURN_ALL);
1039 if (Length < sizeof(MODE_PARAMETER_HEADER))
1042 Status = STATUS_IO_DEVICE_ERROR;
1043 ExFreePool (ModeData);
1047 if (ModeData->DeviceSpecificParameter & MODE_DSP_WRITE_PROTECT)
1049 Status = STATUS_MEDIA_WRITE_PROTECTED;
1053 Status = STATUS_SUCCESS;
1055 ExFreePool (ModeData);
1059 case IOCTL_DISK_VERIFY:
1060 case IOCTL_DISK_FORMAT_TRACKS:
1061 case IOCTL_DISK_PERFORMANCE:
1062 case IOCTL_DISK_LOGGING:
1063 case IOCTL_DISK_FORMAT_TRACKS_EX:
1064 case IOCTL_DISK_HISTOGRAM_STRUCTURE:
1065 case IOCTL_DISK_HISTOGRAM_DATA:
1066 case IOCTL_DISK_HISTOGRAM_RESET:
1067 case IOCTL_DISK_REQUEST_STRUCTURE:
1068 case IOCTL_DISK_REQUEST_DATA:
1069 /* If we get here, something went wrong. Inform the requestor */
1070 DPRINT1("Unhandled control code: %lx\n", ControlCode);
1071 Status = STATUS_INVALID_DEVICE_REQUEST;
1076 /* Call the common device control function */
1077 return(ScsiClassDeviceControl(DeviceObject, Irp));
1080 /* Verify the device if the user caused the error */
1081 if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status))
1083 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
1086 Irp->IoStatus.Status = Status;
1087 Irp->IoStatus.Information = Information;
1088 IoCompleteRequest(Irp,
1095 /**********************************************************************
1097 * DiskClassShutdownFlush
1100 * Answer requests for shutdown and flush calls.
1107 * Pointer to the device.
1110 * Pointer to the IRP
1117 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
1120 PDEVICE_EXTENSION DeviceExtension;
1121 PIO_STACK_LOCATION IrpStack;
1122 PSCSI_REQUEST_BLOCK Srb;
1124 DPRINT("DiskClassShutdownFlush() called!\n");
1126 DeviceExtension = DeviceObject->DeviceExtension;
1129 Srb = ExAllocatePool(NonPagedPool,
1130 sizeof(SCSI_REQUEST_BLOCK));
1133 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1134 Irp->IoStatus.Information = 0;
1135 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1137 return(STATUS_INSUFFICIENT_RESOURCES);
1140 /* Initialize SRB */
1141 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
1142 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
1144 /* Set device IDs */
1145 Srb->PathId = DeviceExtension->PathId;
1146 Srb->TargetId = DeviceExtension->TargetId;
1147 Srb->Lun = DeviceExtension->Lun;
1150 Srb->TimeOutValue = DeviceExtension->TimeOutValue * 4;
1152 /* Flush write cache */
1153 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1154 Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
1155 Srb->CdbLength = 10;
1156 Srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
1157 ScsiClassSendSrbSynchronous(DeviceObject,
1163 /* Get current stack location */
1164 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1166 /* FIXME: Unlock removable media upon shutdown */
1170 IrpStack->Parameters.Others.Argument4 = (PVOID)0;
1172 /* Send shutdown or flush request to the port driver */
1174 if (IrpStack->MajorFunction == IRP_MJ_SHUTDOWN)
1175 Srb->Function = SRB_FUNCTION_SHUTDOWN;
1177 Srb->Function = SRB_FUNCTION_FLUSH;
1179 /* Init completion routine */
1180 IoSetCompletionRoutine(Irp,
1181 ScsiClassIoComplete,
1187 /* Prepare next stack location for a call to the port driver */
1188 IrpStack = IoGetNextIrpStackLocation(Irp);
1189 IrpStack->MajorFunction = IRP_MJ_SCSI;
1190 IrpStack->Parameters.Scsi.Srb = Srb;
1191 Srb->OriginalRequest = Irp;
1193 /* Call port driver */
1194 return(IoCallDriver(DeviceExtension->PortDeviceObject, Irp));
1198 /**********************************************************************
1200 * DiskClassUpdatePartitionDeviceObjects
1203 * Deletes, modifies or creates partition device objects.
1210 * Pointer to the device.
1213 * Pointer to the IRP
1220 DiskClassUpdatePartitionDeviceObjects(IN PDEVICE_OBJECT DiskDeviceObject,
1223 PDRIVE_LAYOUT_INFORMATION PartitionList;
1224 PPARTITION_INFORMATION PartitionEntry;
1225 PDEVICE_EXTENSION DeviceExtension;
1226 PDEVICE_EXTENSION DiskDeviceExtension;
1227 PDISK_DATA DiskData;
1228 ULONG PartitionCount;
1229 ULONG PartitionOrdinal;
1230 ULONG PartitionNumber;
1231 ULONG LastPartitionNumber;
1234 WCHAR NameBuffer[MAX_PATH];
1235 UNICODE_STRING DeviceName;
1236 PDEVICE_OBJECT DeviceObject;
1239 DPRINT("ScsiDiskUpdatePartitionDeviceObjects() called\n");
1241 /* Get partition list */
1242 PartitionList = Irp->AssociatedIrp.SystemBuffer;
1244 /* Round partition count up by 4 */
1245 PartitionCount = ((PartitionList->PartitionCount + 3) / 4) * 4;
1247 /* Remove the partition numbers from the partition list */
1248 for (i = 0; i < PartitionCount; i++)
1250 PartitionList->PartitionEntry[i].PartitionNumber = 0;
1253 DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
1255 /* Traverse on-disk partition list */
1256 LastPartitionNumber = 0;
1257 DeviceExtension = DiskDeviceExtension;
1258 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1261 DeviceExtension = DiskData->NextPartition;
1262 if (DeviceExtension == NULL)
1266 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1268 /* Update last partition number */
1269 if (DiskData->PartitionNumber > LastPartitionNumber)
1270 LastPartitionNumber = DiskData->PartitionNumber;
1272 /* Ignore unused on-disk partitions */
1273 if (DeviceExtension->PartitionLength.QuadPart == 0ULL)
1277 PartitionOrdinal = 0;
1278 for (i = 0; i < PartitionCount; i++)
1280 /* Get current partition entry */
1281 PartitionEntry = &PartitionList->PartitionEntry[i];
1283 /* Ignore empty (aka unused) or extended partitions */
1284 if (PartitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
1285 IsContainerPartition (PartitionEntry->PartitionType))
1290 /* Check for matching partition start offset and length */
1291 if ((PartitionEntry->StartingOffset.QuadPart !=
1292 DeviceExtension->StartingOffset.QuadPart) ||
1293 (PartitionEntry->PartitionLength.QuadPart !=
1294 DeviceExtension->PartitionLength.QuadPart))
1297 DPRINT1("Found matching partition entry for partition %lu\n",
1298 DiskData->PartitionNumber);
1300 /* Found matching partition */
1303 /* Update partition number in partition list */
1304 PartitionEntry->PartitionNumber = DiskData->PartitionNumber;
1310 /* Get disk data for current partition */
1311 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1313 /* Update partition type if partiton will be rewritten */
1314 if (PartitionEntry->RewritePartition == TRUE)
1315 DiskData->PartitionType = PartitionEntry->PartitionType;
1317 /* Assign new partiton ordinal */
1318 DiskData->PartitionOrdinal = PartitionOrdinal;
1320 DPRINT("Partition ordinal %lu was assigned to partition %lu\n",
1321 DiskData->PartitionOrdinal,
1322 DiskData->PartitionNumber);
1326 /* Delete this partition */
1327 DeviceExtension->PartitionLength.QuadPart = 0ULL;
1329 DPRINT("Deleting partition %lu\n",
1330 DiskData->PartitionNumber);
1334 /* Traverse partiton list and create new partiton devices */
1335 PartitionOrdinal = 0;
1336 for (i = 0; i < PartitionCount; i++)
1338 /* Get current partition entry */
1339 PartitionEntry = &PartitionList->PartitionEntry[i];
1341 /* Ignore empty (aka unused) or extended partitions */
1342 if (PartitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
1343 IsContainerPartition (PartitionEntry->PartitionType))
1348 /* Ignore unchanged partition entries */
1349 if (PartitionEntry->RewritePartition == FALSE)
1352 /* Check for an unused device object */
1353 PartitionNumber = 0;
1354 DeviceExtension = DiskDeviceExtension;
1355 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1358 DeviceExtension = DiskData->NextPartition;
1359 if (DeviceExtension == NULL)
1362 /* Get partition disk data */
1363 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1365 /* Found a free (unused) partition (device object) */
1366 if (DeviceExtension->PartitionLength.QuadPart == 0ULL)
1368 PartitionNumber = DiskData->PartitionNumber;
1373 if (PartitionNumber == 0)
1375 /* Create a new partition device object */
1376 DPRINT("Create new partition device object\n");
1378 /* Get new partiton number */
1379 LastPartitionNumber++;
1380 PartitionNumber = LastPartitionNumber;
1382 /* Create partition device object */
1383 swprintf(NameBuffer,
1384 L"\\Device\\Harddisk%lu\\Partition%lu",
1385 DiskDeviceExtension->DeviceNumber,
1387 RtlInitUnicodeString(&DeviceName,
1390 Status = IoCreateDevice(DiskDeviceObject->DriverObject,
1391 sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA),
1397 if (!NT_SUCCESS(Status))
1399 DPRINT1("IoCreateDevice() failed (Status %lx)\n", Status);
1403 DeviceObject->Flags |= DO_DIRECT_IO;
1404 DeviceObject->StackSize = DiskDeviceObject->StackSize;
1405 DeviceObject->Characteristics = DiskDeviceObject->Characteristics;
1406 DeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
1408 /* Initialize device extension */
1409 DeviceExtension = DeviceObject->DeviceExtension;
1410 RtlCopyMemory(DeviceExtension,
1411 DiskDeviceObject->DeviceExtension,
1412 sizeof(DEVICE_EXTENSION));
1413 DeviceExtension->DeviceObject = DeviceObject;
1415 /* Initialize lookaside list for SRBs */
1416 ScsiClassInitializeSrbLookasideList(DeviceExtension,
1419 /* Link current partition device extension to previous disk data */
1420 DiskData->NextPartition = DeviceExtension;
1421 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1422 DiskData->NextPartition = NULL;
1426 /* Reuse an existing partition device object */
1427 DPRINT("Reuse an exisiting partition device object\n");
1428 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1431 /* Update partition data and device extension */
1432 DiskData->PartitionNumber = PartitionNumber;
1433 DiskData->PartitionOrdinal = PartitionOrdinal;
1434 DiskData->PartitionType = PartitionEntry->PartitionType;
1435 DiskData->BootIndicator = PartitionEntry->BootIndicator;
1436 DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
1437 DeviceExtension->StartingOffset = PartitionEntry->StartingOffset;
1438 DeviceExtension->PartitionLength = PartitionEntry->PartitionLength;
1440 /* Update partition number in the partition list */
1441 PartitionEntry->PartitionNumber = PartitionNumber;
1443 DPRINT("Partition ordinal %lu was assigned to partition %lu\n",
1444 DiskData->PartitionOrdinal,
1445 DiskData->PartitionNumber);
1448 DPRINT("ScsiDiskUpdatePartitionDeviceObjects() done\n");
1452 /**********************************************************************
1454 * ScsiDiskSearchForDisk
1457 * Searches the hardware tree for the given disk.
1464 * Disk device extension.
1467 * Handle to the hardware bus key.
1469 * DetectedDiskNumber
1470 * Returned disk number.
1473 * TRUE: Disk was found.
1474 * FALSE: Search failed.
1478 ScsiDiskSearchForDisk(IN PDEVICE_EXTENSION DeviceExtension,
1480 OUT PULONG DetectedDiskNumber)
1482 PKEY_VALUE_FULL_INFORMATION ValueData;
1483 OBJECT_ATTRIBUTES ObjectAttributes;
1484 PDISK_DATA DiskData;
1485 UNICODE_STRING IdentifierString;
1486 UNICODE_STRING NameString;
1487 HANDLE BusInstanceKey;
1488 HANDLE ControllerKey;
1490 HANDLE DiskInstanceKey;
1492 ULONG ControllerNumber;
1499 DPRINT("ScsiDiskSearchForDiskData() called\n");
1503 /* Enumerate buses */
1504 for (BusNumber = 0; ; BusNumber++)
1506 /* Open bus instance subkey */
1511 RtlInitUnicodeString(&NameString,
1514 InitializeObjectAttributes(&ObjectAttributes,
1516 OBJ_CASE_INSENSITIVE,
1520 Status = ZwOpenKey(&BusInstanceKey,
1523 if (!NT_SUCCESS(Status))
1528 /* Open 'DiskController' subkey */
1529 RtlInitUnicodeString(&NameString,
1532 InitializeObjectAttributes(&ObjectAttributes,
1534 OBJ_CASE_INSENSITIVE,
1538 Status = ZwOpenKey(&ControllerKey,
1541 if (!NT_SUCCESS(Status))
1543 ZwClose(BusInstanceKey);
1547 /* Enumerate controllers */
1548 for (ControllerNumber = 0; ; ControllerNumber++)
1550 /* Open 'DiskPeripheral' subkey */
1552 L"%lu\\DiskPeripheral",
1555 RtlInitUnicodeString(&NameString,
1558 InitializeObjectAttributes(&ObjectAttributes,
1560 OBJ_CASE_INSENSITIVE,
1564 Status = ZwOpenKey(&DiskKey,
1567 if (!NT_SUCCESS(Status))
1572 /* Enumerate disks */
1573 for (DiskNumber = 0; ; DiskNumber++)
1575 /* Open disk instance subkey */
1580 RtlInitUnicodeString(&NameString,
1583 InitializeObjectAttributes(&ObjectAttributes,
1585 OBJ_CASE_INSENSITIVE,
1589 Status = ZwOpenKey(&DiskInstanceKey,
1592 if (!NT_SUCCESS(Status))
1597 DPRINT("Found disk key: bus %lu controller %lu disk %lu\n",
1602 /* Allocate data buffer */
1603 ValueData = ExAllocatePool(PagedPool,
1605 if (ValueData == NULL)
1607 ZwClose(DiskInstanceKey);
1611 /* Get the 'Identifier' value */
1612 RtlInitUnicodeString(&NameString,
1614 Status = ZwQueryValueKey(DiskInstanceKey,
1616 KeyValueFullInformation,
1621 ZwClose(DiskInstanceKey);
1622 if (!NT_SUCCESS(Status))
1624 ExFreePool(ValueData);
1628 IdentifierString.Buffer =
1629 (PWSTR)((PUCHAR)ValueData + ValueData->DataOffset);
1630 IdentifierString.Length = (USHORT)ValueData->DataLength - 2;
1631 IdentifierString.MaximumLength = (USHORT)ValueData->DataLength;
1633 DPRINT("DiskIdentifier: %wZ\n",
1636 DiskData = (PDISK_DATA)(DeviceExtension + 1);
1637 if (DiskData->Signature != 0)
1639 /* Comapre disk signature */
1642 DiskData->Signature);
1643 if (!_wcsnicmp(Buffer, &IdentifierString.Buffer[9], 8))
1645 DPRINT("Found disk %lu\n", DiskNumber);
1647 *DetectedDiskNumber = DiskNumber;
1652 /* Comapre mbr checksum */
1655 DiskData->MbrCheckSum);
1656 if (!_wcsnicmp(Buffer, &IdentifierString.Buffer[0], 8))
1658 DPRINT("Found disk %lu\n", DiskNumber);
1660 *DetectedDiskNumber = DiskNumber;
1664 ExFreePool(ValueData);
1666 ZwClose(DiskInstanceKey);
1668 if (DiskFound == TRUE)
1675 ZwClose(ControllerKey);
1676 ZwClose(BusInstanceKey);
1679 DPRINT("ScsiDiskSearchForDisk() done\n");
1685 /**********************************************************************
1687 * DiskClassUpdateFixedDiskGeometry
1690 * Updated the geometry of a disk if the disk can be accessed
1698 * Disk device extension.
1705 ScsiDiskUpdateFixedDiskGeometry(IN PDEVICE_EXTENSION DeviceExtension)
1707 PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor;
1708 PCM_INT13_DRIVE_PARAMETER DriveParameters;
1709 PKEY_VALUE_FULL_INFORMATION ValueBuffer;
1710 OBJECT_ATTRIBUTES ObjectAttributes;
1711 UNICODE_STRING KeyName;
1712 UNICODE_STRING ValueName;
1720 ULONG SectorsPerTrack;
1721 ULONG TracksPerCylinder;
1724 DPRINT("ScsiDiskUpdateFixedDiskGeometry() called\n");
1726 RtlInitUnicodeString(&KeyName,
1727 L"\\Registry\\Machine\\Hardware\\Description\\System");
1729 InitializeObjectAttributes(&ObjectAttributes,
1731 OBJ_CASE_INSENSITIVE,
1735 /* Open the adapter key */
1736 Status = ZwOpenKey(&SystemKey,
1739 if (!NT_SUCCESS(Status))
1741 DPRINT("ZwOpenKey() failed (Status %lx)\n", Status);
1745 /* Allocate value buffer */
1746 ValueBuffer = ExAllocatePool(PagedPool,
1748 if (ValueBuffer == NULL)
1750 DPRINT1("Failed to allocate value buffer\n");
1755 RtlInitUnicodeString(&ValueName,
1756 L"Configuration Data");
1758 /* Query 'Configuration Data' value */
1759 Status = ZwQueryValueKey(SystemKey,
1761 KeyValueFullInformation,
1765 if (!NT_SUCCESS(Status))
1767 DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status);
1768 ExFreePool(ValueBuffer);
1773 /* Open the 'MultifunctionAdapter' subkey */
1774 RtlInitUnicodeString(&KeyName,
1775 L"MultifunctionAdapter");
1777 InitializeObjectAttributes(&ObjectAttributes,
1779 OBJ_CASE_INSENSITIVE,
1783 Status = ZwOpenKey(&BusKey,
1787 if (!NT_SUCCESS(Status))
1789 DPRINT("ZwQueryValueKey() failed (Status %lx)\n", Status);
1790 ExFreePool(ValueBuffer);
1794 if (!ScsiDiskSearchForDisk(DeviceExtension, BusKey, &DiskNumber))
1796 DPRINT("ScsiDiskSearchForDisk() failed\n");
1798 ExFreePool(ValueBuffer);
1804 ResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
1805 ((PUCHAR)ValueBuffer + ValueBuffer->DataOffset);
1807 DriveParameters = (PCM_INT13_DRIVE_PARAMETER)
1808 ((PUCHAR)ResourceDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR));
1811 for (i = 0; i< DriveParameters[0].NumberDrives; i++)
1813 DPRINT1("Drive %lu: %lu Cylinders %hu Heads %hu Sectors\n",
1815 DriveParameters[i].MaxCylinders,
1816 DriveParameters[i].MaxHeads,
1817 DriveParameters[i].SectorsPerTrack);
1821 Cylinders = DriveParameters[DiskNumber].MaxCylinders + 1;
1822 TracksPerCylinder = DriveParameters[DiskNumber].MaxHeads +1;
1823 SectorsPerTrack = DriveParameters[DiskNumber].SectorsPerTrack;
1825 DPRINT("BIOS geometry: %lu Cylinders %hu Heads %hu Sectors\n",
1831 (DeviceExtension->PartitionLength.QuadPart >> DeviceExtension->SectorShift);
1833 DPRINT("Physical sectors: %lu\n",
1836 Length = TracksPerCylinder * SectorsPerTrack;
1839 DPRINT1("Invalid track length 0\n");
1840 ExFreePool(ValueBuffer);
1844 Cylinders = Sectors / Length;
1846 DPRINT("Logical geometry: %lu Cylinders %hu Heads %hu Sectors\n",
1851 /* Update the disk geometry */
1852 DeviceExtension->DiskGeometry->SectorsPerTrack = SectorsPerTrack;
1853 DeviceExtension->DiskGeometry->TracksPerCylinder = TracksPerCylinder;
1854 DeviceExtension->DiskGeometry->Cylinders.QuadPart = (ULONGLONG)Cylinders;
1856 if (DeviceExtension->DMActive)
1858 DPRINT1("FIXME: Update geometry with respect to the installed disk manager!\n");
1860 /* FIXME: Update geometry for disk managers */
1864 ExFreePool(ValueBuffer);
1866 DPRINT("ScsiDiskUpdateFixedDiskGeometry() done\n");
1870 /**********************************************************************
1872 * ScsiDiskCalcMbrCheckSum
1875 * Calculates the Checksum from drives MBR.
1882 * Disk device extension.
1885 * Pointer to the caller supplied cecksum variable.
1888 * TRUE: Checksum was calculated.
1889 * FALSE: Calculation failed.
1893 ScsiDiskCalcMbrCheckSum(IN PDEVICE_EXTENSION DeviceExtension,
1894 OUT PULONG Checksum)
1896 IO_STATUS_BLOCK IoStatusBlock;
1897 LARGE_INTEGER SectorOffset;
1906 KeInitializeEvent(&Event,
1910 /* Get the disk sector size */
1911 SectorSize = DeviceExtension->DiskGeometry->BytesPerSector;
1912 if (SectorSize < 512)
1917 /* Allocate MBR buffer */
1918 MbrBuffer = ExAllocatePool(NonPagedPool,
1920 if (MbrBuffer == NULL)
1925 /* Allocate an IRP */
1926 SectorOffset.QuadPart = 0ULL;
1927 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
1928 DeviceExtension->DeviceObject,
1936 ExFreePool(MbrBuffer);
1940 /* Call the miniport driver */
1941 Status = IoCallDriver(DeviceExtension->DeviceObject,
1943 if (Status == STATUS_PENDING)
1945 KeWaitForSingleObject(&Event,
1950 Status = IoStatusBlock.Status;
1953 if (!NT_SUCCESS(Status))
1955 ExFreePool(MbrBuffer);
1959 /* Calculate MBR checksum */
1961 for (i = 0; i < 128; i++)
1963 Sum += MbrBuffer[i];
1965 *Checksum = ~Sum + 1;
1967 ExFreePool(MbrBuffer);