scsiport.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 2,013 行 · 第 1/5 页
C
2,013 行
if (!NT_SUCCESS(Status))
{
DPRINT("Unable to open driver's registry key %wZ, status 0x%08x\n", RegistryPath, Status);
ConfigInfo->ServiceKey = NULL;
}
/* If we could open driver's service key, then proceed to the Parameters key */
if (ConfigInfo->ServiceKey != NULL)
{
RtlInitUnicodeString(&KeyName, L"Parameters");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ConfigInfo->ServiceKey,
(PSECURITY_DESCRIPTOR) NULL);
/* Try to open it */
Status = ZwOpenKey(&ConfigInfo->DeviceKey,
KEY_READ,
&ObjectAttributes);
if (NT_SUCCESS(Status))
{
/* Yes, Parameters key exist, and it must be used instead of
the Service key */
ZwClose(ConfigInfo->ServiceKey);
ConfigInfo->ServiceKey = ConfigInfo->DeviceKey;
ConfigInfo->DeviceKey = NULL;
}
}
if (ConfigInfo->ServiceKey != NULL)
{
/* Open the Device key */
RtlInitUnicodeString(&KeyName, L"Device");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ConfigInfo->ServiceKey,
NULL);
/* We don't check for failure here - not needed */
ZwOpenKey(&ConfigInfo->DeviceKey,
KEY_READ,
&ObjectAttributes);
}
}
/**********************************************************************
* NAME EXPORTED
* ScsiPortInitialize
*
* DESCRIPTION
* Initializes SCSI port driver specific data.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* Argument1
* Pointer to the miniport driver's driver object.
*
* Argument2
* Pointer to the miniport driver's registry path.
*
* HwInitializationData
* Pointer to port driver specific configuration data.
*
* HwContext
Miniport driver specific context.
*
* RETURN VALUE
* Status.
*
* @implemented
*/
ULONG STDCALL
ScsiPortInitialize(IN PVOID Argument1,
IN PVOID Argument2,
IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
IN PVOID HwContext)
{
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = NULL;
PCONFIGURATION_INFORMATION SystemConfig;
PPORT_CONFIGURATION_INFORMATION PortConfig;
PORT_CONFIGURATION_INFORMATION InitialPortConfig;
CONFIGURATION_INFO ConfigInfo;
ULONG DeviceExtensionSize;
ULONG PortConfigSize;
BOOLEAN Again;
BOOLEAN DeviceFound = FALSE;
BOOLEAN FirstConfigCall = TRUE;
ULONG Result;
NTSTATUS Status;
ULONG MaxBus;
ULONG BusNumber = 0;
PCI_SLOT_NUMBER SlotNumber;
PDEVICE_OBJECT PortDeviceObject;
WCHAR NameBuffer[80];
UNICODE_STRING DeviceName;
WCHAR DosNameBuffer[80];
UNICODE_STRING DosDeviceName;
PIO_SCSI_CAPABILITIES PortCapabilities;
ULONG MappedIrq;
KIRQL Dirql;
KAFFINITY Affinity;
PCM_RESOURCE_LIST ResourceList;
BOOLEAN Conflict;
DPRINT ("ScsiPortInitialize() called!\n");
/* Check params for validity */
if ((HwInitializationData->HwInitialize == NULL) ||
(HwInitializationData->HwStartIo == NULL) ||
(HwInitializationData->HwInterrupt == NULL) ||
(HwInitializationData->HwFindAdapter == NULL) ||
(HwInitializationData->HwResetBus == NULL))
{
return STATUS_INVALID_PARAMETER;
}
/* Set handlers */
DriverObject->DriverStartIo = ScsiPortStartIo;
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = ScsiPortDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
/* Obtain configuration information */
SystemConfig = IoGetConfigurationInformation();
/* Zero the internal configuration info structure */
RtlZeroMemory(&ConfigInfo, sizeof(CONFIGURATION_INFO));
/* Zero starting slot number */
SlotNumber.u.AsULONG = 0;
/* Allocate space for access ranges */
if (HwInitializationData->NumberOfAccessRanges)
{
ConfigInfo.AccessRanges =
ExAllocatePoolWithTag(PagedPool,
HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE), TAG_SCSIPORT);
/* Fail if failed */
if (ConfigInfo.AccessRanges == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Open registry keys */
SpiInitOpenKeys(&ConfigInfo, (PUNICODE_STRING)Argument2);
/* Last adapter number = not known */
ConfigInfo.LastAdapterNumber = SP_UNINITIALIZED_VALUE;
/* Calculate sizes of DeviceExtension and PortConfig */
DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
HwInitializationData->DeviceExtensionSize;
MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1;
DPRINT("MaxBus: %lu\n", MaxBus);
while (TRUE)
{
/* Create a unicode device name */
swprintf(NameBuffer,
L"\\Device\\ScsiPort%lu",
SystemConfig->ScsiPortCount);
RtlInitUnicodeString(&DeviceName, NameBuffer);
DPRINT("Creating device: %wZ\n", &DeviceName);
/* Create the port device */
Status = IoCreateDevice(DriverObject,
DeviceExtensionSize,
&DeviceName,
FILE_DEVICE_CONTROLLER,
0,
FALSE,
&PortDeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
PortDeviceObject = NULL;
break;
}
DPRINT ("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
/* Set the buffering strategy here... */
PortDeviceObject->Flags |= DO_DIRECT_IO;
PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; /* FIXME: Is this really needed? */
/* Fill Device Extension */
DeviceExtension = PortDeviceObject->DeviceExtension;
DeviceExtension->Length = DeviceExtensionSize;
DeviceExtension->DeviceObject = PortDeviceObject;
DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
/* Driver's routines... */
DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
DeviceExtension->HwResetBus = HwInitializationData->HwResetBus;
DeviceExtension->HwDmaStarted = HwInitializationData->HwDmaStarted;
/* Extensions sizes */
DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
DeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
/* Round Srb extension size to the quadword */
DeviceExtension->SrbExtensionSize =
~(sizeof(LONGLONG) - 1) & (DeviceExtension->SrbExtensionSize +
sizeof(LONGLONG) - 1);
/* Fill some numbers (bus count, lun count, etc) */
DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS;
DeviceExtension->RequestsNumber = 16;
/* Initialize the spin lock in the controller extension */
KeInitializeSpinLock(&DeviceExtension->IrqLock);
KeInitializeSpinLock(&DeviceExtension->SpinLock);
/* Initialize the DPC object */
IoInitializeDpcRequest(PortDeviceObject,
ScsiPortDpcForIsr);
/* Initialize the device timer */
DeviceExtension->TimerCount = -1;
IoInitializeTimer(PortDeviceObject,
ScsiPortIoTimer,
DeviceExtension);
/* Initialize miniport timer */
KeInitializeTimer(&DeviceExtension->MiniportTimer);
KeInitializeDpc(&DeviceExtension->MiniportTimerDpc,
SpiMiniportTimerDpc,
PortDeviceObject);
CreatePortConfig:
Status = SpiCreatePortConfig(DeviceExtension,
HwInitializationData,
&ConfigInfo,
&InitialPortConfig,
FirstConfigCall);
if (!NT_SUCCESS(Status))
break;
/* Allocate and initialize port configuration info */
PortConfigSize = (sizeof(PORT_CONFIGURATION_INFORMATION) +
HwInitializationData->NumberOfAccessRanges *
sizeof(ACCESS_RANGE) + 7) & ~7;
DeviceExtension->PortConfig = ExAllocatePoolWithTag(NonPagedPool, PortConfigSize, TAG_SCSIPORT);
/* Fail if failed */
if (DeviceExtension->PortConfig == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
PortConfig = DeviceExtension->PortConfig;
/* Copy information here */
RtlCopyMemory(PortConfig,
&InitialPortConfig,
sizeof(PORT_CONFIGURATION_INFORMATION));
/* Copy extension sizes into the PortConfig */
PortConfig->SpecificLuExtensionSize = DeviceExtension->LunExtensionSize;
PortConfig->SrbExtensionSize = DeviceExtension->SrbExtensionSize;
/* Initialize Access ranges */
if (HwInitializationData->NumberOfAccessRanges != 0)
{
PortConfig->AccessRanges = (PVOID)(PortConfig+1);
/* Align to LONGLONG */
PortConfig->AccessRanges = (PVOID)((ULONG)(PortConfig->AccessRanges) + 7);
PortConfig->AccessRanges = (PVOID)((ULONG)(PortConfig->AccessRanges) & ~7);
/* Copy the data */
RtlCopyMemory(PortConfig->AccessRanges,
ConfigInfo.AccessRanges,
HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE));
}
/* Search for matching PCI device */
if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
(HwInitializationData->VendorIdLength > 0) &&
(HwInitializationData->VendorId != NULL) &&
(HwInitializationData->DeviceIdLength > 0) &&
(HwInitializationData->DeviceId != NULL))
{
PortConfig->BusInterruptLevel = 0;
/* Get PCI device data */
DPRINT("VendorId '%.*s' DeviceId '%.*s'\n",
HwInitializationData->VendorIdLength,
HwInitializationData->VendorId,
HwInitializationData->DeviceIdLength,
HwInitializationData->DeviceId);
if (!SpiGetPciConfigData(DriverObject,
PortDeviceObject,
HwInitializationData,
PortConfig,
RegistryPath,
ConfigInfo.BusNumber,
&SlotNumber))
{
/* Continue to the next bus, nothing here */
ConfigInfo.BusNumber++;
DeviceExtension->PortConfig = NULL;
ExFreePool(PortConfig);
Again = FALSE;
goto CreatePortConfig;
}
if (!PortConfig->BusInterruptLevel)
{
/* Bypass this slot, because no interrupt was assigned */
DeviceExtension->PortConfig = NULL;
ExFreePool(PortConfig);
goto CreatePortConfig;
}
}
else
{
DPRINT("Non-pci bus\n");
}
/* Note: HwFindAdapter is called once for each bus */
Again = FALSE;
DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
Result = (HwInitializationData->HwFindAdapter)(&DeviceExtension->MiniPortDeviceExtension,
HwContext,
0, /* BusInformation */
ConfigInfo.Parameter, /* ArgumentString */
PortConfig,
&Again);
DPRINT("HwFindAdapter() Result: %lu Again: %s\n",
Result, (Again) ? "True" : "False");
/* Free MapRegisterBase, it's not needed anymore */
if (DeviceExtension->MapRegisterBase != NULL)
{
ExFreePool(DeviceExtension->MapRegisterBase);
DeviceExtension->MapRegisterBase = NULL;
}
/* If result is nothing good... */
if (Result != SP_RETURN_FOUND)
{
DPRINT("HwFindAdapter() Result: %lu\n", Result);
if (Result == SP_RETURN_NOT_FOUND)
{
/* We can continue on the next bus */
ConfigInfo.BusNumber++;
Again = FALSE;
DeviceExtension->PortConfig = NULL;
ExFreePool(PortConfig);
goto CreatePortConfig;
}
/* Otherwise, break */
Status = STATUS_INTERNAL_ERROR;
break;
}
DPRINT("ScsiPortInitialize(): Found HBA! (%x), adapter Id %d\n",
PortConfig->BusInterruptVector, PortConfig->InitiatorBusId[0]);
/* If the SRB extension size was updated */
if (!DeviceExtension->NonCachedExtension &&
(PortConfig->SrbExtensionSize != DeviceExtension->SrbExtensionSize))
{
/* Set it (rounding to LONGLONG again) */
DeviceExtension->SrbExtensionSize =
(PortConfig->SrbExtensionSize +
sizeof(LONGLONG)) & ~(sizeof(LONGLONG) - 1);
}
/* The same with LUN extension size */
if (PortConfig->SpecificLuExtensionSize != DeviceExtension->LunExtensionSize)
DeviceExtension->LunExtensionSize = PortConfig->SpecificLuExtensionSize;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?