* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: scsiport.c,v 1.37 2003/09/25 23:23:21 ekohl Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/storage/scsiport/scsiport.c
* PURPOSE: SCSI port driver
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
+ * Hartmut Birr
*/
/* INCLUDES *****************************************************************/
#include <ddk/srb.h>
#include <ddk/scsi.h>
#include <ddk/ntddscsi.h>
+#include <ddk/ntddstor.h>
+#include <ddk/ntdddisk.h>
+#include <stdio.h>
#define NDEBUG
#include <debug.h>
-
-#define VERSION "0.0.1"
-
#include "scsiport_int.h"
-//#define USE_DEVICE_QUEUES
-
/* TYPES *********************************************************************/
#define IRP_FLAG_COMPLETE 0x00000001
#define IRP_FLAG_NEXT 0x00000002
#define IRP_FLAG_NEXT_LU 0x00000004
-
/* GLOBALS *******************************************************************/
+static ULONG InternalDebugLevel = 0;
+
+static VOID
+SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PIRP NextIrp);
+
+static VOID
+SpiStartIo(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PIRP Irp);
+
static BOOLEAN
SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
IN ULONG BusNumber,
- IN OUT PULONG NextDeviceNumber,
- IN OUT PULONG NextFunctionNumber);
+ IN OUT PPCI_SLOT_NUMBER NextSlotNumber);
static NTSTATUS STDCALL
ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
-static VOID STDCALL
-ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp);
-
-static IO_ALLOCATION_ACTION STDCALL
-ScsiPortAllocateController(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN PVOID MapRegisterBase,
- IN PVOID Context);
-
static BOOLEAN STDCALL
ScsiPortStartPacket(IN OUT PVOID Context);
-static NTSTATUS
-ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
- IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension,
- IN ULONG PortCount,
- IN OUT PSCSI_PORT_DEVICE_EXTENSION *RealDeviceExtension);
static PSCSI_PORT_LUN_EXTENSION
SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR TargetId,
IN UCHAR Lun);
+static VOID
+SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension);
+
static PSCSI_PORT_LUN_EXTENSION
SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun);
+static NTSTATUS
+SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PSCSI_REQUEST_BLOCK Srb,
+ IN OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN OUT PKEVENT Event);
+
static VOID
-SpiInquirePort (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
+SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
static ULONG
SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN PVOID ServiceContext);
static VOID STDCALL
-ScsiPortDpcForIsr(IN PKDPC Dpc,
- IN PDEVICE_OBJECT DpcDeviceObject,
- IN PIRP DpcIrp,
- IN PVOID DpcContext);
+ScsiPortDpc(IN PKDPC Dpc,
+ IN PDEVICE_OBJECT DpcDeviceObject,
+ IN PIRP DpcIrp,
+ IN PVOID DpcContext);
static VOID STDCALL
ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
PVOID Context);
static PSCSI_REQUEST_BLOCK
-ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
- PSCSI_REQUEST_BLOCK OriginalSrb);
+ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb);
static NTSTATUS
SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PUNICODE_STRING RegistryPath);
+static VOID
+SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PSCSI_REQUEST_BLOCK Srb);
+
+static VOID
+SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PSCSI_REQUEST_BLOCK Srb);
+
+
+static NTSTATUS
+SpiScsiMiniport(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp);
/* FUNCTIONS *****************************************************************/
char Buffer[256];
va_list ap;
-#if 0
- if (DebugPrintLevel > InternalDebugLevel)
+ if (DebugPrintLevel >= InternalDebugLevel)
return;
-#endif
va_start(ap, DebugMessage);
vsprintf(Buffer, DebugMessage, ap);
IN UCHAR Lun,
IN UCHAR SrbStatus)
{
- DPRINT("ScsiPortCompleteRequest()\n");
- UNIMPLEMENTED;
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ PSCSI_PORT_LUN_EXTENSION LunExtension;
+ PLIST_ENTRY Entry;
+ PIRP Irp;
+ PSCSI_REQUEST_BLOCK Srb;
+
+ DPRINT("ScsiPortCompleteRequest(HwDeviceExtension %x, PathId %d, TargetId %d, Lun %d, SrbStatus %x)\n",
+ HwDeviceExtension, PathId, TargetId, Lun, SrbStatus);
+
+ DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+ SCSI_PORT_DEVICE_EXTENSION,
+ MiniPortDeviceExtension);
+
+ Entry = DeviceExtension->LunExtensionListHead.Flink;
+ while (Entry != &DeviceExtension->LunExtensionListHead)
+ {
+ LunExtension = CONTAINING_RECORD(Entry,
+ SCSI_PORT_LUN_EXTENSION,
+ List);
+
+
+
+ if (PathId == (UCHAR)SP_UNTAGGED ||
+ (PathId == LunExtension->PathId && TargetId == (UCHAR)SP_UNTAGGED) ||
+ (PathId == LunExtension->PathId && TargetId == LunExtension->TargetId && Lun == (UCHAR)SP_UNTAGGED) ||
+ (PathId == LunExtension->PathId && TargetId == LunExtension->TargetId && Lun == LunExtension->Lun))
+ {
+ Irp = LunExtension->NextIrp;
+ while (Irp)
+ {
+ Srb = (PSCSI_REQUEST_BLOCK)Irp->Tail.Overlay.DriverContext[3];
+ if (Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)
+ {
+ Srb->SrbStatus = SrbStatus;
+ ScsiPortNotification(RequestComplete,
+ HwDeviceExtension,
+ Srb);
+ }
+ Irp = Irp->Tail.Overlay.DriverContext[1];
+ }
+ }
+ Entry = Entry->Flink;
+ }
}
/*
* @implemented
*/
+#undef ScsiPortConvertPhysicalAddressToUlong
ULONG STDCALL
ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
{
ULONG AddressSpace;
PVOID MappedAddress;
- DPRINT("ScsiPortGetDeviceBase() called\n");
+ DPRINT ("ScsiPortGetDeviceBase() called\n");
AddressSpace = (ULONG)InIoSpace;
if (HalTranslateBusAddress(BusType,
MappedAddress = MmMapIoSpace(TranslatedAddress,
NumberOfBytes,
- FALSE);
+ MmNonCached);
DeviceBase = ExAllocatePool(NonPagedPool,
sizeof(SCSI_PORT_DEVICE_BASE));
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
SCSI_PHYSICAL_ADDRESS PhysicalAddress;
+ SCSI_PHYSICAL_ADDRESS NextPhysicalAddress;
ULONG BufferLength = 0;
ULONG Offset;
+ PVOID EndAddress;
DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
HwDeviceExtension, Srb, VirtualAddress, Length);
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
- *Length = 0;
-
+ if (Length != NULL)
+ {
+ *Length = 0;
+ }
if (Srb == NULL)
{
- if ((ULONG_PTR)DeviceExtension->VirtualAddress > (ULONG_PTR)VirtualAddress)
+ EndAddress = (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + DeviceExtension->CommonBufferLength);
+ if (VirtualAddress >= DeviceExtension->VirtualAddress && VirtualAddress < EndAddress)
+ {
+ Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
+ PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset;
+ BufferLength = (ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress;
+ }
+ else
+ {
+ /*
+ * The given virtual address is not within the range
+ * of the drivers uncached extension or srb extension.
+ */
+ /*
+ * FIXME:
+ * Check if the address is a sense info buffer of an active srb.
+ */
+ PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
+ if (PhysicalAddress.QuadPart == 0LL)
+ {
+ CHECKPOINT;
+ return PhysicalAddress;
+ }
+ BufferLength = PAGE_SIZE - PhysicalAddress.u.LowPart % PAGE_SIZE;
+ }
+ }
+ else
+ {
+ EndAddress = (PVOID)((ULONG_PTR)Srb->DataBuffer + Srb->DataTransferLength);
+ if (VirtualAddress == NULL)
{
- PhysicalAddress.QuadPart = 0ULL;
- return PhysicalAddress;
+ VirtualAddress = Srb->DataBuffer;
+ }
+ else if (VirtualAddress < Srb->DataBuffer || VirtualAddress >= EndAddress)
+ {
+ EndAddress = (PVOID)((ULONG_PTR)Srb->SenseInfoBuffer + Srb->SenseInfoBufferLength);
+ if (VirtualAddress < Srb->SenseInfoBuffer || VirtualAddress >= EndAddress)
+ {
+ PhysicalAddress.QuadPart = 0LL;
+ CHECKPOINT;
+ return PhysicalAddress;
+ }
}
- Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
- if (Offset >= DeviceExtension->CommonBufferLength)
+ PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
+ if (PhysicalAddress.QuadPart == 0LL)
{
- PhysicalAddress.QuadPart = 0ULL;
+ CHECKPOINT;
return PhysicalAddress;
}
- PhysicalAddress.QuadPart =
- DeviceExtension->PhysicalAddress.QuadPart + (ULONGLONG)Offset;
- BufferLength = DeviceExtension->CommonBufferLength - Offset;
+ BufferLength = PAGE_SIZE - (ULONG_PTR)VirtualAddress % PAGE_SIZE;
+ while ((ULONG_PTR)VirtualAddress + BufferLength < (ULONG_PTR)EndAddress)
+ {
+ NextPhysicalAddress = MmGetPhysicalAddress((PVOID)((ULONG_PTR)VirtualAddress + BufferLength));
+ if (PhysicalAddress.QuadPart + BufferLength != NextPhysicalAddress.QuadPart)
+ {
+ break;
+ }
+ BufferLength += PAGE_SIZE;
+ }
+ if ((ULONG_PTR)VirtualAddress + BufferLength >= (ULONG_PTR)EndAddress)
+ {
+ BufferLength = (ULONG)((ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress);
+ }
}
- else
+ if (Length != NULL)
{
- /* FIXME */
- DPRINT1("Srb != NULL is not implemented yet!\n");
- UNIMPLEMENTED;
+ *Length = BufferLength;
}
-
- *Length = BufferLength;
-
+ DPRINT("Address %I64x, Length %d\n", PhysicalAddress.QuadPart, BufferLength);
return PhysicalAddress;
}
* @unimplemented
*/
PSCSI_REQUEST_BLOCK STDCALL
-ScsiPortGetSrb(IN PVOID DeviceExtension,
+ScsiPortGetSrb(IN PVOID HwDeviceExtension,
IN UCHAR PathId,
IN UCHAR TargetId,
IN UCHAR Lun,
IN LONG QueueTag)
{
- DPRINT("ScsiPortGetSrb()\n");
+ DPRINT1("ScsiPortGetSrb() unimplemented\n");
UNIMPLEMENTED;
+ return NULL;
}
return NULL;
}
}
+ if (DeviceExtension->SrbExtensionSize > 0)
+ {
+ PVOID Buffer;
+ DeviceExtension->CurrentSrbExtensions = 0;
+ if (DeviceExtension->PortConfig->MultipleRequestPerLu)
+ {
+ DeviceExtension->MaxSrbExtensions = 1024;
+ }
+ else
+ {
+ DeviceExtension->MaxSrbExtensions = 32;
+ }
+ Buffer = ExAllocatePool(NonPagedPool, ROUND_UP(DeviceExtension->MaxSrbExtensions / 8, sizeof(ULONG)));
+ if (Buffer == NULL)
+ {
+ KEBUGCHECK(0);
+ return NULL;
+ }
+ RtlInitializeBitMap(&DeviceExtension->SrbExtensionAllocMap, Buffer, DeviceExtension->MaxSrbExtensions);
+ RtlClearAllBits(&DeviceExtension->SrbExtensionAllocMap);
+ }
/* Allocate a common DMA buffer */
- DeviceExtension->CommonBufferLength = NumberOfBytes;
+ DeviceExtension->CommonBufferLength =
+ NumberOfBytes + PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * DeviceExtension->MaxSrbExtensions);
DeviceExtension->VirtualAddress =
HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
DeviceExtension->CommonBufferLength,
return NULL;
}
- return DeviceExtension->VirtualAddress;
+ return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress +
+ PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * DeviceExtension->MaxSrbExtensions));
}
IN PVOID HwContext)
{
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
- PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
- PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension;
- PSCSI_PORT_DEVICE_EXTENSION RealDeviceExtension;
+// PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
PCONFIGURATION_INFORMATION SystemConfig;
PPORT_CONFIGURATION_INFORMATION PortConfig;
+ ULONG DeviceExtensionSize;
+ ULONG PortConfigSize;
BOOLEAN Again;
+ BOOLEAN DeviceFound = FALSE;
ULONG i;
ULONG Result;
NTSTATUS Status;
ULONG MaxBus;
- PACCESS_RANGE AccessRanges;
- ULONG ExtensionSize;
- ULONG NextBusNumber = 0;
- ULONG NextDeviceNumber = 0;
- ULONG NextFunctionNumber = 0;
+ ULONG BusNumber;
+ 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;
- DPRINT("ScsiPortInitialize() called!\n");
+ DPRINT ("ScsiPortInitialize() called!\n");
+#if 0
+ DPRINT1("HwInitializationDataSize: %d\n", HwInitializationData->HwInitializationDataSize);
+ DPRINT1("AdapterInterfaceType: %d\n", HwInitializationData->AdapterInterfaceType);
+ DPRINT1("HwInitialize: %x\n", HwInitializationData->HwInitialize);
+ DPRINT1("HwStartIo: %x\n", HwInitializationData->HwStartIo);
+ DPRINT1("HwInterrupt: %x\n", HwInitializationData->HwInterrupt);
+ DPRINT1("HwFindAdapter: %x\n", HwInitializationData->HwFindAdapter);
+ DPRINT1("HwResetBus: %x\n", HwInitializationData->HwResetBus);
+ DPRINT1("HwDmaStarted: %x\n", HwInitializationData->HwDmaStarted);
+ DPRINT1("HwAdapterState: %x\n", HwInitializationData->HwAdapterState);
+ DPRINT1("DeviceExtensionSize: %d\n", HwInitializationData->DeviceExtensionSize);
+ DPRINT1("SpecificLuExtensionSize: %d\n", HwInitializationData->SpecificLuExtensionSize);
+ DPRINT1("SrbExtensionSize: %d\n", HwInitializationData->SrbExtensionSize);
+ DPRINT1("NumberOfAccessRanges: %d\n", HwInitializationData->NumberOfAccessRanges);
+ DPRINT1("Reserved: %x\n", HwInitializationData->Reserved);
+ DPRINT1("MapBuffers: %d\n", HwInitializationData->MapBuffers);
+ DPRINT1("NeedPhysicalAddresses: %d\n", HwInitializationData->NeedPhysicalAddresses);
+ DPRINT1("TaggedQueueing: %d\n", HwInitializationData->TaggedQueueing);
+ DPRINT1("AutoRequestSense: %d\n", HwInitializationData->AutoRequestSense);
+ DPRINT1("MultipleRequestPerLu: %d\n", HwInitializationData->MultipleRequestPerLu);
+ DPRINT1("ReceiveEvent: %d\n", HwInitializationData->ReceiveEvent);
+ DPRINT1("VendorIdLength: %d\n", HwInitializationData->VendorIdLength);
+ DPRINT1("VendorId: %x\n", HwInitializationData->VendorId);
+ DPRINT1("ReservedUshort: %d\n", HwInitializationData->ReservedUshort);
+ DPRINT1("DeviceIdLength: %d\n", HwInitializationData->DeviceIdLength);
+ DPRINT1("DeviceId: %x\n", HwInitializationData->DeviceId);
+#endif
if ((HwInitializationData->HwInitialize == NULL) ||
(HwInitializationData->HwStartIo == NULL) ||
(HwInitializationData->HwInterrupt == NULL) ||
(HwInitializationData->HwResetBus == NULL))
return(STATUS_INVALID_PARAMETER);
- DriverObject->DriverStartIo = ScsiPortStartIo;
- DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)ScsiPortCreateClose;
- DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)ScsiPortCreateClose;
- DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)ScsiPortDeviceControl;
- DriverObject->MajorFunction[IRP_MJ_SCSI] = (PDRIVER_DISPATCH)ScsiPortDispatchScsi;
-
+ DriverObject->DriverStartIo = NULL;
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
+ DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
SystemConfig = IoGetConfigurationInformation();
- ExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
- HwInitializationData->DeviceExtensionSize;
- PseudoDeviceExtension = ExAllocatePool(PagedPool,
- ExtensionSize);
- RtlZeroMemory(PseudoDeviceExtension,
- ExtensionSize);
- PseudoDeviceExtension->Length = ExtensionSize;
- PseudoDeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
- PseudoDeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
- PseudoDeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
- PseudoDeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
-
- PortConfig = &PseudoDeviceExtension->PortConfig;
-
- PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
- PortConfig->SystemIoBusNumber = 0;
- PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
-// PortConfig->BusInterruptLevel = oz_dev_pci_conf_inb (pciconfp, OZ_DEV_PCI_CONF_B_INTLINE);
-// PortConfig->BusInterruptVector = ;
- PortConfig->InterruptMode =
- (PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched;
- PortConfig->MaximumTransferLength = SP_UNINITIALIZED_VALUE;
- PortConfig->NumberOfPhysicalBreaks = SP_UNINITIALIZED_VALUE;
- PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE;
- PortConfig->DmaPort = SP_UNINITIALIZED_VALUE;
-// PortConfig->DmaWidth =
-// PortConfig->DmaSpeed =
-// PortConfig->AlignmentMask =
- PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
-// PortConfig->NumberOfBuses =
-
- for (i = 0; i < SCSI_MAXIMUM_BUSES; i++)
- PortConfig->InitiatorBusId[i] = 255;
-
-// PortConfig->ScatterGather =
-// PortConfig->Master =
-// PortConfig->CachesData =
-// PortConfig->AdapterScansDown =
- PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
- PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
-// PortConfig->Dma32BitAddresses =
-// PortConfig->DemandMode =
- PortConfig->MapBuffers = HwInitializationData->MapBuffers;
- PortConfig->NeedPhysicalAddresses = HwInitializationData->NeedPhysicalAddresses;
- PortConfig->TaggedQueuing = HwInitializationData->TaggedQueuing;
- PortConfig->AutoRequestSense = HwInitializationData->AutoRequestSense;
- PortConfig->MultipleRequestPerLu = HwInitializationData->MultipleRequestPerLu;
- PortConfig->ReceiveEvent = HwInitializationData->ReceiveEvent;
-// PortConfig->RealModeInitialized =
-// PortConfig->BufferAccessScsiPortControlled =
- PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
-// PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
- PortConfig->SlotNumber = 0;
-
- PortConfig->AccessRanges =
- ExAllocatePool(PagedPool,
- sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges);
-
-
- MaxBus = (PortConfig->AdapterInterfaceType == PCIBus) ? 8 : 1;
+ DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
+ HwInitializationData->DeviceExtensionSize;
+ PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) +
+ HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE);
+
+ MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1;
DPRINT("MaxBus: %lu\n", MaxBus);
+ PortDeviceObject = NULL;
+ BusNumber = 0;
+ SlotNumber.u.AsULONG = 0;
while (TRUE)
{
- DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
+ /* 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))
+ {
+ DbgPrint ("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
+ PortDeviceObject = NULL;
+ goto ByeBye;
+ }
+
+ DPRINT ("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
+
+ /* Increase the stacksize. We reenter our device on IOCTL_SCSI_MINIPORT */
+ PortDeviceObject->StackSize++;
+
+ /* Set the buffering strategy here... */
+ PortDeviceObject->Flags |= DO_DIRECT_IO;
+ PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
+
+ DeviceExtension = PortDeviceObject->DeviceExtension;
+ RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
+ DeviceExtension->Length = DeviceExtensionSize;
+ DeviceExtension->DeviceObject = PortDeviceObject;
+ DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
+
+ DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
+ DeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
+ DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
+ DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
+ DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
+
+ DeviceExtension->AdapterObject = NULL;
+ DeviceExtension->MapRegisterCount = 0;
+ DeviceExtension->PhysicalAddress.QuadPart = 0ULL;
+ DeviceExtension->VirtualAddress = NULL;
+ DeviceExtension->CommonBufferLength = 0;
- InitializeListHead(&PseudoDeviceExtension->DeviceBaseListHead);
+ /* Initialize the device base list */
+ InitializeListHead (&DeviceExtension->DeviceBaseListHead);
-// RtlZeroMemory(AccessRanges,
-// sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges);
+ /* Initialize the irp lists */
+ InitializeListHead (&DeviceExtension->PendingIrpListHead);
+ DeviceExtension->NextIrp = NULL;
+ DeviceExtension->PendingIrpCount = 0;
+ DeviceExtension->ActiveIrpCount = 0;
- PseudoDeviceExtension->AdapterObject = NULL;
- PseudoDeviceExtension->MapRegisterCount = 0;
- PseudoDeviceExtension->PhysicalAddress.QuadPart = 0ULL;
- PseudoDeviceExtension->VirtualAddress = NULL;
- PseudoDeviceExtension->CommonBufferLength = 0;
+ /* Initialize LUN-Extension list */
+ InitializeListHead (&DeviceExtension->LunExtensionListHead);
- RtlZeroMemory(PseudoDeviceExtension->MiniPortDeviceExtension,
- PseudoDeviceExtension->MiniPortExtensionSize);
+ /* Initialize the spin lock in the controller extension */
+ KeInitializeSpinLock (&DeviceExtension->Lock);
+ /* Initialize the DPC object */
+ IoInitializeDpcRequest (PortDeviceObject,
+ ScsiPortDpc);
+
+ /* Initialize the device timer */
+ DeviceExtension->TimerState = IDETimerIdle;
+ DeviceExtension->TimerCount = 0;
+ IoInitializeTimer (PortDeviceObject,
+ ScsiPortIoTimer,
+ DeviceExtension);
+
+ /* Allocate and initialize port configuration info */
+ DeviceExtension->PortConfig = ExAllocatePool (NonPagedPool,
+ PortConfigSize);
+ if (DeviceExtension->PortConfig == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto ByeBye;
+ }
+ RtlZeroMemory (DeviceExtension->PortConfig,
+ PortConfigSize);
+
+ PortConfig = DeviceExtension->PortConfig;
+ PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
+ PortConfig->SystemIoBusNumber = BusNumber;
+ PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
+ PortConfig->InterruptMode =
+ (PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched;
+ PortConfig->MaximumTransferLength = SP_UNINITIALIZED_VALUE;
+ PortConfig->NumberOfPhysicalBreaks = SP_UNINITIALIZED_VALUE;
+ PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE;
+ PortConfig->DmaPort = SP_UNINITIALIZED_VALUE;
+ PortConfig->DmaWidth = 0;
+ PortConfig->DmaSpeed = Compatible;
+ PortConfig->AlignmentMask = 0;
+ PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
+ PortConfig->NumberOfBuses = 0;
+
+ for (i = 0; i < SCSI_MAXIMUM_BUSES; i++)
+ PortConfig->InitiatorBusId[i] = 255;
+
+ PortConfig->ScatterGather = FALSE;
+ PortConfig->Master = FALSE;
+ PortConfig->CachesData = FALSE;
+ PortConfig->AdapterScansDown = FALSE;
+ PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
+ PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
+ PortConfig->Dma32BitAddresses = FALSE;
+ PortConfig->DemandMode = FALSE;
+ PortConfig->MapBuffers = HwInitializationData->MapBuffers;
+ PortConfig->NeedPhysicalAddresses = HwInitializationData->NeedPhysicalAddresses;
+ PortConfig->TaggedQueuing = HwInitializationData->TaggedQueuing;
+ PortConfig->AutoRequestSense = HwInitializationData->AutoRequestSense;
+ PortConfig->MultipleRequestPerLu = HwInitializationData->MultipleRequestPerLu;
+ PortConfig->ReceiveEvent = HwInitializationData->ReceiveEvent;
+ PortConfig->RealModeInitialized = FALSE;
+ PortConfig->BufferAccessScsiPortControlled = FALSE;
+ PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
+// PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
+
+ PortConfig->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
+ PortConfig->SpecificLuExtensionSize = HwInitializationData->SpecificLuExtensionSize;
+
+ PortConfig->AccessRanges = (ACCESS_RANGE(*)[])(PortConfig + 1);
+
+ /* Search for matching PCI device */
if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
(HwInitializationData->VendorIdLength > 0) &&
(HwInitializationData->VendorId != NULL) &&
HwInitializationData->DeviceId);
if (!SpiGetPciConfigData (HwInitializationData,
- &PseudoDeviceExtension->PortConfig,
- NextBusNumber,
- &NextDeviceNumber,
- &NextFunctionNumber))
+ PortConfig,
+ BusNumber,
+ &SlotNumber))
{
- ExFreePool(PortConfig->AccessRanges);
- ExFreePool(PseudoDeviceExtension);
-
- return STATUS_UNSUCCESSFUL;
+ Status = STATUS_UNSUCCESSFUL;
+ goto ByeBye;
}
}
/* Note: HwFindAdapter is called once for each bus */
Again = FALSE;
- Result = (HwInitializationData->HwFindAdapter)(&PseudoDeviceExtension->MiniPortDeviceExtension,
+ DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
+ Result = (HwInitializationData->HwFindAdapter)(&DeviceExtension->MiniPortDeviceExtension,
HwContext,
- 0, /* BusInformation */
- "", /* ArgumentString */
- &PseudoDeviceExtension->PortConfig,
+ 0, /* BusInformation */
+ "", /* ArgumentString */
+ PortConfig,
&Again);
DPRINT("HwFindAdapter() Result: %lu Again: %s\n",
Result, (Again) ? "True" : "False");
if (Result == SP_RETURN_FOUND)
{
- DPRINT("ScsiPortInitialize(): Found HBA!\n");
+ DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig->BusInterruptVector);
- Status = ScsiPortCreatePortDevice(DriverObject,
- PseudoDeviceExtension,
- SystemConfig->ScsiPortCount,
- &RealDeviceExtension);
+#if 0
+ DPRINT1("SystemIoBusNumber: %x\n", PortConfig->SystemIoBusNumber);
+ DPRINT1("AdapterInterfaceType: %x\n", PortConfig->AdapterInterfaceType);
+ DPRINT1("BusInterruptLevel: %x\n", PortConfig->BusInterruptLevel);
+ DPRINT1("BusInterruptVector: %x\n", PortConfig->BusInterruptVector);
+ DPRINT1("InterruptMode: %x\n", PortConfig->InterruptMode);
+ DPRINT1("MaximumTransferLength: %x\n", PortConfig->MaximumTransferLength);
+ DPRINT1("NumberOfPhysicalBreaks: %x\n", PortConfig->NumberOfPhysicalBreaks);
+ DPRINT1("DmaChannel: %x\n", PortConfig->DmaChannel);
+ DPRINT1("DmaPort: %d\n", PortConfig->DmaPort);
+ DPRINT1("DmaWidth: %d\n", PortConfig->DmaWidth);
+ DPRINT1("DmaSpeed: %d\n", PortConfig->DmaSpeed);
+ DPRINT1("AlignmentMask: %d\n", PortConfig->AlignmentMask);
+ DPRINT1("NumberOfAccessRanges: %d\n", PortConfig->NumberOfAccessRanges);
+ DPRINT1("NumberOfBuses: %d\n", PortConfig->NumberOfBuses);
+ DPRINT1("ScatterGather: %d\n", PortConfig->ScatterGather);
+ DPRINT1("Master: %d\n", PortConfig->Master);
+ DPRINT1("CachesData: %d\n", PortConfig->CachesData);
+ DPRINT1("AdapterScansDown: %d\n", PortConfig->AdapterScansDown);
+ DPRINT1("AtdiskPrimaryClaimed: %d\n", PortConfig->AtdiskPrimaryClaimed);
+ DPRINT1("AtdiskSecondaryClaimed: %d\n", PortConfig->AtdiskSecondaryClaimed);
+ DPRINT1("Dma32BitAddresses: %d\n", PortConfig->Dma32BitAddresses);
+ DPRINT1("DemandMode: %d\n", PortConfig->DemandMode);
+ DPRINT1("MapBuffers: %d\n", PortConfig->MapBuffers);
+ DPRINT1("NeedPhysicalAddresses: %d\n", PortConfig->NeedPhysicalAddresses);
+ DPRINT1("TaggedQueuing: %d\n", PortConfig->TaggedQueuing);
+ DPRINT1("AutoRequestSense: %d\n", PortConfig->AutoRequestSense);
+ DPRINT1("MultipleRequestPerLu: %d\n", PortConfig->MultipleRequestPerLu);
+ DPRINT1("ReceiveEvent: %d\n", PortConfig->ReceiveEvent);
+ DPRINT1("RealModeInitialized: %d\n", PortConfig->RealModeInitialized);
+ DPRINT1("BufferAccessScsiPortControlled: %d\n", PortConfig->BufferAccessScsiPortControlled);
+ DPRINT1("MaximumNumberOfTargets: %d\n", PortConfig->MaximumNumberOfTargets);
+ DPRINT1("SlotNumber: %d\n", PortConfig->SlotNumber);
+ DPRINT1("BusInterruptLevel2: %x\n", PortConfig->BusInterruptLevel2);
+ DPRINT1("BusInterruptVector2: %x\n", PortConfig->BusInterruptVector2);
+ DPRINT1("InterruptMode2: %x\n", PortConfig->InterruptMode2);
+ DPRINT1("DmaChannel2: %d\n", PortConfig->DmaChannel2);
+ DPRINT1("DmaPort2: %d\n", PortConfig->DmaPort2);
+ DPRINT1("DmaWidth2: %d\n", PortConfig->DmaWidth2);
+ DPRINT1("DmaSpeed2: %d\n", PortConfig->DmaSpeed2);
+ DPRINT1("DeviceExtensionSize: %d\n", PortConfig->DeviceExtensionSize);
+ DPRINT1("SpecificLuExtensionSize: %d\n", PortConfig->SpecificLuExtensionSize);
+ DPRINT1("SrbExtensionSize: %d\n", PortConfig->SrbExtensionSize);
+
+#endif
+
+ if (DeviceExtension->VirtualAddress == NULL && DeviceExtension->SrbExtensionSize)
+ {
+ ScsiPortGetUncachedExtension(&DeviceExtension->MiniPortDeviceExtension,
+ PortConfig,
+ 0);
+ }
+ /* Register an interrupt handler for this device */
+ MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,
+ PortConfig->SystemIoBusNumber,
+ PortConfig->BusInterruptLevel,
+#if 1
+/*
+ * FIXME:
+ * Something is wrong in our interrupt conecting code.
+ * The promise Ultra100TX driver returns 0 for BusInterruptVector
+ * and a nonzero value for BusInterruptLevel. The driver does only
+ * work with this fix.
+ */
+ PortConfig->BusInterruptLevel,
+#else
+ PortConfig->BusInterruptVector,
+#endif
+ &Dirql,
+ &Affinity);
+ DPRINT("AdapterInterfaceType %x, SystemIoBusNumber %x, BusInterruptLevel %x, BusInterruptVector %x\n",
+ PortConfig->AdapterInterfaceType, PortConfig->SystemIoBusNumber,
+ PortConfig->BusInterruptLevel, PortConfig->BusInterruptVector);
+ Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
+ ScsiPortIsr,
+ DeviceExtension,
+ NULL,
+ MappedIrq,
+ Dirql,
+ Dirql,
+ PortConfig->InterruptMode,
+ TRUE,
+ Affinity,
+ FALSE);
if (!NT_SUCCESS(Status))
{
- DbgPrint("ScsiPortCreatePortDevice() failed! (Status 0x%lX)\n", Status);
+ DbgPrint("Could not connect interrupt %d\n",
+ PortConfig->BusInterruptVector);
+ goto ByeBye;
+ }
+
+ if (!(HwInitializationData->HwInitialize)(&DeviceExtension->MiniPortDeviceExtension))
+ {
+ DbgPrint("HwInitialize() failed!");
+ Status = STATUS_UNSUCCESSFUL;
+ goto ByeBye;
+ }
- ExFreePool(PortConfig->AccessRanges);
- ExFreePool(PseudoDeviceExtension);
+ /* 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;
+ }
- return(Status);
+ PortCapabilities = DeviceExtension->PortCapabilities;
+ PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
+ if (PortConfig->ScatterGather == FALSE ||
+ PortConfig->NumberOfPhysicalBreaks >= (0x100000000LL >> PAGE_SHIFT) ||
+ PortConfig->MaximumTransferLength < PortConfig->NumberOfPhysicalBreaks * PAGE_SIZE)
+ {
+ PortCapabilities->MaximumTransferLength =
+ PortConfig->MaximumTransferLength;
+ }
+ else
+ {
+ PortCapabilities->MaximumTransferLength =
+ PortConfig->NumberOfPhysicalBreaks * PAGE_SIZE;
}
- /* Get inquiry data */
- SpiInquirePort (RealDeviceExtension);
+ 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 */
+
+ /* Scan the adapter for devices */
+ SpiScanAdapter (DeviceExtension);
/* Build the registry device map */
- SpiBuildDeviceMap (RealDeviceExtension,
+ SpiBuildDeviceMap (DeviceExtension,
(PUNICODE_STRING)Argument2);
+ /* Create the dos device link */
+ swprintf(DosNameBuffer,
+ L"\\??\\Scsi%lu:",
+ SystemConfig->ScsiPortCount);
+ RtlInitUnicodeString(&DosDeviceName,
+ DosNameBuffer);
+ IoCreateSymbolicLink(&DosDeviceName,
+ &DeviceName);
+
/* Update the system configuration info */
- SystemConfig->AtDiskPrimaryAddressClaimed = PortConfig->AtdiskPrimaryClaimed;
- SystemConfig->AtDiskSecondaryAddressClaimed = PortConfig->AtdiskSecondaryClaimed;
+ if (PortConfig->AtdiskPrimaryClaimed == TRUE)
+ SystemConfig->AtDiskPrimaryAddressClaimed = TRUE;
+ if (PortConfig->AtdiskSecondaryClaimed == TRUE)
+ SystemConfig->AtDiskSecondaryAddressClaimed = TRUE;
+
SystemConfig->ScsiPortCount++;
+ PortDeviceObject = NULL;
+ DeviceFound = TRUE;
}
-
- if (Again == FALSE)
+ else
{
- PortConfig->SystemIoBusNumber++;
- PortConfig->SlotNumber = 0;
- NextBusNumber++;
- NextDeviceNumber = 0;
- NextFunctionNumber = 0;
+ DPRINT("HwFindAdapter() Result: %lu\n", Result);
+
+ ExFreePool (PortConfig);
+ IoDeleteDevice (PortDeviceObject);
+ PortDeviceObject = NULL;
}
- DPRINT("Bus: %lu MaxBus: %lu\n", PortConfig->SystemIoBusNumber, MaxBus);
- if (PortConfig->SystemIoBusNumber >= MaxBus)
+ DPRINT("Bus: %lu MaxBus: %lu\n", BusNumber, MaxBus);
+ if (BusNumber >= MaxBus)
{
DPRINT("Scanned all buses!\n");
- break;
+ Status = STATUS_SUCCESS;
+ goto ByeBye;
+ }
+
+ if (Again == FALSE)
+ {
+ BusNumber++;
+ SlotNumber.u.AsULONG = 0;
}
}
- ExFreePool(PortConfig->AccessRanges);
- ExFreePool(PseudoDeviceExtension);
+ByeBye:
+ /* Clean up the mess */
+ if (PortDeviceObject != NULL)
+ {
+ DPRINT("Delete device: %p\n", PortDeviceObject);
+
+ DeviceExtension = PortDeviceObject->DeviceExtension;
+
+ if (DeviceExtension->PortCapabilities != NULL)
+ {
+ IoDisconnectInterrupt (DeviceExtension->Interrupt);
+ ExFreePool (DeviceExtension->PortCapabilities);
+ }
+
+ if (DeviceExtension->PortConfig != NULL)
+ {
+ ExFreePool (DeviceExtension->PortConfig);
+ }
+
+ IoDeleteDevice (PortDeviceObject);
+ }
DPRINT("ScsiPortInitialize() done!\n");
- return(STATUS_SUCCESS);
+ return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS;
}
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
DPRINT1("ScsiPortLogError() called\n");
+ DPRINT1("Srb %x, PathId %d, TargetId %d, Lun %d, ErrorCode %x, UniqueId %x\n",
+ Srb, PathId, TargetId, Lun, ErrorCode, UniqueId);
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
SCSI_PORT_DEVICE_EXTENSION,
DPRINT("DeviceExtension %p\n", DeviceExtension);
- DPRINT("Initializing = %s\n", (DeviceExtension->Initializing)?"TRUE":"FALSE");
-
- if (DeviceExtension->Initializing == TRUE)
- return;
-
va_start(ap, HwDeviceExtension);
switch (NotificationType)
Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);
DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
- DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
+ DeviceExtension->Flags |= IRP_FLAG_COMPLETE;
+ Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
}
break;
case NextRequest:
DPRINT("Notify: NextRequest\n");
- DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
+ DeviceExtension->Flags |= IRP_FLAG_NEXT;
break;
case NextLuRequest:
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
+ PSCSI_PORT_LUN_EXTENSION LunExtension;
PathId = (UCHAR) va_arg (ap, int);
TargetId = (UCHAR) va_arg (ap, int);
Lun = (UCHAR) va_arg (ap, int);
- DPRINT1 ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
+ DPRINT ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
PathId, TargetId, Lun);
- /* FIXME: Implement it! */
-
-// DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
+ LunExtension = SpiGetLunExtension(DeviceExtension,
+ PathId,
+ TargetId,
+ Lun);
+ if (LunExtension)
+ {
+ DeviceExtension->Flags |= IRP_FLAG_NEXT_LU;
+ LunExtension->Flags |= IRP_FLAG_NEXT_LU;
+ }
}
break;
DPRINT1 ("Unsupported notification %lu\n", NotificationType);
break;
}
+ if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
+ {
+ IoRequestDpc(DeviceExtension->DeviceObject,
+ NULL,
+ DeviceExtension);
+ }
+ else
+ {
+ SpiProcessRequests(DeviceExtension, NULL);
+ }
va_end(ap);
}
SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
IN ULONG BusNumber,
- IN OUT PULONG NextDeviceNumber,
- IN OUT PULONG NextFunctionNumber)
+ IN OUT PPCI_SLOT_NUMBER NextSlotNumber)
{
PCI_COMMON_CONFIG PciConfig;
PCI_SLOT_NUMBER SlotNumber;
ULONG FunctionNumber;
CHAR VendorIdString[8];
CHAR DeviceIdString[8];
+ ULONG i;
+ ULONG RangeLength;
- DPRINT1("SpiGetPciConfiguration() called\n");
+ DPRINT ("SpiGetPciConfiguration() called\n");
- if (*NextFunctionNumber > 7)
+ if (NextSlotNumber->u.bits.FunctionNumber >= PCI_MAX_FUNCTION)
{
- *NextFunctionNumber = 0;
- (*NextDeviceNumber)++;
+ NextSlotNumber->u.bits.FunctionNumber = 0;
+ NextSlotNumber->u.bits.DeviceNumber++;
}
- if (*NextDeviceNumber > 31)
+ if (NextSlotNumber->u.bits.DeviceNumber >= PCI_MAX_DEVICES)
{
- *NextDeviceNumber = 0;
+ NextSlotNumber->u.bits.DeviceNumber = 0;
return FALSE;
}
- for (DeviceNumber = *NextDeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
+ for (DeviceNumber = NextSlotNumber->u.bits.DeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
{
SlotNumber.u.bits.DeviceNumber = DeviceNumber;
- for (FunctionNumber = *NextFunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
+ for (FunctionNumber = NextSlotNumber->u.bits.FunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
{
SlotNumber.u.bits.FunctionNumber = FunctionNumber;
if (!_strnicmp(VendorIdString, HwInitializationData->VendorId, HwInitializationData->VendorIdLength) &&
!_strnicmp(DeviceIdString, HwInitializationData->DeviceId, HwInitializationData->DeviceIdLength))
{
- DPRINT1 ("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
- PciConfig.VendorID,
- PciConfig.DeviceID,
- BusNumber,
- SlotNumber.u.bits.DeviceNumber,
- SlotNumber.u.bits.FunctionNumber);
-
+ DPRINT ("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
+ PciConfig.VendorID,
+ PciConfig.DeviceID,
+ BusNumber,
+ SlotNumber.u.bits.DeviceNumber,
+ SlotNumber.u.bits.FunctionNumber);
+
+ PortConfig->BusInterruptLevel =
+ PortConfig->BusInterruptVector = PciConfig.u.type0.InterruptLine;
PortConfig->SlotNumber = SlotNumber.u.AsULONG;
- *NextDeviceNumber = DeviceNumber;
- *NextFunctionNumber = FunctionNumber + 1;
+ /* Initialize access ranges */
+ if (PortConfig->NumberOfAccessRanges > 0)
+ {
+ if (PortConfig->NumberOfAccessRanges > PCI_TYPE0_ADDRESSES)
+ PortConfig->NumberOfAccessRanges = PCI_TYPE0_ADDRESSES;
+
+ for (i = 0; i < PortConfig->NumberOfAccessRanges; i++)
+ {
+ (*PortConfig->AccessRanges)[i].RangeStart.QuadPart =
+ PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_ADDRESS_MASK;
+ if ((*PortConfig->AccessRanges)[i].RangeStart.QuadPart != 0)
+ {
+ RangeLength = (ULONG)-1;
+ HalSetBusDataByOffset (PCIConfiguration,
+ BusNumber,
+ SlotNumber.u.AsULONG,
+ (PVOID)&RangeLength,
+ 0x10 + (i * sizeof(ULONG)),
+ sizeof(ULONG));
+
+ HalGetBusDataByOffset (PCIConfiguration,
+ BusNumber,
+ SlotNumber.u.AsULONG,
+ (PVOID)&RangeLength,
+ 0x10 + (i * sizeof(ULONG)),
+ sizeof(ULONG));
+
+ HalSetBusDataByOffset (PCIConfiguration,
+ BusNumber,
+ SlotNumber.u.AsULONG,
+ (PVOID)&PciConfig.u.type0.BaseAddresses[i],
+ 0x10 + (i * sizeof(ULONG)),
+ sizeof(ULONG));
+ if (RangeLength != 0)
+ {
+ (*PortConfig->AccessRanges)[i].RangeLength =
+ -(RangeLength & PCI_ADDRESS_IO_ADDRESS_MASK);
+ (*PortConfig->AccessRanges)[i].RangeInMemory =
+ !(PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_SPACE);
+
+ DPRINT("RangeStart 0x%lX RangeLength 0x%lX RangeInMemory %s\n",
+ PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_ADDRESS_MASK,
+ -(RangeLength & PCI_ADDRESS_IO_ADDRESS_MASK),
+ (PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_SPACE)?"FALSE":"TRUE");
+ }
+ }
+ }
+ }
+
+ NextSlotNumber->u.bits.DeviceNumber = DeviceNumber;
+ NextSlotNumber->u.bits.FunctionNumber = FunctionNumber;
+
+ PortConfig->SlotNumber = NextSlotNumber->u.AsULONG;
+
+ NextSlotNumber->u.bits.FunctionNumber += 1;
return TRUE;
}
break;
}
}
- *NextFunctionNumber = 0;
+ NextSlotNumber->u.bits.FunctionNumber = 0;
}
- DPRINT1("No device found\n");
+ DPRINT ("No device found\n");
return FALSE;
}
* Irp
* Pointer to an IRP.
*
- * ...
- Additional output data (see printf()).
- *
* RETURN VALUE
* Status.
*/
{
case SRB_FUNCTION_EXECUTE_SCSI:
case SRB_FUNCTION_IO_CONTROL:
-#ifdef USE_DEVICE_QUEUES
- if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
- {
- IoStartPacket (DeviceObject, Irp, NULL, NULL);
- }
- else
- {
- KIRQL oldIrql;
-
- KeRaiseIrql (DISPATCH_LEVEL,
- &oldIrql);
-
- if (!KeInsertByKeyDeviceQueue (&LunExtension->DeviceQueue,
- &Irp->Tail.Overlay.DeviceQueueEntry,
- Srb->QueueSortKey))
- {
- Srb->SrbStatus = SRB_STATUS_SUCCESS;
- IoStartPacket (DeviceObject, Irp, NULL, NULL);
- }
-
- KeLowerIrql (oldIrql);
- }
-#else
- IoStartPacket (DeviceObject, Irp, NULL, NULL);
-#endif
+ IoMarkIrpPending(Irp);
+ Srb->OriginalRequest = LunExtension;
+ Irp->Tail.Overlay.DriverContext[3] = Srb;
+ SpiProcessRequests(DeviceExtension, Irp);
return(STATUS_PENDING);
case SRB_FUNCTION_SHUTDOWN:
case SRB_FUNCTION_FLUSH:
- if (DeviceExtension->PortConfig.CachesData == TRUE)
+ if (DeviceExtension->PortConfig->CachesData == TRUE)
{
- IoStartPacket(DeviceObject, Irp, NULL, NULL);
+ IoMarkIrpPending(Irp);
+ Srb->OriginalRequest = LunExtension;
+ Irp->Tail.Overlay.DriverContext[3] = Srb;
+ SpiProcessRequests(DeviceExtension, Irp);
return(STATUS_PENDING);
}
break;
case SRB_FUNCTION_CLAIM_DEVICE:
- DPRINT(" SRB_FUNCTION_CLAIM_DEVICE\n");
+ DPRINT (" SRB_FUNCTION_CLAIM_DEVICE\n");
- /* Reference device object and keep the pointer */
+ /* Reference device object and keep the device object */
ObReferenceObject(DeviceObject);
LunExtension->DeviceObject = DeviceObject;
LunExtension->DeviceClaimed = TRUE;
break;
case SRB_FUNCTION_RELEASE_DEVICE:
- {
- PSCSI_PORT_LUN_EXTENSION LunExtension;
-
- DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n");
- DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
-
- LunExtension = SpiGetLunExtension(DeviceExtension,
- Srb->PathId,
- Srb->TargetId,
- Srb->Lun);
- if (LunExtension != NULL)
- {
- /* Dereference device object */
- ObDereferenceObject(LunExtension->DeviceObject);
- LunExtension->DeviceObject = NULL;
- LunExtension->DeviceClaimed = FALSE;
- }
- }
+ DPRINT (" SRB_FUNCTION_RELEASE_DEVICE\n");
+ DPRINT ("PathId: %lu TargetId: %lu Lun: %lu\n",
+ Srb->PathId, Srb->TargetId, Srb->Lun);
+
+ /* Dereference device object and clear the device object */
+ ObDereferenceObject(LunExtension->DeviceObject);
+ LunExtension->DeviceObject = NULL;
+ LunExtension->DeviceClaimed = FALSE;
break;
default:
{
PIO_STACK_LOCATION Stack;
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status = STATUS_SUCCESS;
DPRINT("ScsiPortDeviceControl()\n");
- Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
DumpPointers->DeviceObject = DeviceObject;
-
+
Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
}
break;
DPRINT("Inquiry data size: %lu\n", Irp->IoStatus.Information);
}
break;
+
+ case IOCTL_SCSI_PASS_THROUGH:
+ DPRINT(" IOCTL_SCSI_PASS_THROUGH\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case IOCTL_SCSI_PASS_THROUGH_DIRECT:
+ DPRINT(" IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case IOCTL_SCSI_MINIPORT:
+ DPRINT1(" IOCTL_SCSI_MINIPORT\n");
+ DPRINT1(" Signature: %.8s\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->Signature);
+ DPRINT1(" ControlCode: 0x%lX\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->ControlCode);
+ return SpiScsiMiniport(DeviceObject, Irp);
default:
DPRINT1(" unknown ioctl code: 0x%lX\n",
Stack->Parameters.DeviceIoControl.IoControlCode);
+ Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
+ Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return(STATUS_SUCCESS);
+ return Status;
}
-
-static VOID STDCALL
-ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
+static NTSTATUS STDCALL
+SpiCompletion(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
{
- PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
- PSCSI_PORT_LUN_EXTENSION LunExtension;
- PIO_STACK_LOCATION IrpStack;
PSCSI_REQUEST_BLOCK Srb;
- KIRQL oldIrql;
- BOOLEAN Result;
-
- DPRINT("ScsiPortStartIo() called!\n");
+
+ DPRINT("SpiCompletion(DeviceObject %x, Irp %x, Context %x)\n",
+ DeviceObject, Irp, Context);
- DeviceExtension = DeviceObject->DeviceExtension;
- IrpStack = IoGetCurrentIrpStackLocation(Irp);
-
- DPRINT("DeviceExtension %p\n", DeviceExtension);
+ Srb = (PSCSI_REQUEST_BLOCK)Context;
+ Irp->IoStatus.Information = 0;
- if (IrpStack->MajorFunction != IRP_MJ_SCSI)
+ switch (SRB_STATUS(Srb->SrbStatus))
{
- DPRINT("No IRP_MJ_SCSI!\n");
- Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest (Irp,
- IO_NO_INCREMENT);
- IoStartNextPacket (DeviceObject,
- FALSE);
- return;
- }
-
- Srb = IrpStack->Parameters.Scsi.Srb;
+ case SRB_STATUS_SUCCESS:
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = Srb->DataTransferLength;
+ break;
+
+ case SRB_STATUS_INVALID_PATH_ID:
+ case SRB_STATUS_INVALID_TARGET_ID:
+ case SRB_STATUS_INVALID_LUN:
+ case SRB_STATUS_NO_HBA:
+ Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
+ break;
- LunExtension = SpiGetLunExtension(DeviceExtension,
- Srb->PathId,
- Srb->TargetId,
- Srb->Lun);
- if (LunExtension == NULL)
- {
- DPRINT("No IRP_MJ_SCSI!\n");
- Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest (Irp,
- IO_NO_INCREMENT);
- IoStartNextPacket (DeviceObject,
- FALSE);
- return;
- }
+ case SRB_STATUS_NO_DEVICE:
+ Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
+ break;
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = Srb->DataTransferLength;
+ case SRB_STATUS_BUSY:
+ Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
+ break;
- DeviceExtension->CurrentIrp = Irp;
+ case SRB_STATUS_DATA_OVERRUN:
+ Irp->IoStatus.Status = STATUS_DATA_OVERRUN;
+ Irp->IoStatus.Information = Srb->DataTransferLength;
+ break;
- if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
- ScsiPortStartPacket,
- DeviceExtension))
- {
- DPRINT("Synchronization failed!\n");
+ case SRB_STATUS_INVALID_REQUEST:
+ Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
- Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp,
- IO_NO_INCREMENT);
- IoStartNextPacket(DeviceObject,
- FALSE);
+ default:
+ Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
+ break;
}
- KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
- if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
- {
- DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
- IoCompleteRequest(Irp,
- IO_NO_INCREMENT);
- }
+ ExFreePool(Srb);
- if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
- {
- DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
- KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
- IoStartNextPacket(DeviceObject,
- FALSE);
- }
- else
+ if (Irp->PendingReturned)
{
- KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
+ IoMarkIrpPending (Irp);
}
-
- DPRINT("ScsiPortStartIo() done\n");
+ return Irp->IoStatus.Status;
}
-
-static BOOLEAN STDCALL
-ScsiPortStartPacket(IN OUT PVOID Context)
+static NTSTATUS
+SpiScsiMiniport(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ PSRB_IO_CONTROL SrbIoControl;
PIO_STACK_LOCATION IrpStack;
PSCSI_REQUEST_BLOCK Srb;
+ PSCSI_PORT_LUN_EXTENSION LunExtension;
+
+ DPRINT("SpiScsiMiniport(DeviceObject %x, Irp %x)\n",
+ DeviceObject, Irp);
- DPRINT("ScsiPortStartPacket() called\n");
-
- DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context;
+ DeviceExtension = DeviceObject->DeviceExtension;
+ SrbIoControl = (PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer;
- IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
- Srb = IrpStack->Parameters.Scsi.Srb;
+ IrpStack = IoGetCurrentIrpStackLocation(Irp);
+ if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS) - 1)
+ {
+ Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SRB_IO_CONTROL) + SrbIoControl->Length)
+ {
+ Irp->IoStatus.Information = sizeof(SRB_IO_CONTROL) + SrbIoControl->Length;
+ Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
+ {
+ Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_NO_SUCH_DEVICE;
+ }
- return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
- Srb));
+ Srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK));
+ if (Srb == NULL)
+ {
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
+ Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
+ Srb->OriginalRequest = Irp;
+ Srb->Function = SRB_FUNCTION_IO_CONTROL;
+ Srb->DataBuffer = (PVOID)SrbIoControl;
+ Srb->DataTransferLength = sizeof(SRB_IO_CONTROL) + SrbIoControl->Length;
+
+ /* We using the first extension from the list. The miniport driver is responsible to find the correct device. */
+ LunExtension = CONTAINING_RECORD(DeviceExtension->LunExtensionListHead.Flink,
+ SCSI_PORT_LUN_EXTENSION,
+ List);
+ Srb->PathId = LunExtension->PathId;
+ Srb->TargetId = LunExtension->TargetId;
+ Srb->Lun = LunExtension->Lun;
+
+ IrpStack = IoGetNextIrpStackLocation(Irp);
+
+ IrpStack->MajorFunction = IRP_MJ_SCSI;
+ IrpStack->Parameters.Scsi.Srb = Srb;
+
+ IoSetCompletionRoutine(Irp,
+ SpiCompletion,
+ Srb,
+ TRUE,
+ TRUE,
+ TRUE);
+
+ return IoCallDriver(DeviceObject, Irp);
}
-
-/**********************************************************************
- * NAME INTERNAL
- * ScsiPortCreatePortDevice
- *
- * DESCRIPTION
- * Creates and initializes a SCSI port device object.
- *
- * RUN LEVEL
- * PASSIVE_LEVEL
- *
- * ARGUMENTS
- * DriverObject
- * ...
- *
- * PseudoDeviceExtension
- * ...
- *
- * PortNumber
- * ...
- *
- * RETURNS
- * NTSTATUS
- */
-
-static NTSTATUS
-ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
- IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension,
- IN ULONG PortNumber,
- IN OUT PSCSI_PORT_DEVICE_EXTENSION *RealDeviceExtension)
+static VOID
+SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PSCSI_REQUEST_BLOCK Srb)
{
- PSCSI_PORT_DEVICE_EXTENSION PortDeviceExtension;
- PIO_SCSI_CAPABILITIES PortCapabilities;
- PDEVICE_OBJECT PortDeviceObject;
- WCHAR NameBuffer[80];
- UNICODE_STRING DeviceName;
- WCHAR DosNameBuffer[80];
- UNICODE_STRING DosDeviceName;
- NTSTATUS Status;
- ULONG AccessRangeSize;
- ULONG MappedIrq;
- KIRQL Dirql;
- KAFFINITY Affinity;
-
- DPRINT("ScsiPortCreatePortDevice() called\n");
-
- *RealDeviceExtension = NULL;
-
- MappedIrq = HalGetInterruptVector(PseudoDeviceExtension->PortConfig.AdapterInterfaceType,
- PseudoDeviceExtension->PortConfig.SystemIoBusNumber,
- PseudoDeviceExtension->PortConfig.BusInterruptLevel,
- PseudoDeviceExtension->PortConfig.BusInterruptVector,
- &Dirql,
- &Affinity);
+ ULONG index;
- /* Create a unicode device name */
- swprintf(NameBuffer,
- L"\\Device\\ScsiPort%lu",
- PortNumber);
- RtlInitUnicodeString(&DeviceName,
- NameBuffer);
+ DPRINT("SpiAllocateSrbExtension\n");
- DPRINT("Creating device: %wZ\n", &DeviceName);
+ DPRINT("DeviceExtension->VirtualAddress %x, DeviceExtension->SrbExtensionSize %x\n",
+ DeviceExtension->VirtualAddress, DeviceExtension->SrbExtensionSize);
- /* Create the port device */
- Status = IoCreateDevice(DriverObject,
- PseudoDeviceExtension->Length,
- &DeviceName,
- FILE_DEVICE_CONTROLLER,
- 0,
- FALSE,
- &PortDeviceObject);
- if (!NT_SUCCESS(Status))
+ Srb->SrbExtension = NULL;
+ if (DeviceExtension->VirtualAddress != NULL &&
+ DeviceExtension->SrbExtensionSize > 0)
{
- DbgPrint("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
- return(Status);
+ index = RtlFindClearBitsAndSet(&DeviceExtension->SrbExtensionAllocMap, 1, 0);
+ if (index != 0xffffffff)
+ {
+ DeviceExtension->CurrentSrbExtensions++;
+ Srb->SrbExtension = (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + index * DeviceExtension->SrbExtensionSize);
+ }
}
+ DPRINT("%x\n", Srb->SrbExtension);
+}
- DPRINT("Created device: %wZ\n", &DeviceName);
-
- /* Set the buffering strategy here... */
- PortDeviceObject->Flags |= DO_DIRECT_IO;
- PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
-
- PortDeviceExtension = PortDeviceObject->DeviceExtension;
-
- /* Copy pseudo device extension into the real device extension */
- memcpy(PortDeviceExtension,
- PseudoDeviceExtension,
- PseudoDeviceExtension->Length);
-
- /* Copy access ranges */
- AccessRangeSize =
- sizeof(ACCESS_RANGE) * PseudoDeviceExtension->PortConfig.NumberOfAccessRanges;
- PortDeviceExtension->PortConfig.AccessRanges = ExAllocatePool(NonPagedPool,
- AccessRangeSize);
- memcpy(PortDeviceExtension->PortConfig.AccessRanges,
- PseudoDeviceExtension->PortConfig.AccessRanges,
- AccessRangeSize);
+static VOID
+SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PSCSI_REQUEST_BLOCK Srb)
+{
+ ULONG index;
- /* Copy device base list */
- if (IsListEmpty(&PseudoDeviceExtension->DeviceBaseListHead))
- {
- InitializeListHead(&PortDeviceExtension->DeviceBaseListHead);
- }
- else
+ if (DeviceExtension->VirtualAddress != NULL &&
+ DeviceExtension->SrbExtensionSize > 0 &&
+ Srb->SrbExtension != NULL)
{
- PseudoDeviceExtension->DeviceBaseListHead.Flink =
- PortDeviceExtension->DeviceBaseListHead.Flink;
- PseudoDeviceExtension->DeviceBaseListHead.Blink =
- PortDeviceExtension->DeviceBaseListHead.Blink;
- PortDeviceExtension->DeviceBaseListHead.Blink->Flink =
- &PortDeviceExtension->DeviceBaseListHead;
- PortDeviceExtension->DeviceBaseListHead.Flink->Blink =
- &PortDeviceExtension->DeviceBaseListHead;
+ index = ((ULONG_PTR)Srb->SrbExtension - (ULONG_PTR)DeviceExtension->VirtualAddress) / DeviceExtension->SrbExtensionSize;
+ RtlClearBits(&DeviceExtension->SrbExtensionAllocMap, index, 1);
+ DeviceExtension->CurrentSrbExtensions--;
}
+ Srb->SrbExtension = NULL;
+}
- PortDeviceExtension->DeviceObject = PortDeviceObject;
- PortDeviceExtension->PortNumber = PortNumber;
-
- /* Initialize the spin lock in the controller extension */
- KeInitializeSpinLock(&PortDeviceExtension->IrpLock);
- KeInitializeSpinLock(&PortDeviceExtension->SpinLock);
-
- /* Register an interrupt handler for this device */
- Status = IoConnectInterrupt(&PortDeviceExtension->Interrupt,
- ScsiPortIsr,
- PortDeviceExtension,
- &PortDeviceExtension->SpinLock,
- MappedIrq,
- Dirql,
- Dirql,
- PortDeviceExtension->PortConfig.InterruptMode,
- TRUE,
- Affinity,
- FALSE);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("Could not Connect Interrupt %d\n",
- PortDeviceExtension->PortConfig.BusInterruptVector);
- IoDeleteDevice(PortDeviceObject);
- return(Status);
- }
- /* Initialize the DPC object */
- IoInitializeDpcRequest(PortDeviceExtension->DeviceObject,
- ScsiPortDpcForIsr);
-
- /* Initialize the device timer */
- PortDeviceExtension->TimerState = IDETimerIdle;
- PortDeviceExtension->TimerCount = 0;
- IoInitializeTimer(PortDeviceExtension->DeviceObject,
- ScsiPortIoTimer,
- PortDeviceExtension);
-
- /* Initialize port capabilities */
- PortCapabilities = ExAllocatePool(NonPagedPool,
- sizeof(IO_SCSI_CAPABILITIES));
- PortDeviceExtension->PortCapabilities = PortCapabilities;
- PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
- PortCapabilities->MaximumTransferLength =
- PortDeviceExtension->PortConfig.MaximumTransferLength;
- PortCapabilities->MaximumPhysicalPages =
- PortCapabilities->MaximumTransferLength / PAGE_SIZE;
- PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
- PortCapabilities->AlignmentMask =
- PortDeviceExtension->PortConfig.AlignmentMask;
- PortCapabilities->TaggedQueuing =
- PortDeviceExtension->PortConfig.TaggedQueuing;
- PortCapabilities->AdapterScansDown =
- PortDeviceExtension->PortConfig.AdapterScansDown;
- PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */
-
- /* Initialize LUN-Extension list */
- InitializeListHead(&PortDeviceExtension->LunExtensionListHead);
-
- DPRINT("DeviceExtension %p\n", PortDeviceExtension);
-
- /* FIXME: Copy more configuration data? */
-
-
- /* Create the dos device link */
- swprintf(DosNameBuffer,
- L"\\??\\Scsi%lu:",
- PortNumber);
- RtlInitUnicodeString(&DosDeviceName,
- DosNameBuffer);
-
- IoCreateSymbolicLink(&DosDeviceName,
- &DeviceName);
-
- *RealDeviceExtension = PortDeviceExtension;
-
- DPRINT("ScsiPortCreatePortDevice() done\n");
+static BOOLEAN STDCALL
+ScsiPortStartPacket(IN OUT PVOID Context)
+{
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ PSCSI_REQUEST_BLOCK Srb;
+ PIRP Irp;
+ PIO_STACK_LOCATION IrpStack;
- return(STATUS_SUCCESS);
+ DPRINT("ScsiPortStartPacket(Context %x) called\n", Context);
+
+ Srb = (PSCSI_REQUEST_BLOCK)Context;
+ Irp = (PIRP)Srb->OriginalRequest;
+ IrpStack = IoGetCurrentIrpStackLocation(Irp);
+ DeviceExtension = IrpStack->DeviceObject->DeviceExtension;
+
+ return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
+ Srb));
}
LunExtension->TargetId = TargetId;
LunExtension->Lun = Lun;
- KeInitializeDeviceQueue (&LunExtension->DeviceQueue);
+ LunExtension->PendingIrpCount = 0;
+ LunExtension->ActiveIrpCount = 0;
+
+ LunExtension->NextIrp = NULL;
return LunExtension;
}
+static VOID
+SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension)
+{
+ DPRINT("SpiRemoveLunExtension(%p) called\n",
+ LunExtension);
+
+ if (LunExtension == NULL)
+ return;
+
+ RemoveEntryList (&LunExtension->List);
+
+
+ /* Release LUN extersion data */
+
+
+ ExFreePool (LunExtension);
+
+ return;
+}
+
+
static PSCSI_PORT_LUN_EXTENSION
SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN UCHAR PathId,
}
-static VOID
-SpiInquirePort(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
+static NTSTATUS
+SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PSCSI_REQUEST_BLOCK Srb,
+ IN OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN OUT PKEVENT Event)
{
- PSCSI_PORT_LUN_EXTENSION LunExtension;
- SCSI_REQUEST_BLOCK Srb;
- ULONG Bus;
- ULONG Target;
- ULONG Lun;
- BOOLEAN Result;
+ PIO_STACK_LOCATION IrpStack;
+ PIRP Irp;
+ NTSTATUS Status;
- DPRINT("SpiInquirePort() called\n");
+ DPRINT ("SpiSendInquiry() called\n");
- DeviceExtension->Initializing = TRUE;
- RtlZeroMemory(&Srb,
- sizeof(SCSI_REQUEST_BLOCK));
- Srb.SrbFlags = SRB_FLAGS_DATA_IN;
- Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256);
- Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
- Srb.DataTransferLength = 256;
- Srb.Cdb[0] = SCSIOP_INQUIRY;
+ KeInitializeEvent (Event,
+ NotificationEvent,
+ FALSE);
- for (Bus = 0; Bus < DeviceExtension->PortConfig.NumberOfBuses; Bus++)
+ Irp = IoBuildDeviceIoControlRequest (IOCTL_SCSI_EXECUTE_OUT,
+ DeviceObject,
+ NULL,
+ 0,
+ Srb->DataBuffer,
+ Srb->DataTransferLength,
+ TRUE,
+ Event,
+ IoStatusBlock);
+ if (Irp == NULL)
{
- Srb.PathId = Bus;
+ DPRINT("IoBuildDeviceIoControlRequest() failed\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
- {
- Srb.TargetId = Target;
+ /* Attach Srb to the Irp */
+ IrpStack = IoGetNextIrpStackLocation (Irp);
+ IrpStack->Parameters.Scsi.Srb = Srb;
+ Srb->OriginalRequest = Irp;
- for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
- {
- Srb.Lun = Lun;
- Srb.SrbStatus = SRB_STATUS_SUCCESS;
+ /* Call the driver */
+ Status = IoCallDriver (DeviceObject,
+ Irp);
- Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
- &Srb);
- DPRINT("Result %s Srb.SrbStatus %lx\n", (Result) ? "TRUE" : "FALSE", Srb.SrbStatus);
+ return Status;
+}
+
+static VOID
+SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
+{
+ PSCSI_REQUEST_BLOCK Srb;
+ PCDB Cdb;
+ ULONG Bus;
+ ULONG Target;
+ PSCSI_PORT_SCAN_ADAPTER ScanDataArray;
+ PSCSI_PORT_SCAN_ADAPTER ScanData;
+ ULONG i;
+ ULONG MaxCount;
+ ULONG WaitCount;
+ ULONG ActiveCount;
+ PVOID* EventArray;
+ PKWAIT_BLOCK WaitBlockArray;
- if (Result == TRUE && Srb.SrbStatus == SRB_STATUS_SUCCESS)
+ DPRINT ("SpiScanAdapter() called\n");
+
+ MaxCount = DeviceExtension->PortConfig->NumberOfBuses *
+ DeviceExtension->PortConfig->MaximumNumberOfTargets;
+
+ ScanDataArray = ExAllocatePool(NonPagedPool, MaxCount * (sizeof(SCSI_PORT_SCAN_ADAPTER) + sizeof(PVOID) + sizeof(KWAIT_BLOCK)));
+ if (ScanDataArray == NULL)
+ {
+ return;
+ }
+ EventArray = (PVOID*)((PUCHAR)ScanDataArray + MaxCount * sizeof(SCSI_PORT_SCAN_ADAPTER));
+ WaitBlockArray = (PKWAIT_BLOCK)((PUCHAR)EventArray + MaxCount * sizeof(PVOID));
+
+ for (Bus = 0; Bus < DeviceExtension->PortConfig->NumberOfBuses; Bus++)
+ {
+ for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
+ {
+ ScanData = &ScanDataArray[Bus * DeviceExtension->PortConfig->MaximumNumberOfTargets + Target];
+ ScanData->Bus = Bus;
+ ScanData->Target = Target;
+ ScanData->Lun = 0;
+ ScanData->Active = FALSE;
+ }
+ }
+ do
+ {
+ ActiveCount = 0;
+ WaitCount = 0;
+ for (i = 0; i < MaxCount; i++)
+ {
+ ScanData = &ScanDataArray[i];
+ Srb = &ScanData->Srb;
+ if (ScanData->Active)
+ {
+ if (ScanData->Status == STATUS_PENDING &&
+ 0 == KeReadStateEvent(&ScanData->Event))
+ {
+ ActiveCount++;
+ continue;
+ }
+ else
+ {
+ ScanData->Status = ScanData->IoStatusBlock.Status;
+ }
+ ScanData->Active = FALSE;
+ DPRINT ("Target %lu Lun %lu\n", ScanData->Target, ScanData->Lun);
+ DPRINT ("Status %lx Srb.SrbStatus %x\n", ScanData->Status, Srb->SrbStatus);
+ DPRINT ("DeviceTypeQualifier %x\n", ((PINQUIRYDATA)Srb->DataBuffer)->DeviceTypeQualifier);
+
+ if (NT_SUCCESS(ScanData->Status) &&
+ (Srb->SrbStatus == SRB_STATUS_SUCCESS ||
+ (Srb->SrbStatus == SRB_STATUS_DATA_OVERRUN &&
+ /*
+ * FIXME:
+ * The NT 4.0 driver from an inic950 based scsi controller
+ * returns only 4 byte of inquiry data, but the device name
+ * is visible on NT 4.0. We must implement an other way
+ * to get the complete inquiry data.
+ */
+ Srb->DataTransferLength >= /*INQUIRYDATABUFFERSIZE*/4)) &&
+ ((PINQUIRYDATA)Srb->DataBuffer)->DeviceTypeQualifier == 0)
{
- LunExtension = SpiAllocateLunExtension(DeviceExtension,
- Bus,
- Target,
- Lun);
- if (LunExtension != NULL)
- {
- /* Copy inquiry data */
- memcpy(&LunExtension->InquiryData,
- Srb.DataBuffer,
- sizeof(INQUIRYDATA));
- }
+ /* Copy inquiry data */
+ RtlCopyMemory (&ScanData->LunExtension->InquiryData,
+ Srb->DataBuffer,
+ min(sizeof(INQUIRYDATA), Srb->DataTransferLength));
+ ScanData->Lun++;
}
+ else
+ {
+ SpiRemoveLunExtension (ScanData->LunExtension);
+ ScanData->Lun = SCSI_MAXIMUM_LOGICAL_UNITS;
+ }
+ }
+ if (ScanData->Lun >= SCSI_MAXIMUM_LOGICAL_UNITS)
+ {
+ continue;
}
+ RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
+ Srb->SrbFlags = SRB_FLAGS_DATA_IN;
+ Srb->DataBuffer = ScanData->DataBuffer;
+ Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
+ Srb->DataTransferLength = 255; //256;
+ Srb->CdbLength = 6;
+ Srb->Lun = ScanData->Lun;
+ Srb->PathId = ScanData->Bus;
+ Srb->TargetId = ScanData->Target;
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ Srb->TimeOutValue = 2;
+ Cdb = (PCDB) &Srb->Cdb;
+
+ Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
+ Cdb->CDB6INQUIRY.AllocationLength = 255;
+ Cdb->CDB6INQUIRY.LogicalUnitNumber = ScanData->Lun;
+
+ RtlZeroMemory(Srb->DataBuffer, 256);
+
+ ScanData->LunExtension = SpiAllocateLunExtension (DeviceExtension,
+ ScanData->Bus,
+ ScanData->Target,
+ ScanData->Lun);
+ if (ScanData->LunExtension == NULL)
+ {
+ DPRINT1("Failed to allocate the LUN extension!\n");
+ ScanData->Lun = SCSI_MAXIMUM_LOGICAL_UNITS;
+ continue;
+ }
+ ScanData->Status = SpiSendInquiry (DeviceExtension->DeviceObject,
+ Srb,
+ &ScanData->IoStatusBlock,
+ &ScanData->Event);
+ ScanData->Active = TRUE;
+ ActiveCount++;
+ if (ScanData->Status == STATUS_PENDING)
+ {
+ EventArray[WaitCount] = &ScanData->Event;
+ WaitCount++;
+ }
+ }
+ if (WaitCount > 0 && WaitCount == ActiveCount)
+ {
+ KeWaitForMultipleObjects(WaitCount,
+ EventArray,
+ WaitAny,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL,
+ WaitBlockArray);
}
}
+ while (ActiveCount > 0);
- ExFreePool(Srb.DataBuffer);
-
- DeviceExtension->Initializing = FALSE;
+ ExFreePool(ScanDataArray);
- DPRINT("SpiInquirePort() done\n");
+ DPRINT ("SpiScanAdapter() done\n");
}
DPRINT("SpiGetInquiryData() called\n");
/* Copy inquiry data to the port device extension */
- AdapterBusInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses;
+ AdapterBusInfo->NumberOfBuses = DeviceExtension->PortConfig->NumberOfBuses;
UnitInfo = (PSCSI_INQUIRY_DATA)
((PUCHAR)AdapterBusInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
for (Bus = 0; Bus < AdapterBusInfo->NumberOfBuses; Bus++)
{
AdapterBusInfo->BusData[Bus].InitiatorBusId =
- DeviceExtension->PortConfig.InitiatorBusId[Bus];
+ DeviceExtension->PortConfig->InitiatorBusId[Bus];
AdapterBusInfo->BusData[Bus].InquiryDataOffset =
(ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterBusInfo);
PrevUnit = NULL;
UnitCount = 0;
- for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
+ for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
{
for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
{
{
DPRINT("(Bus %lu Target %lu Lun %lu)\n",
Bus, Target, Lun);
-
+ RtlZeroMemory(UnitInfo, sizeof(*UnitInfo));
UnitInfo->PathId = Bus;
UnitInfo->TargetId = Target;
UnitInfo->Lun = Lun;
UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
- memcpy(&UnitInfo->InquiryData,
- &LunExtension->InquiryData,
- INQUIRYDATABUFFERSIZE);
+ RtlCopyMemory (&UnitInfo->InquiryData,
+ &LunExtension->InquiryData,
+ INQUIRYDATABUFFERSIZE);
if (PrevUnit != NULL)
- PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterBusInfo);
+ {
+ PrevUnit->NextInquiryDataOffset =
+ (ULONG)((ULONG_PTR)UnitInfo-(ULONG_PTR)AdapterBusInfo);
+ }
PrevUnit = UnitInfo;
UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
UnitCount++;
DPRINT("UnitCount: %lu\n", UnitCount);
AdapterBusInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
if (UnitCount == 0)
- AdapterBusInfo->BusData[Bus].InquiryDataOffset = 0;
+ {
+ AdapterBusInfo->BusData[Bus].InquiryDataOffset = 0;
+ }
}
DPRINT("Data size: %lu\n", (ULONG)UnitInfo - (ULONG)AdapterBusInfo);
IN PVOID ServiceContext)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
- BOOLEAN Result;
DPRINT("ScsiPortIsr() called!\n");
DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
- Result = DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
- if (Result == FALSE)
- {
- return(FALSE);
- }
-
- if (DeviceExtension->IrpFlags)
- {
- IoRequestDpc(DeviceExtension->DeviceObject,
- DeviceExtension->CurrentIrp,
- DeviceExtension);
- }
-
- return(TRUE);
+ return DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
}
-// ScsiPortDpcForIsr
+// ScsiPortDpc
// DESCRIPTION:
//
// RUN LEVEL:
// IN PVOID DpcContext
//
static VOID STDCALL
-ScsiPortDpcForIsr(IN PKDPC Dpc,
- IN PDEVICE_OBJECT DpcDeviceObject,
- IN PIRP DpcIrp,
- IN PVOID DpcContext)
+ScsiPortDpc(IN PKDPC Dpc,
+ IN PDEVICE_OBJECT DpcDeviceObject,
+ IN PIRP DpcIrp,
+ IN PVOID DpcContext)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
- PIO_STACK_LOCATION IrpStack;
- PSCSI_REQUEST_BLOCK Srb;
- KIRQL oldIrql;
- DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
+ DPRINT("ScsiPortDpc(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
Dpc, DpcDeviceObject, DpcIrp, DpcContext);
DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
- KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
- if (DeviceExtension->IrpFlags)
- {
- IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
- Srb = IrpStack->Parameters.Scsi.Srb;
-
- if (DeviceExtension->OriginalSrb != NULL)
- {
- DPRINT("Got sense data!\n");
-
- DPRINT("Valid: %x\n", DeviceExtension->InternalSenseData.Valid);
- DPRINT("ErrorCode: %x\n", DeviceExtension->InternalSenseData.ErrorCode);
- DPRINT("SenseKey: %x\n", DeviceExtension->InternalSenseData.SenseKey);
- DPRINT("SenseCode: %x\n", DeviceExtension->InternalSenseData.AdditionalSenseCode);
+ SpiProcessRequests(DeviceExtension, NULL);
- /* Copy sense data */
- if (DeviceExtension->OriginalSrb->SenseInfoBufferLength != 0)
- {
- RtlCopyMemory(DeviceExtension->OriginalSrb->SenseInfoBuffer,
- &DeviceExtension->InternalSenseData,
- sizeof(SENSE_DATA));
- DeviceExtension->OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
- }
-
- /* Clear current sense data */
- RtlZeroMemory(&DeviceExtension->InternalSenseData, sizeof(SENSE_DATA));
-
- IrpStack->Parameters.Scsi.Srb = DeviceExtension->OriginalSrb;
- DeviceExtension->OriginalSrb = NULL;
- }
- else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
- (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION))
- {
- DPRINT("SCSIOP_REQUEST_SENSE required!\n");
-
- DeviceExtension->OriginalSrb = Srb;
- IrpStack->Parameters.Scsi.Srb = ScsiPortInitSenseRequestSrb(DeviceExtension,
- Srb);
- KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
- if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
- ScsiPortStartPacket,
- DeviceExtension))
- {
- DPRINT1("Synchronization failed!\n");
-
- DpcIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
- DpcIrp->IoStatus.Information = 0;
- IoCompleteRequest(DpcIrp,
- IO_NO_INCREMENT);
- IoStartNextPacket(DpcDeviceObject,
- FALSE);
- }
-
- return;
- }
-
- DeviceExtension->CurrentIrp = NULL;
-
-// DpcIrp->IoStatus.Information = 0;
-// DpcIrp->IoStatus.Status = STATUS_SUCCESS;
-
- if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
- {
- DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
- IoCompleteRequest(DpcIrp, IO_NO_INCREMENT);
- }
-
- if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
- {
- DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
- KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
- IoStartNextPacket(DpcDeviceObject, FALSE);
- }
- else
- {
- KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
- }
- }
- else
- {
- KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
- }
-
- DPRINT("ScsiPortDpcForIsr() done\n");
+ DPRINT("ScsiPortDpc() done\n");
}
static PSCSI_REQUEST_BLOCK
-ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
- PSCSI_REQUEST_BLOCK OriginalSrb)
+ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb)
{
PSCSI_REQUEST_BLOCK Srb;
+ ULONG Length;
PCDB Cdb;
- Srb = &DeviceExtension->InternalSrb;
+ Length = sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA) + 32;
+ Srb = ExAllocatePoolWithTag(NonPagedPool,
+ Length,
+ TAG('S', 'S', 'r', 'b'));
+ if (Srb == NULL)
+ {
+ return NULL;
+ }
- RtlZeroMemory(Srb,
- sizeof(SCSI_REQUEST_BLOCK));
+ RtlZeroMemory(Srb, Length);
Srb->PathId = OriginalSrb->PathId;
Srb->TargetId = OriginalSrb->TargetId;
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
+ Srb->OriginalRequest = OriginalSrb->OriginalRequest;
Srb->TimeOutValue = 4;
Srb->CdbLength = 6;
- Srb->DataBuffer = &DeviceExtension->InternalSenseData;
+ /* The DataBuffer must be located in contiguous physical memory if
+ * the miniport driver uses dma for the sense info. The size of
+ * the sense data is 18 byte. If the buffer starts at a 32 byte
+ * boundary than is the buffer always in one memory page.
+ */
+ Srb->DataBuffer = (PVOID)ROUND_UP((ULONG_PTR)(Srb + 1), 32);
Srb->DataTransferLength = sizeof(SENSE_DATA);
Cdb = (PCDB)Srb->Cdb;
return(Srb);
}
-
-static VOID
-ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
-{
- DeviceExtension->OriginalSrb = NULL;
-}
-
-
/**********************************************************************
* NAME INTERNAL
* SpiBuildDeviceMap
{
PSCSI_PORT_LUN_EXTENSION LunExtension;
OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING KeyName;
+ UNICODE_STRING KeyName =
+ RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
UNICODE_STRING ValueName;
WCHAR NameBuffer[64];
ULONG Disposition;
}
/* Open or create the 'Scsi' subkey */
- RtlInitUnicodeStringFromLiteral(&KeyName,
- L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
}
/* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
- UlongData = (ULONG)DeviceExtension->PortConfig.BusInterruptLevel;
+ UlongData = (ULONG)DeviceExtension->PortConfig->BusInterruptLevel;
DPRINT(" Interrupt = %lu\n", UlongData);
RtlInitUnicodeString(&ValueName,
L"Interrupt");
}
/* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
- UlongData = ScsiPortConvertPhysicalAddressToUlong(DeviceExtension->PortConfig.AccessRanges[0].RangeStart);
+ UlongData = ScsiPortConvertPhysicalAddressToUlong((*DeviceExtension->PortConfig->AccessRanges)[0].RangeStart);
DPRINT(" IOAddress = %lx\n", UlongData);
RtlInitUnicodeString(&ValueName,
L"IOAddress");
}
/* Enumerate buses */
- for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig.NumberOfBuses; BusNumber++)
+ for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig->NumberOfBuses; BusNumber++)
{
/* Create 'Scsi Bus X' key */
DPRINT(" Scsi Bus %lu\n", BusNumber);
/* Create 'Initiator Id X' key */
DPRINT(" Initiator Id %u\n",
- DeviceExtension->PortConfig.InitiatorBusId[BusNumber]);
+ DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
swprintf(NameBuffer,
L"Initiator Id %u",
- DeviceExtension->PortConfig.InitiatorBusId[BusNumber]);
+ (unsigned int)(UCHAR)DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
RtlInitUnicodeString(&KeyName,
NameBuffer);
InitializeObjectAttributes(&ObjectAttributes,
/* Enumerate targets */
CurrentTarget = (ULONG)-1;
ScsiTargetKey = NULL;
- for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
+ for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
{
for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
{
return Status;
}
+static VOID
+SpiRemoveActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PIRP Irp,
+ PIRP PrevIrp)
+{
+ PSCSI_PORT_LUN_EXTENSION LunExtension;
+ PIRP CurrentIrp;
+ LunExtension = Irp->Tail.Overlay.DriverContext[2];
+ InterlockedDecrement((PLONG)&LunExtension->ActiveIrpCount);
+ InterlockedDecrement((PLONG)&DeviceExtension->ActiveIrpCount);
+ if (PrevIrp)
+ {
+ InterlockedExchangePointer(&PrevIrp->Tail.Overlay.DriverContext[0],
+ Irp->Tail.Overlay.DriverContext[0]);
+ }
+ else
+ {
+ InterlockedExchangePointer(&DeviceExtension->NextIrp,
+ Irp->Tail.Overlay.DriverContext[0]);
+ }
+ if (LunExtension->NextIrp == Irp)
+ {
+ InterlockedExchangePointer(&LunExtension->NextIrp,
+ Irp->Tail.Overlay.DriverContext[1]);
+ return;
+ }
+ else
+ {
+ CurrentIrp = LunExtension->NextIrp;
+ while (CurrentIrp)
+ {
+ if (CurrentIrp->Tail.Overlay.DriverContext[1] == Irp)
+ {
+ InterlockedExchangePointer(&CurrentIrp->Tail.Overlay.DriverContext[1],
+ Irp->Tail.Overlay.DriverContext[1]);
+ return;
+ }
+ CurrentIrp = CurrentIrp->Tail.Overlay.DriverContext[1];
+ }
+ KEBUGCHECK(0);
+ }
+}
+
+static VOID
+SpiAddActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PIRP Irp)
+{
+ PSCSI_PORT_LUN_EXTENSION LunExtension;
+ PSCSI_REQUEST_BLOCK Srb;
+ LunExtension = Irp->Tail.Overlay.DriverContext[2];
+ Srb = Irp->Tail.Overlay.DriverContext[3];
+ Irp->Tail.Overlay.DriverContext[0] = (PVOID)DeviceExtension->NextIrp;
+ InterlockedExchangePointer(&DeviceExtension->NextIrp, Irp);
+ Irp->Tail.Overlay.DriverContext[1] = (PVOID)LunExtension->NextIrp;
+ InterlockedExchangePointer(&LunExtension->NextIrp, Irp);
+}
+
+static VOID
+SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ IN PIRP NextIrp)
+{
+ /*
+ * Using of some fields from Srb and Irp while processing requests:
+ *
+ * NextIrp on entry:
+ * Srb->OriginalRequest -> LunExtension
+ * Irp->Tail.Overlay.DriverContext[3] -> original Srb
+ * IoStack->Parameters.Scsi.Srb -> original Srb
+ *
+ * Irp is within the pending irp list:
+ * Srb->OriginalRequest -> LunExtension
+ * Irp->Tail.Overlay.DriverContext[0] and DriverContext[1] -> ListEntry for queue
+ * Irp->Tail.Overlay.DriverContext[2] -> sort key (from Srb->QueueSortKey)
+ * Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
+ * IoStack->Parameters.Scsi.Srb -> original Srb
+ *
+ * Irp is within the active irp list or while other processing:
+ * Srb->OriginalRequest -> Irp
+ * Irp->Tail.Overlay.DriverContext[0] -> next irp, DeviceExtension->NextIrp is head.
+ * Irp->Tail.Overlay.DriverContext[1] -> next irp, LunExtension->NextIrp is head.
+ * Irp->Tail.Overlay.DriverContext[2] -> LunExtension
+ * Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
+ * IoStack->Parameters.Scsi.Srb -> original Srb
+ */
+ PIO_STACK_LOCATION IrpStack;
+ PSCSI_PORT_LUN_EXTENSION LunExtension;
+ PLIST_ENTRY ListEntry;
+ KIRQL oldIrql;
+ PIRP Irp;
+ LIST_ENTRY NextIrpListHead;
+ LIST_ENTRY CompleteIrpListHead;
+ PSCSI_REQUEST_BLOCK Srb;
+ PSCSI_REQUEST_BLOCK OriginalSrb;
+ PIRP PrevIrp;
+
+ DPRINT("SpiProcessRequests() called\n");
+
+ InitializeListHead(&NextIrpListHead);
+ InitializeListHead(&CompleteIrpListHead);
+
+ KeAcquireSpinLock(&DeviceExtension->Lock, &oldIrql);
+
+ if (NextIrp)
+ {
+ Srb = NextIrp->Tail.Overlay.DriverContext[3];
+ /*
+ * FIXME:
+ * Is this the right place to set this flag ?
+ */
+ NextIrp->Tail.Overlay.DriverContext[2] = (PVOID)Srb->QueueSortKey;
+ LunExtension = Srb->OriginalRequest;
+
+ ListEntry = DeviceExtension->PendingIrpListHead.Flink;
+ while (ListEntry != &DeviceExtension->PendingIrpListHead)
+ {
+ Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
+ if ((ULONG)Irp->Tail.Overlay.DriverContext[2] > Srb->QueueSortKey)
+ {
+ break;
+ }
+ ListEntry = ListEntry->Flink;
+ }
+ InsertTailList(ListEntry, (PLIST_ENTRY)&NextIrp->Tail.Overlay.DriverContext[0]);
+ DeviceExtension->PendingIrpCount++;
+ LunExtension->PendingIrpCount++;
+ }
+
+ while (DeviceExtension->Flags & IRP_FLAG_COMPLETE ||
+ (((DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->CurrentSrbExtensions < DeviceExtension->MaxSrbExtensions) &&
+ DeviceExtension->PendingIrpCount > 0 &&
+ (DeviceExtension->Flags & (IRP_FLAG_NEXT|IRP_FLAG_NEXT_LU) || DeviceExtension->NextIrp == NULL))))
+ {
+ DPRINT ("RequestComplete %d, NextRequest %d, NextLuRequest %d, PendingIrpCount %d, ActiveIrpCount %d\n",
+ DeviceExtension->Flags & IRP_FLAG_COMPLETE ? 1 : 0,
+ DeviceExtension->Flags & IRP_FLAG_NEXT ? 1 : 0,
+ DeviceExtension->Flags & IRP_FLAG_NEXT_LU ? 1 : 0,
+ DeviceExtension->PendingIrpCount,
+ DeviceExtension->ActiveIrpCount);
+
+
+ if (DeviceExtension->Flags & IRP_FLAG_COMPLETE)
+ {
+ DeviceExtension->Flags &= ~IRP_FLAG_COMPLETE;
+ PrevIrp = NULL;
+ Irp = DeviceExtension->NextIrp;
+ while (Irp)
+ {
+ NextIrp = (PIRP)Irp->Tail.Overlay.DriverContext[0];
+ Srb = Irp->Tail.Overlay.DriverContext[3];
+ if (!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE))
+ {
+ BOOLEAN CompleteThisRequest;
+ LunExtension = Irp->Tail.Overlay.DriverContext[2];
+ IrpStack = IoGetCurrentIrpStackLocation(Irp);
+ OriginalSrb = IrpStack->Parameters.Scsi.Srb;
+
+ if (Srb->SrbStatus == SRB_STATUS_BUSY)
+ {
+ CompleteThisRequest = FALSE;
+ Irp->Tail.Overlay.DriverContext[3] = Srb;
+
+ SpiRemoveActiveIrp(DeviceExtension, Irp, PrevIrp);
+ SpiFreeSrbExtension(DeviceExtension, OriginalSrb);
+
+ Srb->OriginalRequest = LunExtension;
+ Irp->Tail.Overlay.DriverContext[2] = 0;
+
+ InsertHeadList(&DeviceExtension->PendingIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
+ DeviceExtension->PendingIrpCount++;
+ LunExtension->PendingIrpCount++;
+ Irp = NextIrp;
+ continue;
+ }
+
+ if (OriginalSrb != Srb)
+ {
+ SENSE_DATA* SenseInfoBuffer;
+
+ SenseInfoBuffer = Srb->DataBuffer;
+
+ DPRINT("Got sense data!\n");
+
+ DPRINT("Valid: %x\n", SenseInfoBuffer->Valid);
+ DPRINT("ErrorCode: %x\n", SenseInfoBuffer->ErrorCode);
+ DPRINT("SenseKey: %x\n", SenseInfoBuffer->SenseKey);
+ DPRINT("SenseCode: %x\n", SenseInfoBuffer->AdditionalSenseCode);
+
+ /* Copy sense data */
+ RtlCopyMemory(OriginalSrb->SenseInfoBuffer,
+ SenseInfoBuffer,
+ sizeof(SENSE_DATA));
+ OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
+ OriginalSrb->SrbExtension = Srb->SrbExtension;
+ ExFreePool(Srb);
+ CompleteThisRequest = TRUE;
+ }
+ else if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS &&
+ Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION &&
+ Srb->SenseInfoBuffer != NULL &&
+ Srb->SenseInfoBufferLength >= sizeof(SENSE_DATA) &&
+ !(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID))
+ {
+ DPRINT("SCSIOP_REQUEST_SENSE required!\n");
+
+ Srb = ScsiPortInitSenseRequestSrb(OriginalSrb);
+
+ if (Srb)
+ {
+ CompleteThisRequest = FALSE;
+ Irp->Tail.Overlay.DriverContext[3] = Srb;
+ SpiRemoveActiveIrp(DeviceExtension, Irp, PrevIrp);
+ SpiFreeSrbExtension(DeviceExtension, OriginalSrb);
+
+ Srb->OriginalRequest = LunExtension;
+ Irp->Tail.Overlay.DriverContext[2] = 0;
+
+ InsertHeadList(&DeviceExtension->PendingIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
+ DeviceExtension->PendingIrpCount++;
+ LunExtension->PendingIrpCount++;
+ Irp = NextIrp;
+ continue;
+ }
+ else
+ {
+ CompleteThisRequest = TRUE;
+ }
+ }
+ else
+ {
+ DPRINT("Complete Request\n");
+ CompleteThisRequest = TRUE;
+ }
+ if (CompleteThisRequest)
+ {
+ SpiRemoveActiveIrp(DeviceExtension, Irp, PrevIrp);
+ InsertHeadList(&CompleteIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
+ SpiFreeSrbExtension(DeviceExtension, OriginalSrb);
+ }
+ else
+ {
+ PrevIrp = Irp;
+ }
+ Irp = NextIrp;
+ continue;
+ }
+ PrevIrp = Irp;
+ Irp = NextIrp;
+ }
+ }
+ if (!IsListEmpty(&CompleteIrpListHead))
+ {
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->Lock);
+ while (!IsListEmpty(&CompleteIrpListHead))
+ {
+ ListEntry = RemoveTailList(&CompleteIrpListHead);
+ Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+ KeAcquireSpinLockAtDpcLevel(&DeviceExtension->Lock);
+ }
+ if (DeviceExtension->Flags & (IRP_FLAG_NEXT|IRP_FLAG_NEXT_LU) &&
+ (DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->CurrentSrbExtensions < DeviceExtension->MaxSrbExtensions))
+ {
+ BOOLEAN StartThisRequest;
+ ListEntry = DeviceExtension->PendingIrpListHead.Flink;
+ while (ListEntry != &DeviceExtension->PendingIrpListHead)
+ {
+ Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
+ ListEntry = ListEntry->Flink;
+ Srb = Irp->Tail.Overlay.DriverContext[3];
+ LunExtension = Srb->OriginalRequest;
+ if (DeviceExtension->SrbExtensionSize > 0 &&
+ DeviceExtension->CurrentSrbExtensions >= DeviceExtension->MaxSrbExtensions)
+ {
+ break;
+ }
+ if (LunExtension->Flags & IRP_FLAG_NEXT_LU)
+ {
+ StartThisRequest = TRUE;
+ LunExtension->Flags &= ~IRP_FLAG_NEXT_LU;
+ DeviceExtension->Flags &= ~IRP_FLAG_NEXT_LU;
+ }
+ else if (DeviceExtension->Flags & IRP_FLAG_NEXT &&
+ LunExtension->ActiveIrpCount == 0)
+ {
+ StartThisRequest = TRUE;
+ DeviceExtension->Flags &= ~IRP_FLAG_NEXT;
+ }
+ else
+ {
+ StartThisRequest = FALSE;
+ }
+ if (StartThisRequest)
+ {
+ LunExtension->PendingIrpCount--;
+ DeviceExtension->PendingIrpCount--;
+ Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
+ LunExtension->ActiveIrpCount++;
+ DeviceExtension->ActiveIrpCount++;
+
+ RemoveEntryList((PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
+ Irp->Tail.Overlay.DriverContext[2] = LunExtension;
+ Srb->OriginalRequest = Irp;
+ SpiAllocateSrbExtension(DeviceExtension, Srb);
+
+ InsertHeadList(&NextIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
+ }
+ }
+ }
+
+ if (!IsListEmpty(&NextIrpListHead))
+ {
+ while (!IsListEmpty(&NextIrpListHead))
+ {
+ ListEntry = RemoveTailList(&NextIrpListHead);
+ Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->Lock);
+
+ // Start this Irp
+ SpiStartIo(DeviceExtension, Irp);
+ KeAcquireSpinLockAtDpcLevel(&DeviceExtension->Lock);
+ }
+ }
+
+ if (!IsListEmpty(&DeviceExtension->PendingIrpListHead) &&
+ DeviceExtension->NextIrp == NULL &&
+ (DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->CurrentSrbExtensions < DeviceExtension->MaxSrbExtensions))
+ {
+ ListEntry = RemoveHeadList(&DeviceExtension->PendingIrpListHead);
+ Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
+ Srb = Irp->Tail.Overlay.DriverContext[3];
+ LunExtension = Srb->OriginalRequest;
+ Irp->Tail.Overlay.DriverContext[2] = LunExtension;
+ Srb->OriginalRequest = Irp;
+
+ LunExtension->PendingIrpCount--;
+ DeviceExtension->PendingIrpCount--;
+ Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
+ LunExtension->ActiveIrpCount++;
+ DeviceExtension->ActiveIrpCount++;
+
+ SpiAllocateSrbExtension(DeviceExtension, Srb);
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->Lock);
+
+ /* Start this irp */
+ SpiStartIo(DeviceExtension, Irp);
+ KeAcquireSpinLockAtDpcLevel(&DeviceExtension->Lock);
+ }
+ }
+ KeReleaseSpinLock(&DeviceExtension->Lock, oldIrql);
+
+ DPRINT("SpiProcessRequests() done\n");
+ }
+
+static VOID
+SpiStartIo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ IN PIRP Irp)
+{
+ PSCSI_PORT_LUN_EXTENSION LunExtension;
+ PSCSI_REQUEST_BLOCK Srb;
+
+ DPRINT("SpiStartIo() called!\n");
+
+ assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ Srb = Irp->Tail.Overlay.DriverContext[3];
+ LunExtension = Irp->Tail.Overlay.DriverContext[2];
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = Srb->DataTransferLength;
+
+ SpiAddActiveIrp(DeviceExtension, Irp);
+
+ if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
+ ScsiPortStartPacket,
+ Srb))
+ {
+ DPRINT1("Synchronization failed!\n");
+ DPRINT1("Irp %x, Srb->Function %02x, Srb->Cdb[0] %02x, Srb->SrbStatus %02x\n", Irp, Srb->Function, Srb->Cdb[0], Srb->SrbStatus);
+ ScsiPortNotification(RequestComplete,
+ &DeviceExtension->MiniPortDeviceExtension,
+ Srb);
+ }
+
+ DPRINT("SpiStartIo() done\n");
+}
+
+
+
/* EOF */