3 * Copyright (C) 2001, 2002 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
44 ULONG PartitionNumber;
45 ULONG PartitionOrdinal;
47 BOOLEAN BootIndicator;
48 BOOLEAN DriveNotReady;
49 } DISK_DATA, *PDISK_DATA;
53 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
54 PUNICODE_STRING RegistryPath,
55 PCLASS_INIT_DATA InitializationData,
56 PDEVICE_OBJECT PortDeviceObject,
60 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData);
63 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
68 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
69 IN PUNICODE_STRING RegistryPath, /* what's this used for? */
70 IN PDEVICE_OBJECT PortDeviceObject,
73 IN PIO_SCSI_CAPABILITIES Capabilities,
74 IN PSCSI_INQUIRY_DATA InquiryData,
75 IN PCLASS_INIT_DATA InitializationData);
78 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
82 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
87 /* FUNCTIONS ****************************************************************/
92 // This function initializes the driver, locates and claims
93 // hardware resources, and creates various NT objects needed
94 // to process I/O requests.
100 // IN PDRIVER_OBJECT DriverObject System allocated Driver Object
102 // IN PUNICODE_STRING RegistryPath Name of registry driver service
109 DriverEntry(IN PDRIVER_OBJECT DriverObject,
110 IN PUNICODE_STRING RegistryPath)
112 CLASS_INIT_DATA InitData;
114 DPRINT("Disk Class Driver %s\n",
116 DPRINT("RegistryPath '%wZ'\n",
119 RtlZeroMemory(&InitData,
120 sizeof(CLASS_INIT_DATA));
122 InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
123 InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION) + sizeof(DISK_DATA);
124 InitData.DeviceType = FILE_DEVICE_DISK;
125 InitData.DeviceCharacteristics = 0;
127 InitData.ClassError = NULL; // DiskClassProcessError;
128 InitData.ClassReadWriteVerification = DiskClassCheckReadWrite;
129 InitData.ClassFindDeviceCallBack = DiskClassCheckDevice;
130 InitData.ClassFindDevices = DiskClassFindDevices;
131 InitData.ClassDeviceControl = DiskClassDeviceControl;
132 InitData.ClassShutdownFlush = DiskClassShutdownFlush;
133 InitData.ClassCreateClose = NULL;
134 InitData.ClassStartIo = NULL;
136 return(ScsiClassInitialize(DriverObject,
142 /**********************************************************************
144 * DiskClassFindDevices
147 * This function searches for device that are attached to the
155 * System allocated Driver Object for this driver
158 * Name of registry driver service key
161 * Pointer to the main initialization data
164 * Pointer to the port Device Object
170 * TRUE: At least one disk drive was found
171 * FALSE: No disk drive found
175 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
176 PUNICODE_STRING RegistryPath,
177 PCLASS_INIT_DATA InitializationData,
178 PDEVICE_OBJECT PortDeviceObject,
181 PCONFIGURATION_INFORMATION ConfigInfo;
182 PIO_SCSI_CAPABILITIES PortCapabilities;
183 PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
184 PSCSI_INQUIRY_DATA UnitInfo;
185 PINQUIRYDATA InquiryData;
192 DPRINT("DiskClassFindDevices() called.\n");
194 /* Get port capabilities */
195 Status = ScsiClassGetCapabilities(PortDeviceObject,
197 if (!NT_SUCCESS(Status))
199 DPRINT("ScsiClassGetCapabilities() failed! (Status 0x%lX)\n", Status);
203 DPRINT("PortCapabilities: %p\n", PortCapabilities);
204 DPRINT("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength);
205 DPRINT("MaximumPhysicalPages: %lu\n", PortCapabilities->MaximumPhysicalPages);
207 /* Get inquiry data */
208 Status = ScsiClassGetInquiryData(PortDeviceObject,
209 (PSCSI_ADAPTER_BUS_INFO *)&Buffer);
210 if (!NT_SUCCESS(Status))
212 DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status);
216 /* Check whether there are unclaimed devices */
217 AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
218 DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData,
220 if (DeviceCount == 0)
222 DPRINT("No unclaimed devices!\n");
226 DPRINT("Found %lu unclaimed devices!\n", DeviceCount);
228 ConfigInfo = IoGetConfigurationInformation();
230 /* Search each bus of this adapter */
231 for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++)
233 DPRINT("Searching bus %lu\n", Bus);
235 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset);
237 while (AdapterBusInfo->BusData[Bus].InquiryDataOffset)
239 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
241 if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
242 (InquiryData->DeviceType == OPTICAL_DEVICE)) &&
243 (InquiryData->DeviceTypeQualifier == 0) &&
244 (UnitInfo->DeviceClaimed == FALSE))
246 DPRINT("Vendor: '%.24s'\n",
247 InquiryData->VendorId);
249 /* Create device objects for disk */
250 Status = DiskClassCreateDeviceObject(DriverObject,
254 ConfigInfo->DiskCount,
258 if (NT_SUCCESS(Status))
260 ConfigInfo->DiskCount++;
265 if (UnitInfo->NextInquiryDataOffset == 0)
268 UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset);
274 DPRINT("DiskClassFindDevices() done\n");
280 /**********************************************************************
282 * DiskClassCheckDevice
285 * This function checks the InquiryData for the correct device
286 * type and qualifier.
293 * Pointer to the inquiry data for the device in question.
296 * TRUE: A disk device was found.
301 DiskClassCheckDevice(IN PINQUIRYDATA InquiryData)
303 return((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE ||
304 InquiryData->DeviceType == OPTICAL_DEVICE) &&
305 InquiryData->DeviceTypeQualifier == 0);
309 /**********************************************************************
311 * DiskClassCheckReadWrite
314 * This function checks the given IRP for correct data.
321 * Pointer to the device.
327 * STATUS_SUCCESS: The IRP matches the requirements of the given device.
332 DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
335 PDEVICE_EXTENSION DeviceExtension;
338 DPRINT("DiskClassCheckReadWrite() called\n");
340 DeviceExtension = DeviceObject->DeviceExtension;
341 DiskData = (PDISK_DATA)(DeviceExtension + 1);
343 if (DiskData->DriveNotReady == TRUE)
345 Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
346 IoSetHardErrorOrVerifyDevice(Irp,
348 return(STATUS_INVALID_PARAMETER);
351 return(STATUS_SUCCESS);
355 /**********************************************************************
357 * DiskClassCreateDeviceObject
360 * Create the raw device and any partition devices on this drive
367 * The system created driver object
377 * STATUS_SUCCESS: Device objects for disk and partitions were created.
382 DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
383 IN PUNICODE_STRING RegistryPath, /* what's this used for? */
384 IN PDEVICE_OBJECT PortDeviceObject,
387 IN PIO_SCSI_CAPABILITIES Capabilities,
388 IN PSCSI_INQUIRY_DATA InquiryData,
389 IN PCLASS_INIT_DATA InitializationData)
391 OBJECT_ATTRIBUTES ObjectAttributes;
392 UNICODE_STRING UnicodeDeviceDirName;
393 WCHAR NameBuffer[80];
394 CHAR NameBuffer2[80];
395 PDEVICE_OBJECT DiskDeviceObject;
396 PDEVICE_OBJECT PartitionDeviceObject;
397 PDEVICE_EXTENSION DiskDeviceExtension; /* defined in class2.h */
398 PDEVICE_EXTENSION PartitionDeviceExtension; /* defined in class2.h */
399 PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
401 PPARTITION_INFORMATION PartitionEntry;
403 ULONG PartitionNumber;
406 DPRINT("DiskClassCreateDeviceObject() called\n");
408 /* Create the harddisk device directory */
410 L"\\Device\\Harddisk%lu",
412 RtlInitUnicodeString(&UnicodeDeviceDirName,
414 InitializeObjectAttributes(&ObjectAttributes,
415 &UnicodeDeviceDirName,
419 Status = ZwCreateDirectoryObject(&Handle,
422 if (!NT_SUCCESS(Status))
424 DbgPrint("Could not create device dir object\n");
428 /* Claim the disk device */
429 Status = ScsiClassClaimDevice(PortDeviceObject,
433 if (!NT_SUCCESS(Status))
435 DbgPrint("Could not claim disk device\n");
437 ZwMakeTemporaryObject(Handle);
443 /* Create disk device (Partition 0) */
445 "\\Device\\Harddisk%lu\\Partition0",
448 Status = ScsiClassCreateDeviceObject(DriverObject,
453 if (!NT_SUCCESS(Status))
455 DPRINT("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status);
457 /* Release (unclaim) the disk */
458 ScsiClassClaimDevice(PortDeviceObject,
463 /* Delete the harddisk device directory */
464 ZwMakeTemporaryObject(Handle);
470 DiskDeviceObject->Flags |= DO_DIRECT_IO;
471 if (((PINQUIRYDATA)InquiryData->InquiryData)->RemovableMedia)
473 DiskDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
475 DiskDeviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;
477 if (PortDeviceObject->AlignmentRequirement > DiskDeviceObject->AlignmentRequirement)
479 DiskDeviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
482 DiskDeviceExtension = DiskDeviceObject->DeviceExtension;
483 DiskDeviceExtension->LockCount = 0;
484 DiskDeviceExtension->DeviceNumber = DiskNumber;
485 DiskDeviceExtension->PortDeviceObject = PortDeviceObject;
486 DiskDeviceExtension->PhysicalDevice = DiskDeviceObject;
487 DiskDeviceExtension->PortCapabilities = Capabilities;
488 DiskDeviceExtension->StartingOffset.QuadPart = 0;
489 DiskDeviceExtension->PortNumber = (UCHAR)PortNumber;
490 DiskDeviceExtension->PathId = InquiryData->PathId;
491 DiskDeviceExtension->TargetId = InquiryData->TargetId;
492 DiskDeviceExtension->Lun = InquiryData->Lun;
494 /* Initialize the lookaside list for SRBs */
495 ScsiClassInitializeSrbLookasideList(DiskDeviceExtension,
498 /* zero-out disk data */
499 DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);
500 RtlZeroMemory(DiskData,
503 /* Get disk geometry */
504 DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
505 sizeof(DISK_GEOMETRY));
506 if (DiskDeviceExtension->DiskGeometry == NULL)
508 DPRINT("Failed to allocate geometry buffer!\n");
510 ExDeleteNPagedLookasideList(&DiskDeviceExtension->SrbLookasideListHead);
512 IoDeleteDevice(DiskDeviceObject);
514 /* Release (unclaim) the disk */
515 ScsiClassClaimDevice(PortDeviceObject,
520 /* Delete the harddisk device directory */
521 ZwMakeTemporaryObject(Handle);
524 return(STATUS_INSUFFICIENT_RESOURCES);
527 /* Read the drive's capacity */
528 Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
529 if (!NT_SUCCESS(Status) &&
530 (DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) == 0)
532 DPRINT1("Failed to retrieve drive capacity!\n");
533 return(STATUS_SUCCESS);
537 /* Clear the verify flag for removable media drives. */
538 DiskDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
541 DPRINT("SectorSize: %lu\n", DiskDeviceExtension->DiskGeometry->BytesPerSector);
543 if ((DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
544 (DiskDeviceExtension->DiskGeometry->MediaType == RemovableMedia))
546 /* Allocate a partition list for a single entry. */
547 PartitionList = ExAllocatePool(NonPagedPool,
548 sizeof(DRIVE_LAYOUT_INFORMATION));
549 if (PartitionList != NULL)
551 RtlZeroMemory(PartitionList,
552 sizeof(DRIVE_LAYOUT_INFORMATION));
553 PartitionList->PartitionCount = 1;
555 DiskData->DriveNotReady = TRUE;
556 Status = STATUS_SUCCESS;
561 /* Read partition table */
562 Status = IoReadPartitionTable(DiskDeviceObject,
563 DiskDeviceExtension->DiskGeometry->BytesPerSector,
567 DPRINT("IoReadPartitionTable(): Status: %lx\n", Status);
569 if ((!NT_SUCCESS(Status) || PartitionList->PartitionCount == 0) &&
570 DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
572 if (!NT_SUCCESS(Status))
574 /* Drive is not ready. */
575 DPRINT("Drive not ready\n");
576 DiskData->DriveNotReady = TRUE;
580 ExFreePool(PartitionList);
583 /* Allocate a partition list for a single entry. */
584 PartitionList = ExAllocatePool(NonPagedPool,
585 sizeof(DRIVE_LAYOUT_INFORMATION));
586 if (PartitionList != NULL)
588 RtlZeroMemory(PartitionList,
589 sizeof(DRIVE_LAYOUT_INFORMATION));
590 PartitionList->PartitionCount = 1;
592 Status = STATUS_SUCCESS;
597 if (NT_SUCCESS(Status))
599 DPRINT("Read partition table!\n");
601 DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount);
603 for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
605 PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];
607 DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
609 PartitionEntry->PartitionNumber,
610 PartitionEntry->BootIndicator,
611 PartitionEntry->PartitionType,
612 PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
613 PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
615 /* Create partition device object */
617 "\\Device\\Harddisk%lu\\Partition%lu",
619 PartitionNumber + 1);
621 Status = ScsiClassCreateDeviceObject(DriverObject,
624 &PartitionDeviceObject,
626 DPRINT("ScsiClassCreateDeviceObject(): Status %x\n", Status);
627 if (NT_SUCCESS(Status))
629 PartitionDeviceObject->Flags = DiskDeviceObject->Flags;
630 PartitionDeviceObject->Characteristics = DiskDeviceObject->Characteristics;
631 PartitionDeviceObject->StackSize = DiskDeviceObject->StackSize;
632 PartitionDeviceObject->AlignmentRequirement = DiskDeviceObject->AlignmentRequirement;
634 PartitionDeviceExtension = PartitionDeviceObject->DeviceExtension;
635 PartitionDeviceExtension->LockCount = 0;
636 PartitionDeviceExtension->DeviceNumber = DiskNumber;
637 PartitionDeviceExtension->PortDeviceObject = PortDeviceObject;
638 PartitionDeviceExtension->DiskGeometry = DiskDeviceExtension->DiskGeometry;
639 PartitionDeviceExtension->PhysicalDevice = DiskDeviceExtension->PhysicalDevice;
640 PartitionDeviceExtension->PortCapabilities = Capabilities;
641 PartitionDeviceExtension->StartingOffset.QuadPart =
642 PartitionEntry->StartingOffset.QuadPart;
643 PartitionDeviceExtension->PartitionLength.QuadPart =
644 PartitionEntry->PartitionLength.QuadPart;
645 PartitionDeviceExtension->PortNumber = (UCHAR)PortNumber;
646 PartitionDeviceExtension->PathId = InquiryData->PathId;
647 PartitionDeviceExtension->TargetId = InquiryData->TargetId;
648 PartitionDeviceExtension->Lun = InquiryData->Lun;
649 PartitionDeviceExtension->SectorShift = DiskDeviceExtension->SectorShift;
651 /* Initialize lookaside list for SRBs */
652 ScsiClassInitializeSrbLookasideList(PartitionDeviceExtension,
655 DiskData = (PDISK_DATA)(PartitionDeviceExtension + 1);
656 DiskData->PartitionType = PartitionEntry->PartitionType;
657 DiskData->PartitionNumber = PartitionNumber + 1;
658 DiskData->PartitionOrdinal = PartitionNumber + 1;
659 DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
660 DiskData->BootIndicator = PartitionEntry->BootIndicator;
661 DiskData->DriveNotReady = FALSE;
665 DPRINT1("ScsiClassCreateDeviceObject() failed to create partition device object (Status %x)\n", Status);
672 if (PartitionList != NULL)
673 ExFreePool(PartitionList);
675 DPRINT("DiskClassCreateDeviceObjects() done\n");
677 return(STATUS_SUCCESS);
681 /**********************************************************************
683 * DiskClassDeviceControl
686 * Answer requests for device control calls
692 * Standard dispatch arguments
699 DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
702 PDEVICE_EXTENSION DeviceExtension;
703 PIO_STACK_LOCATION IrpStack;
704 ULONG ControlCode, InputLength, OutputLength;
709 DPRINT("DiskClassDeviceControl() called!\n");
711 Status = STATUS_INVALID_DEVICE_REQUEST;
713 IrpStack = IoGetCurrentIrpStackLocation(Irp);
714 ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
715 InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
716 OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
717 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
718 DiskData = (PDISK_DATA)(DeviceExtension + 1);
722 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
723 DPRINT("IOCTL_DISK_GET_DRIVE_GEOMETRY\n");
724 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
726 Status = STATUS_INVALID_PARAMETER;
730 PDISK_GEOMETRY Geometry;
732 if (DeviceExtension->DiskGeometry == NULL)
734 DPRINT("No disk geometry available!\n");
735 DeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool,
736 sizeof(DISK_GEOMETRY));
738 Status = ScsiClassReadDriveCapacity(DeviceObject);
739 DPRINT("ScsiClassReadDriveCapacity() returned (Status %lx)\n", Status);
740 if (NT_SUCCESS(Status))
742 Geometry = (PDISK_GEOMETRY)Irp->AssociatedIrp.SystemBuffer;
743 RtlMoveMemory(Geometry,
744 DeviceExtension->DiskGeometry,
745 sizeof(DISK_GEOMETRY));
747 Status = STATUS_SUCCESS;
748 Information = sizeof(DISK_GEOMETRY);
753 case IOCTL_DISK_GET_PARTITION_INFO:
754 DPRINT("IOCTL_DISK_GET_PARTITION_INFO\n");
755 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
756 sizeof(PARTITION_INFORMATION))
758 Status = STATUS_INFO_LENGTH_MISMATCH;
760 else if (DiskData->PartitionNumber == 0)
762 Status = STATUS_INVALID_DEVICE_REQUEST;
766 PPARTITION_INFORMATION PartitionInfo;
768 PartitionInfo = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
770 PartitionInfo->PartitionType = DiskData->PartitionType;
771 PartitionInfo->StartingOffset = DeviceExtension->StartingOffset;
772 PartitionInfo->PartitionLength = DeviceExtension->PartitionLength;
773 PartitionInfo->HiddenSectors = DiskData->HiddenSectors;
774 PartitionInfo->PartitionNumber = DiskData->PartitionNumber;
775 PartitionInfo->BootIndicator = DiskData->BootIndicator;
776 PartitionInfo->RewritePartition = FALSE;
777 PartitionInfo->RecognizedPartition =
778 IsRecognizedPartition(DiskData->PartitionType);
780 Status = STATUS_SUCCESS;
781 Information = sizeof(PARTITION_INFORMATION);
785 case IOCTL_DISK_SET_PARTITION_INFO:
786 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
787 sizeof(SET_PARTITION_INFORMATION))
789 Status = STATUS_INFO_LENGTH_MISMATCH;
791 else if (DiskData->PartitionNumber == 0)
793 Status = STATUS_INVALID_DEVICE_REQUEST;
797 PSET_PARTITION_INFORMATION PartitionInfo;
799 PartitionInfo = (PSET_PARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
801 Status = IoSetPartitionInformation(DeviceExtension->PhysicalDevice,
802 DeviceExtension->DiskGeometry->BytesPerSector,
803 DiskData->PartitionOrdinal,
804 PartitionInfo->PartitionType);
805 if (NT_SUCCESS(Status))
807 DiskData->PartitionType = PartitionInfo->PartitionType;
812 case IOCTL_DISK_GET_DRIVE_LAYOUT:
813 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
814 sizeof(DRIVE_LAYOUT_INFORMATION))
816 Status = STATUS_BUFFER_TOO_SMALL;
820 PDRIVE_LAYOUT_INFORMATION PartitionList;
822 Status = IoReadPartitionTable(DeviceExtension->PhysicalDevice,
823 DeviceExtension->DiskGeometry->BytesPerSector,
826 if (NT_SUCCESS(Status))
830 BufferSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,
832 BufferSize += PartitionList->PartitionCount * sizeof(PARTITION_INFORMATION);
834 if (BufferSize > IrpStack->Parameters.DeviceIoControl.OutputBufferLength)
836 Status = STATUS_BUFFER_TOO_SMALL;
840 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
843 Status = STATUS_SUCCESS;
844 Information = BufferSize;
846 ExFreePool(PartitionList);
851 case IOCTL_DISK_SET_DRIVE_LAYOUT:
852 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength <
853 sizeof(DRIVE_LAYOUT_INFORMATION))
855 Status = STATUS_INFO_LENGTH_MISMATCH;
857 else if (DeviceExtension->PhysicalDevice->DeviceExtension != DeviceExtension)
859 Status = STATUS_INVALID_PARAMETER;
863 PDRIVE_LAYOUT_INFORMATION PartitionList;
866 PartitionList = Irp->AssociatedIrp.SystemBuffer;
867 TableSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
868 ((PartitionList->PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
870 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < TableSize)
872 Status = STATUS_BUFFER_TOO_SMALL;
876 Status = IoWritePartitionTable(DeviceExtension->DeviceObject,
877 DeviceExtension->DiskGeometry->BytesPerSector,
878 DeviceExtension->DiskGeometry->SectorsPerTrack,
879 DeviceExtension->DiskGeometry->TracksPerCylinder,
881 if (NT_SUCCESS(Status))
883 /* FIXME: Update partition device objects */
885 Information = TableSize;
891 case IOCTL_DISK_VERIFY:
892 case IOCTL_DISK_FORMAT_TRACKS:
893 case IOCTL_DISK_PERFORMANCE:
894 case IOCTL_DISK_IS_WRITABLE:
895 case IOCTL_DISK_LOGGING:
896 case IOCTL_DISK_FORMAT_TRACKS_EX:
897 case IOCTL_DISK_HISTOGRAM_STRUCTURE:
898 case IOCTL_DISK_HISTOGRAM_DATA:
899 case IOCTL_DISK_HISTOGRAM_RESET:
900 case IOCTL_DISK_REQUEST_STRUCTURE:
901 case IOCTL_DISK_REQUEST_DATA:
902 /* If we get here, something went wrong. Inform the requestor */
903 DPRINT1("Unhandled control code: %lx\n", ControlCode);
904 Status = STATUS_INVALID_DEVICE_REQUEST;
909 /* Call the common device control function */
910 return(ScsiClassDeviceControl(DeviceObject, Irp));
913 /* Verify the device if the user caused the error */
914 if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status))
916 IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
919 Irp->IoStatus.Status = Status;
920 Irp->IoStatus.Information = Information;
921 IoCompleteRequest(Irp,
928 /**********************************************************************
930 * DiskClassShutdownFlush
933 * Answer requests for shutdown and flush calls.
940 * Pointer to the device.
950 DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
953 PDEVICE_EXTENSION DeviceExtension;
954 PIO_STACK_LOCATION IrpStack;
955 PSCSI_REQUEST_BLOCK Srb;
957 DPRINT("DiskClassShutdownFlush() called!\n");
959 DeviceExtension = DeviceObject->DeviceExtension;
962 Srb = ExAllocatePool(NonPagedPool,
963 sizeof(SCSI_REQUEST_BLOCK));
966 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
967 Irp->IoStatus.Information = 0;
968 IoCompleteRequest(Irp, IO_NO_INCREMENT);
970 return(STATUS_INSUFFICIENT_RESOURCES);
974 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
975 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
978 Srb->PathId = DeviceExtension->PathId;
979 Srb->TargetId = DeviceExtension->TargetId;
980 Srb->Lun = DeviceExtension->Lun;
982 /* Flush write cache */
983 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
984 Srb->SrbFlags = SRB_FLAGS_NO_DATA_TRANSFER;
986 Srb->Cdb[0] = SCSIOP_SYNCHRONIZE_CACHE;
987 ScsiClassSendSrbSynchronous(DeviceObject,
993 /* Get current stack location */
994 IrpStack = IoGetCurrentIrpStackLocation(Irp);
996 /* FIXME: Unlock removable media upon shutdown */
1000 IrpStack->Parameters.Others.Argument4 = (PVOID)0;
1002 /* Send shutdown or flush request to the port driver */
1004 if (IrpStack->MajorFunction == IRP_MJ_SHUTDOWN)
1005 Srb->Function = SRB_FUNCTION_SHUTDOWN;
1007 Srb->Function = SRB_FUNCTION_FLUSH;
1009 /* Init completion routine */
1010 IoSetCompletionRoutine(Irp,
1011 ScsiClassIoComplete,
1017 /* Prepare next stack location for a call to the port driver */
1018 IrpStack = IoGetNextIrpStackLocation(Irp);
1019 IrpStack->MajorFunction = IRP_MJ_SCSI;
1020 IrpStack->Parameters.Scsi.Srb = Srb;
1021 Srb->OriginalRequest = Irp;
1023 /* Call port driver */
1024 return(IoCallDriver(DeviceExtension->PortDeviceObject, Irp));