- Finish ScsiPortInitialize() refactoring / improving. Only DMA stuff and 2-interrupts case are missing now.

svn path=/trunk/; revision=26220
This commit is contained in:
Aleksey Bragin 2007-03-31 18:37:07 +00:00
parent c08f45390a
commit fc3d38d1cb
2 changed files with 716 additions and 161 deletions

View file

@ -194,6 +194,13 @@ SpiResourceToConfig(IN PHW_INITIALIZATION_DATA HwInitializationData,
IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor,
IN PPORT_CONFIGURATION_INFORMATION PortConfig);
static PCM_RESOURCE_LIST
SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PPORT_CONFIGURATION_INFORMATION PortConfig);
static VOID
SpiCleanupAfterInit(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
/* FUNCTIONS *****************************************************************/
@ -780,7 +787,7 @@ ScsiPortInitialize(IN PVOID Argument1,
{
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = NULL;
PCONFIGURATION_INFORMATION SystemConfig;
PPORT_CONFIGURATION_INFORMATION PortConfig;
PORT_CONFIGURATION_INFORMATION InitialPortConfig;
@ -793,7 +800,7 @@ ScsiPortInitialize(IN PVOID Argument1,
ULONG Result;
NTSTATUS Status;
ULONG MaxBus;
ULONG BusNumber;
ULONG BusNumber = 0;
PCI_SLOT_NUMBER SlotNumber;
PDEVICE_OBJECT PortDeviceObject;
@ -806,6 +813,9 @@ ScsiPortInitialize(IN PVOID Argument1,
KIRQL Dirql;
KAFFINITY Affinity;
PCM_RESOURCE_LIST ResourceList;
BOOLEAN Conflict;
DPRINT ("ScsiPortInitialize() called!\n");
@ -854,12 +864,8 @@ ScsiPortInitialize(IN PVOID Argument1,
DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
HwInitializationData->DeviceExtensionSize;
MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1;
DPRINT("MaxBus: %lu\n", MaxBus);
PortDeviceObject = NULL;
BusNumber = 0;
SlotNumber.u.AsULONG = 0;
MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1;
DPRINT("MaxBus: %lu\n", MaxBus);
while (TRUE)
{
@ -901,6 +907,7 @@ ScsiPortInitialize(IN PVOID Argument1,
DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
/* Driver's routines... */
DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
DeviceExtension->HwResetBus = HwInitializationData->HwResetBus;
@ -1022,189 +1029,548 @@ CreatePortConfig:
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 */
"", /* ArgumentString */
PortConfig,
&Again);
HwContext,
0, /* BusInformation */
ConfigInfo.Parameter, /* ArgumentString */
PortConfig,
&Again);
DPRINT("HwFindAdapter() Result: %lu Again: %s\n",
Result, (Again) ? "True" : "False");
Result, (Again) ? "True" : "False");
if (Result == SP_RETURN_FOUND)
{
DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig->BusInterruptVector);
/* Free MapRegisterBase, it's not needed anymore */
if (DeviceExtension->MapRegisterBase != NULL)
{
ExFreePool(DeviceExtension->MapRegisterBase);
DeviceExtension->MapRegisterBase = NULL;
}
/* Register an interrupt handler for this device */
MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,
PortConfig->SystemIoBusNumber,
PortConfig->BusInterruptLevel,
PortConfig->BusInterruptVector,
&Dirql,
&Affinity);
Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
ScsiPortIsr,
DeviceExtension,
&DeviceExtension->SpinLock,
MappedIrq,
Dirql,
Dirql,
PortConfig->InterruptMode,
TRUE,
Affinity,
FALSE);
if (!NT_SUCCESS(Status))
{
DbgPrint("Could not connect interrupt %d\n",
PortConfig->BusInterruptVector);
goto ByeBye;
}
/* If result is nothing good... */
if (Result != SP_RETURN_FOUND)
{
DPRINT("HwFindAdapter() Result: %lu\n", Result);
/* 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;
if (!(HwInitializationData->HwInitialize)(&DeviceExtension->MiniPortDeviceExtension))
{
DbgPrint("HwInitialize() failed!");
Status = STATUS_UNSUCCESSFUL;
goto ByeBye;
}
/* Initialize port capabilities */
DeviceExtension->PortCapabilities = ExAllocatePool(NonPagedPool,
sizeof(IO_SCSI_CAPABILITIES));
if (DeviceExtension->PortCapabilities == NULL)
{
DbgPrint("Failed to allocate port capabilities!\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto ByeBye;
}
PortCapabilities = DeviceExtension->PortCapabilities;
PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
PortCapabilities->MaximumTransferLength =
PortConfig->MaximumTransferLength;
PortCapabilities->MaximumPhysicalPages =
PortCapabilities->MaximumTransferLength / PAGE_SIZE;
PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
PortCapabilities->AlignmentMask =
PortConfig->AlignmentMask;
PortCapabilities->TaggedQueuing =
PortConfig->TaggedQueuing;
PortCapabilities->AdapterScansDown =
PortConfig->AdapterScansDown;
PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */
/* Initialize bus scanning information */
DeviceExtension->BusesConfig = ExAllocatePool(PagedPool,
sizeof(PSCSI_BUS_SCAN_INFO) * DeviceExtension->PortConfig->NumberOfBuses
+ sizeof(ULONG));
if (!DeviceExtension->BusesConfig)
if (Result == SP_RETURN_NOT_FOUND)
{
DPRINT1("Out of resources!\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto ByeBye;
/* We can continue on the next bus */
ConfigInfo.BusNumber++;
Again = FALSE;
DeviceExtension->PortConfig = NULL;
ExFreePool(PortConfig);
goto CreatePortConfig;
}
/* Zero it */
RtlZeroMemory(DeviceExtension->BusesConfig,
sizeof(PSCSI_BUS_SCAN_INFO) * DeviceExtension->PortConfig->NumberOfBuses
+ sizeof(ULONG));
/* Otherwise, break */
Status = STATUS_INTERNAL_ERROR;
break;
}
/* Store number of buses there */
DeviceExtension->BusesConfig->NumberOfBuses = DeviceExtension->PortConfig->NumberOfBuses;
DPRINT("ScsiPortInitialize(): Found HBA! (%x), adapter Id %d\n",
PortConfig->BusInterruptVector, PortConfig->InitiatorBusId[0]);
/* Scan the adapter for devices */
SpiScanAdapter (DeviceExtension);
/* 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);
}
/* Build the registry device map */
SpiBuildDeviceMap (DeviceExtension,
(PUNICODE_STRING)Argument2);
/* The same with LUN extension size */
if (PortConfig->SpecificLuExtensionSize != DeviceExtension->LunExtensionSize)
DeviceExtension->LunExtensionSize = PortConfig->SpecificLuExtensionSize;
/* Create the dos device link */
swprintf(DosNameBuffer,
L"\\??\\Scsi%lu:",
SystemConfig->ScsiPortCount);
RtlInitUnicodeString(&DosDeviceName,
DosNameBuffer);
IoCreateSymbolicLink(&DosDeviceName,
&DeviceName);
/* Update the system configuration info */
if (PortConfig->AtdiskPrimaryClaimed == TRUE)
SystemConfig->AtDiskPrimaryAddressClaimed = TRUE;
if (PortConfig->AtdiskSecondaryClaimed == TRUE)
SystemConfig->AtDiskSecondaryAddressClaimed = TRUE;
if (!((HwInitializationData->AdapterInterfaceType == PCIBus) &&
(HwInitializationData->VendorIdLength > 0) &&
(HwInitializationData->VendorId != NULL) &&
(HwInitializationData->DeviceIdLength > 0) &&
(HwInitializationData->DeviceId != NULL)))
{
/* Construct a resource list */
ResourceList = SpiConfigToResource(DeviceExtension,
PortConfig);
SystemConfig->ScsiPortCount++;
PortDeviceObject = NULL;
DeviceFound = TRUE;
}
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
{
DPRINT("HwFindAdapter() Result: %lu\n", Result);
DeviceExtension->MaxTargedIds = PortConfig->MaximumNumberOfTargets;
ExFreePool (PortConfig);
IoDeleteDevice (PortDeviceObject);
PortDeviceObject = NULL;
}
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;
//Status = STATUS_UNSUCCESFUL;
/* TODO: Allocate common buffer */
ASSERT(FALSE);
/* 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 = ExAllocatePool(NonPagedPool, Count * sizeof(SCSI_REQUEST_BLOCK_INFO));
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 = ExAllocatePool(PagedPool,
sizeof(PSCSI_BUS_SCAN_INFO) * DeviceExtension->PortConfig->NumberOfBuses
+ sizeof(ULONG));
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 = DeviceExtension->PortConfig->NumberOfBuses;
/* 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);
if (BusNumber >= MaxBus)
{
DPRINT("Scanned all buses!\n");
Status = STATUS_SUCCESS;
goto ByeBye;
}
if (Again == FALSE)
{
BusNumber++;
SlotNumber.u.AsULONG = 0;
}
DeviceFound = TRUE;
}
ByeBye:
/* Clean up the mess */
if (PortDeviceObject != NULL)
{
DPRINT("Delete device: %p\n", PortDeviceObject);
/* Clean up the mess */
SpiCleanupAfterInit(DeviceExtension);
DeviceExtension = PortDeviceObject->DeviceExtension;
/* Close registry keys */
if (ConfigInfo.ServiceKey != NULL)
ZwClose(ConfigInfo.ServiceKey);
if (DeviceExtension->PortCapabilities != NULL)
{
IoDisconnectInterrupt (DeviceExtension->Interrupt);
ExFreePool (DeviceExtension->PortCapabilities);
}
if (ConfigInfo.DeviceKey != NULL)
ZwClose(ConfigInfo.DeviceKey);
if (DeviceExtension->PortConfig != NULL)
{
ExFreePool (DeviceExtension->PortConfig);
}
if (ConfigInfo.BusKey != NULL)
ZwClose(ConfigInfo.BusKey);
IoDeleteDevice (PortDeviceObject);
}
if (ConfigInfo.AccessRanges != NULL)
ExFreePool(ConfigInfo.AccessRanges);
DPRINT("ScsiPortInitialize() done, Status = 0x%08X, DeviceFound = %b!\n",
Status, DeviceFound);
if (ConfigInfo.Parameter != NULL)
ExFreePool(ConfigInfo.Parameter);
return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS;
DPRINT("ScsiPortInitialize() done, Status = 0x%08X, DeviceFound = %b!\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);
LunInfo = Ptr;
}
ExFreePool(DeviceExtension->BusesConfig->BusScanInfo[Bus]);
}
ExFreePool(DeviceExtension->BusesConfig);
}
/* Free PortConfig */
if (DeviceExtension->PortConfig)
ExFreePool(DeviceExtension->PortConfig);
/* Free LUNs*/
for(Lun = 0; Lun < LUS_NUMBER; Lun++)
{
while (DeviceExtension->LunExtensionList[Lun])
{
Ptr = DeviceExtension->LunExtensionList[Lun];
DeviceExtension->LunExtensionList[Lun] = DeviceExtension->LunExtensionList[Lun]->Next;
ExFreePool(Ptr);
}
}
/* Free common buffer (if it exists) */
if (DeviceExtension->SrbExtensionBuffer != NULL &&
DeviceExtension->CommonBufferSize != 0)
{
if (!DeviceExtension->AdapterObject)
{
ExFreePool(DeviceExtension->SrbExtensionBuffer);
}
else
{
#if 0
HalFreeCommonBuffer(DeviceExtension->AdapterObject,
DeviceExtension->CommonBufferSize,
DeviceExtension->PhysicalCommonBuffer,
DeviceExtension->SrbExtensionBuffer,
FALSE);
#endif
}
}
/* Free SRB info */
if (DeviceExtension->SrbInfo != NULL)
ExFreePool(DeviceExtension->SrbInfo);
/* Unmap mapped addresses */
while (DeviceExtension->MappedAddressList != NULL)
{
MmUnmapIoSpace(DeviceExtension->MappedAddressList->MappedAddress,
DeviceExtension->MappedAddressList->NumberOfBytes);
Ptr = DeviceExtension->MappedAddressList;
DeviceExtension->MappedAddressList = DeviceExtension->MappedAddressList->NextMappedAddress;
ExFreePool(Ptr);
}
/* Finally delete the device object */
IoDeleteDevice(DeviceExtension->DeviceObject);
}
/*
* @unimplemented
@ -1491,6 +1857,187 @@ SpiResourceToConfig(IN PHW_INITIALIZATION_DATA HwInitializationData,
}
}
static PCM_RESOURCE_LIST
SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PPORT_CONFIGURATION_INFORMATION PortConfig)
{
PCONFIGURATION_INFORMATION ConfigInfo;
PCM_RESOURCE_LIST ResourceList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
PACCESS_RANGE AccessRange;
BOOLEAN Dma;
ULONG ListLength = 0, i, FullSize;
ULONG Interrupt;
/* Get current Atdisk usage from the system */
ConfigInfo = IoGetConfigurationInformation();
if (PortConfig->AtdiskPrimaryClaimed)
ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE;
if (PortConfig->AtdiskSecondaryClaimed)
ConfigInfo->AtDiskSecondaryAddressClaimed = TRUE;
/* Do we use DMA? */
if (PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE ||
PortConfig->DmaPort != SP_UNINITIALIZED_VALUE)
{
Dma = TRUE;
ListLength++;
}
else
{
Dma = FALSE;
}
/* How many interrupts to we have? */
if (DeviceExtension->HwInterrupt == NULL ||
(PortConfig->BusInterruptLevel == 0 &&
PortConfig->BusInterruptVector == 0))
{
Interrupt = 0;
}
else
{
Interrupt = 1;
ListLength++;
}
if (DeviceExtension->HwInterrupt != NULL &&
(PortConfig->BusInterruptLevel2 != 0 ||
PortConfig->BusInterruptVector2 != 0))
{
Interrupt++;
ListLength++;
}
/* How many access ranges do we use? */
AccessRange = &((*(PortConfig->AccessRanges))[0]);
for (i = 0; i < PortConfig->NumberOfAccessRanges; i++)
{
if (AccessRange->RangeLength != 0)
ListLength++;
AccessRange++;
}
/* Allocate the resource list, since we know its size now */
FullSize = sizeof(CM_RESOURCE_LIST) + (ListLength - 1) *
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, FullSize);
if (!ResourceList)
return NULL;
/* Zero it */
RtlZeroMemory(ResourceList, FullSize);
/* Initialize it */
ResourceList->Count = 1;
ResourceList->List[0].InterfaceType = PortConfig->AdapterInterfaceType;
ResourceList->List[0].BusNumber = PortConfig->SystemIoBusNumber;
ResourceList->List[0].PartialResourceList.Count = ListLength;
ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
/* Copy access ranges array over */
for (i = 0; i < PortConfig->NumberOfAccessRanges; i++)
{
AccessRange = &((*(PortConfig->AccessRanges))[i]);
/* If the range is empty - skip it */
if (AccessRange->RangeLength == 0)
continue;
if (AccessRange->RangeInMemory)
{
ResourceDescriptor->Type = CmResourceTypeMemory;
ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
}
else
{
ResourceDescriptor->Type = CmResourceTypePort;
ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
}
ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
ResourceDescriptor->u.Memory.Start = AccessRange->RangeStart;
ResourceDescriptor->u.Memory.Length = AccessRange->RangeLength;
ResourceDescriptor++;
}
/* If we use interrupt(s), copy them */
if (Interrupt)
{
ResourceDescriptor->Type = CmResourceTypeInterrupt;
if (PortConfig->AdapterInterfaceType == MicroChannel ||
PortConfig->InterruptMode == LevelSensitive)
{
ResourceDescriptor->ShareDisposition = CmResourceShareShared;
ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
}
else
{
ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
}
ResourceDescriptor->u.Interrupt.Level = PortConfig->BusInterruptLevel;
ResourceDescriptor->u.Interrupt.Vector = PortConfig->BusInterruptVector;
ResourceDescriptor->u.Interrupt.Affinity = 0;
ResourceDescriptor++;
Interrupt--;
}
/* Copy 2nd interrupt
FIXME: Stupid code duplication, remove */
if (Interrupt)
{
ResourceDescriptor->Type = CmResourceTypeInterrupt;
if (PortConfig->AdapterInterfaceType == MicroChannel ||
PortConfig->InterruptMode == LevelSensitive)
{
ResourceDescriptor->ShareDisposition = CmResourceShareShared;
ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
}
else
{
ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
}
ResourceDescriptor->u.Interrupt.Level = PortConfig->BusInterruptLevel;
ResourceDescriptor->u.Interrupt.Vector = PortConfig->BusInterruptVector;
ResourceDescriptor->u.Interrupt.Affinity = 0;
ResourceDescriptor++;
}
/* Copy DMA data */
if (Dma)
{
ResourceDescriptor->Type = CmResourceTypeDma;
ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
ResourceDescriptor->u.Dma.Channel = PortConfig->DmaChannel;
ResourceDescriptor->u.Dma.Port = PortConfig->DmaPort;
ResourceDescriptor->Flags = 0;
if (PortConfig->DmaChannel == SP_UNINITIALIZED_VALUE)
ResourceDescriptor->u.Dma.Channel = 0;
if (PortConfig->DmaPort == SP_UNINITIALIZED_VALUE)
ResourceDescriptor->u.Dma.Port = 0;
}
return ResourceList;
}
static BOOLEAN
SpiGetPciConfigData(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject,
@ -1838,7 +2385,7 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
*((PIO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer) =
DeviceExtension->PortCapabilities;
&DeviceExtension->PortCapabilities;
Irp->IoStatus.Information = sizeof(PIO_SCSI_CAPABILITIES);
}
@ -3843,7 +4390,7 @@ SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
*/
/* Set 'DMA Enabled' (REG_DWORD) value */
UlongData = (ULONG)!DeviceExtension->PortCapabilities->AdapterUsesPio;
UlongData = (ULONG)!DeviceExtension->PortCapabilities.AdapterUsesPio;
DPRINT(" DMA Enabled = %s\n", (UlongData) ? "TRUE" : "FALSE");
RtlInitUnicodeString(&ValueName,
L"DMA Enabled");

View file

@ -194,6 +194,7 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
ULONG MiniPortExtensionSize;
PPORT_CONFIGURATION_INFORMATION PortConfig;
PBUSES_CONFIGURATION_INFORMATION BusesConfig;
PVOID NonCachedExtension;
ULONG PortNumber;
LONG ActiveRequestCounter;
@ -223,6 +224,7 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
SCSI_PORT_INTERRUPT_DATA InterruptData;
ULONG CommonBufferSize;
/* SRB extension stuff*/
ULONG SrbExtensionSize;
PVOID SrbExtensionBuffer;
@ -231,12 +233,14 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
/* SRB information */
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
PSCSI_REQUEST_BLOCK_INFO FreeSrbInfo;
ULONG SrbDataCount;
PIO_SCSI_CAPABILITIES PortCapabilities;
IO_SCSI_CAPABILITIES PortCapabilities;
PDEVICE_OBJECT DeviceObject;
PCONTROLLER_OBJECT ControllerObject;
PHW_INITIALIZE HwInitialize;
PHW_STARTIO HwStartIo;
PHW_INTERRUPT HwInterrupt;
PHW_RESET_BUS HwResetBus;
@ -254,13 +258,17 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
PVOID MapRegisterBase;
/* Features */
BOOLEAN CachesData;
BOOLEAN SupportsTaggedQueuing;
BOOLEAN SupportsAutoSense;
BOOLEAN MultipleReqsPerLun;
BOOLEAN ReceiveEvent;
PHYSICAL_ADDRESS PhysicalAddress;
PVOID VirtualAddress;
ULONG CommonBufferLength;
ULONG InterruptLevel;
ULONG IoAddress;
BOOLEAN NeedSrbExtensionAlloc;
BOOLEAN NeedSrbDataAlloc;