📄 disk.c
字号:
//
// Call port driver to get adapter capabilities.
//
status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities);
if (!NT_SUCCESS(status)) {
DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n"));
return(FALSE);
}
//
// Call port driver to get inquiry information to find disks.
//
status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer);
if (!NT_SUCCESS(status)) {
DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n"));
return(FALSE);
}
//
// Do a quick scan of the devices on this adapter to determine how many
// disks are on this adapter. This is used to determine the number of
// SRB zone elements to allocate.
//
adapterDisk = 0;
adapterInfo = (PVOID) buffer;
adapterDisk = ScsiClassFindUnclaimedDevices(InitializationData, adapterInfo);
//
// Allocate a zone of SRB for disks on this adapter.
//
if (adapterDisk == 0) {
//
// No free disks were found.
//
return(FALSE);
}
//
// Get the number of disks already initialized.
//
configurationInformation = IoGetConfigurationInformation();
diskCount = &configurationInformation->DiskCount;
//
// For each SCSI bus this adapter supports ...
//
for (scsiBus=0; scsiBus < (ULONG)adapterInfo->NumberOfBuses; scsiBus++) {
//
// Get the SCSI bus scan data for this bus.
//
lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);
//
// Search list for unclaimed disk devices.
//
while (adapterInfo->BusData[scsiBus].InquiryDataOffset) {
inquiryData = (PVOID)lunInfo->InquiryData;
if (((inquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
(inquiryData->DeviceType == OPTICAL_DEVICE)) &&
inquiryData->DeviceTypeQualifier == 0 &&
(!lunInfo->DeviceClaimed)) {
DebugPrint((1,
"FindScsiDevices: Vendor string is %.24s\n",
inquiryData->VendorId));
//
// Create device objects for disk
//
status = CreateDiskDeviceObject(DriverObject,
RegistryPath,
PortDeviceObject,
PortNumber,
diskCount,
portCapabilities,
lunInfo,
InitializationData);
if (NT_SUCCESS(status)) {
//
// Increment system disk device count.
//
(*diskCount)++;
foundOne = TRUE;
}
}
//
// Get next LunInfo.
//
if (lunInfo->NextInquiryDataOffset == 0) {
break;
}
lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
}
}
//
// Buffer is allocated by ScsiClassGetInquiryData and must be free returning.
//
ExFreePool(buffer);
return(foundOne);
} // end FindScsiDisks()
NTSTATUS
STDCALL
CreateDiskDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath,
IN PDEVICE_OBJECT PortDeviceObject,
IN ULONG PortNumber,
IN PULONG DeviceCount,
IN PIO_SCSI_CAPABILITIES PortCapabilities,
IN PSCSI_INQUIRY_DATA LunInfo,
IN PCLASS_INIT_DATA InitData
)
/*++
Routine Description:
This routine creates an object for the physical device and then searches
the device for partitions and creates an object for each partition.
Arguments:
DriverObject - Pointer to driver object created by system.
PortDeviceObject - Miniport device object.
PortNumber - port number. Used in creating disk objects.
DeviceCount - Number of previously installed devices.
PortCapabilities - Capabilities of this SCSI port.
LunInfo - LUN specific information.
Return Value:
NTSTATUS
--*/
{
CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
STRING ntNameString;
UNICODE_STRING ntUnicodeString;
ULONG partitionNumber = 0;
OBJECT_ATTRIBUTES objectAttributes;
HANDLE handle;
NTSTATUS status;
PDEVICE_OBJECT deviceObject = NULL;
PDEVICE_OBJECT physicalDevice;
PDISK_GEOMETRY diskGeometry = NULL;
PDRIVE_LAYOUT_INFORMATION partitionList;
PDEVICE_EXTENSION deviceExtension = NULL;
PDEVICE_EXTENSION physicalDeviceExtension;
PDISK_DATA diskData;
ULONG bytesPerSector;
UCHAR sectorShift;
UCHAR pathId = LunInfo->PathId;
UCHAR targetId = LunInfo->TargetId;
UCHAR lun = LunInfo->Lun;
BOOLEAN writeCache;
PVOID senseData = NULL;
ULONG srbFlags;
ULONG dmByteSkew = 0;
PULONG dmSkew;
BOOLEAN dmActive = FALSE;
ULONG timeOut = 0;
ULONG numberListElements = 0;
BOOLEAN srbListInitialized = FALSE;
PAGED_CODE();
//
// Set up an object directory to contain the objects for this
// device and all its partitions.
//
sprintf(ntNameBuffer,
"\\Device\\Harddisk%lu",
*DeviceCount);
RtlInitString(&ntNameString,
ntNameBuffer);
status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
&ntNameString,
TRUE);
if (!NT_SUCCESS(status)) {
return(status);
}
InitializeObjectAttributes(&objectAttributes,
&ntUnicodeString,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL,
NULL);
status = ZwCreateDirectoryObject(&handle,
DIRECTORY_ALL_ACCESS,
&objectAttributes);
RtlFreeUnicodeString(&ntUnicodeString);
if (!NT_SUCCESS(status)) {
DebugPrint((1,
"CreateDiskDeviceObjects: Could not create directory %s\n",
ntNameBuffer));
return(status);
}
//
// Claim the device.
//
status = ScsiClassClaimDevice(PortDeviceObject,
LunInfo,
FALSE,
&PortDeviceObject);
if (!NT_SUCCESS(status)) {
ZwMakeTemporaryObject(handle);
ZwClose(handle);
return status;
}
//
// Create a device object for this device. Each physical disk will
// have at least one device object. The required device object
// describes the entire device. Its directory path is
// \Device\HarddiskN\Partition0, where N = device number.
//
sprintf(ntNameBuffer,
"\\Device\\Harddisk%lu\\Partition0",
*DeviceCount);
status = ScsiClassCreateDeviceObject(DriverObject,
ntNameBuffer,
NULL,
&deviceObject,
InitData);
if (!NT_SUCCESS(status)) {
DebugPrint((1,
"CreateDiskDeviceObjects: Can not create device object %s\n",
ntNameBuffer));
goto CreateDiskDeviceObjectsExit;
}
//
// Indicate that IRPs should include MDLs for data transfers.
//
deviceObject->Flags |= DO_DIRECT_IO;
//
// Check if this is during initialization. If not indicate that
// system initialization already took place and this disk is ready
// to be accessed.
//
if (!RegistryPath) {
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
}
//
// Check for removable media support.
//
if (((PINQUIRYDATA)LunInfo->InquiryData)->RemovableMedia) {
deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
}
//
// Set up required stack size in device object.
//
deviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;
deviceExtension = deviceObject->DeviceExtension;
//
// Allocate spinlock for split request completion.
//
KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
//
// Initialize lock count to zero. The lock count is used to
// disable the ejection mechanism on devices that support
// removable media. Only the lock count in the physical
// device extension is used.
//
deviceExtension->LockCount = 0;
//
// Save system disk number.
//
deviceExtension->DeviceNumber = *DeviceCount;
//
// Copy port device object pointer to the device extension.
//
deviceExtension->PortDeviceObject = PortDeviceObject;
//
// Set the alignment requirements for the device based on the
// host adapter requirements
//
if (PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
deviceObject->AlignmentRequirement = PortDeviceObject->AlignmentRequirement;
}
//
// This is the physical device object.
//
physicalDevice = deviceObject;
physicalDeviceExtension = deviceExtension;
//
// Save address of port driver capabilities.
//
deviceExtension->PortCapabilities = PortCapabilities;
//
// Build the lookaside list for srb's for the physical disk. Should only
// need a couple.
//
ScsiClassInitializeSrbLookasideList(deviceExtension,
PARTITION0_LIST_SIZE);
srbListInitialized = TRUE;
//
// Initialize the srb flags.
//
if (((PINQUIRYDATA)LunInfo->InquiryData)->CommandQueue &&
PortCapabilities->TaggedQueuing) {
deviceExtension->SrbFlags = SRB_FLAGS_QUEUE_ACTION_ENABLE;
} else {
deviceExtension->SrbFlags = 0;
}
//
// Allow queued requests if this is not removable media.
//
if (!(deviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {
deviceExtension->SrbFlags |= SRB_FLAGS_NO_QUEUE_FREEZE;
}
//
// Look for controller that require special flags.
//
ScanForSpecial(deviceObject,
LunInfo,
PortCapabilities);
srbFlags = deviceExtension->SrbFlags;
//
// Allocate buffer for drive geometry.
//
diskGeometry = ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY));
if (diskGeometry == NULL) {
DebugPrint((1,
"CreateDiskDeviceObjects: Can not allocate disk geometry buffer\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
goto CreateDiskDeviceObjectsExit;
}
deviceExtension->DiskGeometry = diskGeometry;
//
// Allocate request sense buffer.
//
senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
if (senseData == NULL) {
//
// The buffer can not be allocated.
//
DebugPrint((1,
"CreateDiskDeviceObjects: Can not allocate request sense buffer\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
goto CreateDiskDeviceObjectsExit;
}
//
// Set the sense data pointer in the device extension.
//
deviceExtension->SenseData = senseData;
//
// Physical device object will describe the entire
// device, starting at byte offset 0.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -