📄 scsiport.c
字号:
if (!((HwInitializationData->AdapterInterfaceType == PCIBus) &&
(HwInitializationData->VendorIdLength > 0) &&
(HwInitializationData->VendorId != NULL) &&
(HwInitializationData->DeviceIdLength > 0) &&
(HwInitializationData->DeviceId != NULL)))
{
/* Construct a resource list */
ResourceList = SpiConfigToResource(DeviceExtension,
PortConfig);
if (ResourceList)
{
UNICODE_STRING UnicodeString;
RtlInitUnicodeString(&UnicodeString, L"ScsiAdapter");
DPRINT("Reporting resources\n");
Status = IoReportResourceUsage(&UnicodeString,
DriverObject,
NULL,
0,
PortDeviceObject,
ResourceList,
FIELD_OFFSET(CM_RESOURCE_LIST,
List[0].PartialResourceList.PartialDescriptors) +
ResourceList->List[0].PartialResourceList.Count
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
FALSE,
&Conflict);
ExFreePool(ResourceList);
/* In case of a failure or a conflict, break */
if (Conflict || (!NT_SUCCESS(Status)))
{
if (Conflict)
Status = STATUS_CONFLICTING_ADDRESSES;
break;
}
}
}
/* Reset the Conflict var */
Conflict = FALSE;
/* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
if (PortConfig->MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS)
DeviceExtension->MaxTargedIds = SCSI_MAXIMUM_TARGETS_PER_BUS;
else
DeviceExtension->MaxTargedIds = PortConfig->MaximumNumberOfTargets;
DeviceExtension->BusNum = PortConfig->NumberOfBuses;
DeviceExtension->CachesData = PortConfig->CachesData;
DeviceExtension->ReceiveEvent = PortConfig->ReceiveEvent;
DeviceExtension->SupportsTaggedQueuing = PortConfig->TaggedQueuing;
DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu;
/* If something was disabled via registry - apply it */
if (ConfigInfo.DisableMultipleLun)
DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu = FALSE;
if (ConfigInfo.DisableTaggedQueueing)
DeviceExtension->SupportsTaggedQueuing = PortConfig->MultipleRequestPerLu = FALSE;
/* Check if we need to alloc SRB data */
if (DeviceExtension->SupportsTaggedQueuing ||
DeviceExtension->MultipleReqsPerLun)
{
DeviceExtension->NeedSrbDataAlloc = TRUE;
}
else
{
DeviceExtension->NeedSrbDataAlloc = FALSE;
}
/* Get a pointer to the port capabilities */
PortCapabilities = &DeviceExtension->PortCapabilities;
/* Copy one field there */
DeviceExtension->MapBuffers = PortConfig->MapBuffers;
PortCapabilities->AdapterUsesPio = PortConfig->MapBuffers;
if (DeviceExtension->AdapterObject == NULL &&
(PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE || PortConfig->Master))
{
DPRINT1("DMA is not supported yet\n");
ASSERT(FALSE);
}
if (DeviceExtension->SrbExtensionBuffer == NULL &&
(DeviceExtension->SrbExtensionSize != 0 ||
PortConfig->AutoRequestSense))
{
DeviceExtension->SupportsAutoSense = PortConfig->AutoRequestSense;
DeviceExtension->NeedSrbExtensionAlloc = TRUE;
/* Allocate common buffer */
Status = SpiAllocateCommonBuffer(DeviceExtension, 0);
/* Check for failure */
if (!NT_SUCCESS(Status))
break;
}
/* Allocate SrbData, if needed */
if (DeviceExtension->NeedSrbDataAlloc)
{
ULONG Count;
PSCSI_REQUEST_BLOCK_INFO SrbData;
if (DeviceExtension->SrbDataCount != 0)
Count = DeviceExtension->SrbDataCount;
else
Count = DeviceExtension->RequestsNumber * 2;
/* Allocate the data */
SrbData = ExAllocatePoolWithTag(NonPagedPool, Count * sizeof(SCSI_REQUEST_BLOCK_INFO), TAG_SCSIPORT);
if (SrbData == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(SrbData, Count * sizeof(SCSI_REQUEST_BLOCK_INFO));
DeviceExtension->SrbInfo = SrbData;
DeviceExtension->FreeSrbInfo = SrbData;
DeviceExtension->SrbDataCount = Count;
/* Link it to the list */
while (Count > 0)
{
SrbData->Requests.Flink = (PLIST_ENTRY)(SrbData + 1);
SrbData++;
Count--;
}
/* Mark the last entry of the list */
SrbData--;
SrbData->Requests.Flink = NULL;
}
/* Initialize port capabilities */
PortCapabilities = &DeviceExtension->PortCapabilities;
PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
PortCapabilities->MaximumTransferLength = PortConfig->MaximumTransferLength;
if (PortConfig->ReceiveEvent)
PortCapabilities->SupportedAsynchronousEvents |= SRBEV_SCSI_ASYNC_NOTIFICATION;
PortCapabilities->TaggedQueuing = DeviceExtension->SupportsTaggedQueuing;
PortCapabilities->AdapterScansDown = PortConfig->AdapterScansDown;
if (PortConfig->AlignmentMask > PortDeviceObject->AlignmentRequirement)
PortDeviceObject->AlignmentRequirement = PortConfig->AlignmentMask;
PortCapabilities->AlignmentMask = PortDeviceObject->AlignmentRequirement;
if (PortCapabilities->MaximumPhysicalPages == 0)
{
PortCapabilities->MaximumPhysicalPages =
BYTES_TO_PAGES(PortCapabilities->MaximumTransferLength);
/* Apply miniport's limits */
if (PortConfig->NumberOfPhysicalBreaks < PortCapabilities->MaximumPhysicalPages)
{
PortCapabilities->MaximumPhysicalPages = PortConfig->NumberOfPhysicalBreaks;
}
}
/* Deal with interrupts */
if (DeviceExtension->HwInterrupt == NULL ||
(PortConfig->BusInterruptLevel == 0 && PortConfig->BusInterruptVector == 0))
{
/* No interrupts */
KeInitializeSpinLock(&DeviceExtension->IrqLock);
/* FIXME: Use synchronization routine */
ASSERT("No interrupts branch requires changes in synchronization\n");
DeviceExtension->Interrupt = (PVOID)DeviceExtension;
DPRINT("No interrupts\n");
}
else
{
/* Are 2 interrupts needed? */
if (DeviceExtension->HwInterrupt != NULL &&
(PortConfig->BusInterruptLevel != 0 || PortConfig->BusInterruptVector != 0) &&
(PortConfig->BusInterruptLevel2 != 0 || PortConfig->BusInterruptVector2 != 0))
{
DPRINT1("2 interrupts requested! Not yet supported\n");
ASSERT(FALSE);
}
else
{
BOOLEAN InterruptShareable;
/* No, only 1 interrupt */
DPRINT("1 interrupt, IRQ is %d\n", PortConfig->BusInterruptLevel);
DeviceExtension->InterruptLevel = PortConfig->BusInterruptLevel;
/* Register an interrupt handler for this device */
MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,
PortConfig->SystemIoBusNumber,
PortConfig->BusInterruptLevel,
PortConfig->BusInterruptVector,
&Dirql,
&Affinity);
/* Determing IRQ sharability as usual */
if (PortConfig->AdapterInterfaceType == MicroChannel ||
PortConfig->InterruptMode == LevelSensitive)
{
InterruptShareable = TRUE;
}
else
{
InterruptShareable = FALSE;
}
Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
(PKSERVICE_ROUTINE)ScsiPortIsr,
DeviceExtension,
NULL,
MappedIrq,
Dirql,
Dirql,
PortConfig->InterruptMode,
InterruptShareable,
Affinity,
FALSE);
if (!(NT_SUCCESS(Status)))
{
DPRINT1("Could not connect interrupt %d\n",
PortConfig->BusInterruptVector);
DeviceExtension->Interrupt = NULL;
break;
}
}
}
/* Save IoAddress (from access ranges) */
if (HwInitializationData->NumberOfAccessRanges != 0)
{
DeviceExtension->IoAddress =
((*(PortConfig->AccessRanges))[0]).RangeStart.LowPart;
DPRINT("Io Address %x\n", DeviceExtension->IoAddress);
}
/* Set flag that it's allowed to disconnect during this command */
DeviceExtension->Flags |= SCSI_PORT_DISCONNECT_ALLOWED;
/* Initialize counter of active requests (-1 means there are none) */
DeviceExtension->ActiveRequestCounter = -1;
/* Analyze what we have about DMA */
if (DeviceExtension->AdapterObject != NULL &&
PortConfig->Master &&
PortConfig->NeedPhysicalAddresses)
{
DeviceExtension->MapRegisters = TRUE;
}
else
{
DeviceExtension->MapRegisters = FALSE;
}
/* Call HwInitialize at DISPATCH_LEVEL */
KeRaiseIrql(DISPATCH_LEVEL, &Dirql);
if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
DeviceExtension->HwInitialize,
DeviceExtension->MiniPortDeviceExtension))
{
DPRINT1("HwInitialize() failed!\n");
KeLowerIrql(Dirql);
Status = STATUS_ADAPTER_HARDWARE_ERROR;
break;
}
/* Check if a notification is needed */
if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
{
/* Call DPC right away, because we're already at DISPATCH_LEVEL */
ScsiPortDpcForIsr(NULL,
DeviceExtension->DeviceObject,
NULL,
NULL);
}
/* Lower irql back to what it was */
KeLowerIrql(Dirql);
/* Start our timer */
IoStartTimer(PortDeviceObject);
/* Initialize bus scanning information */
DeviceExtension->BusesConfig = ExAllocatePoolWithTag(PagedPool,
sizeof(PSCSI_BUS_SCAN_INFO) * DeviceExtension->PortConfig->NumberOfBuses
+ sizeof(ULONG), TAG_SCSIPORT);
if (!DeviceExtension->BusesConfig)
{
DPRINT1("Out of resources!\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
/* Zero it */
RtlZeroMemory(DeviceExtension->BusesConfig,
sizeof(PSCSI_BUS_SCAN_INFO) * DeviceExtension->PortConfig->NumberOfBuses
+ sizeof(ULONG));
/* Store number of buses there */
DeviceExtension->BusesConfig->NumberOfBuses = (UCHAR)DeviceExtension->BusNum;
/* Scan the adapter for devices */
SpiScanAdapter(DeviceExtension);
/* Build the registry device map */
SpiBuildDeviceMap(DeviceExtension,
(PUNICODE_STRING)Argument2);
/* Create the dos device link */
swprintf(DosNameBuffer,
L"\\??\\Scsi%lu:",
SystemConfig->ScsiPortCount);
RtlInitUnicodeString(&DosDeviceName, DosNameBuffer);
IoCreateSymbolicLink(&DosDeviceName, &DeviceName);
/* Increase the port count */
SystemConfig->ScsiPortCount++;
FirstConfigCall = FALSE;
/* Increase adapter number and bus number respectively */
ConfigInfo.AdapterNumber++;
if (!Again)
ConfigInfo.BusNumber++;
DPRINT("Bus: %lu MaxBus: %lu\n", BusNumber, MaxBus);
DeviceFound = TRUE;
}
/* Clean up the mess */
SpiCleanupAfterInit(DeviceExtension);
/* Close registry keys */
if (ConfigInfo.ServiceKey != NULL)
ZwClose(ConfigInfo.ServiceKey);
if (ConfigInfo.DeviceKey != NULL)
ZwClose(ConfigInfo.DeviceKey);
if (ConfigInfo.BusKey != NULL)
ZwClose(ConfigInfo.BusKey);
if (ConfigInfo.AccessRanges != NULL)
ExFreePool(ConfigInfo.AccessRanges);
if (ConfigInfo.Parameter != NULL)
ExFreePool(ConfigInfo.Parameter);
DPRINT("ScsiPortInitialize() done, Status = 0x%08X, DeviceFound = %d!\n",
Status, DeviceFound);
return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS;
}
static VOID
SpiCleanupAfterInit(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
{
PSCSI_LUN_INFO LunInfo;
PVOID Ptr;
ULONG Bus, Lun;
/* Check if we have something to clean up */
if (DeviceExtension == NULL)
return;
/* Stop the timer and disconnect the interrupt */
if (DeviceExtension->Interrupt)
{
IoStopTimer(DeviceExtension->DeviceObject);
IoDisconnectInterrupt(DeviceExtension->Interrupt);
}
/* Delete ConfigInfo */
if (DeviceExtension->BusesConfig)
{
for (Bus = 0; Bus < DeviceExtension->BusNum; Bus++)
{
if (!DeviceExtension->BusesConfig->BusScanInfo[Bus])
continue;
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Bus]->LunInfo;
while (!LunInfo)
{
/* Free current, but save pointer to the next one */
Ptr = LunInfo->Next;
ExFreePool(LunInfo);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -