* 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.51 2004/03/24 16:21:59 navaraf 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 <rosrtl/string.h>
+#include <ddk/ntddstor.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,
ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
-static VOID STDCALL
-ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp);
-
static BOOLEAN STDCALL
ScsiPortStartPacket(IN OUT PVOID Context);
static NTSTATUS
SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
- IN OUT PSCSI_REQUEST_BLOCK Srb);
+ IN OUT PSCSI_REQUEST_BLOCK Srb,
+ IN OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN OUT PKEVENT Event);
static VOID
SpiScanAdapter (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);
-
-static VOID
-ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
+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);
+
/* 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)
{
MappedAddress = MmMapIoSpace(TranslatedAddress,
NumberOfBytes,
- FALSE);
+ MmNonCached);
DeviceBase = ExAllocatePool(NonPagedPool,
sizeof(SCSI_PORT_DEVICE_BASE));
SCSI_PORT_DEVICE_EXTENSION,
MiniPortDeviceExtension);
- *Length = 0;
-
+ if (Length != NULL)
+ {
+ *Length = 0;
+ }
if (Srb == NULL)
{
- if ((ULONG_PTR)DeviceExtension->VirtualAddress > (ULONG_PTR)VirtualAddress)
- {
- PhysicalAddress.QuadPart = 0ULL;
- return PhysicalAddress;
+ 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;
}
-
- Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
- if (Offset >= DeviceExtension->CommonBufferLength)
- {
- PhysicalAddress.QuadPart = 0ULL;
- return PhysicalAddress;
+ 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;
}
-
- PhysicalAddress.QuadPart =
- DeviceExtension->PhysicalAddress.QuadPart + (ULONGLONG)Offset;
- BufferLength = DeviceExtension->CommonBufferLength - Offset;
}
else
{
- EndAddress = Srb->DataBuffer + Srb->DataTransferLength;
+ EndAddress = (PVOID)((ULONG_PTR)Srb->DataBuffer + Srb->DataTransferLength);
if (VirtualAddress == NULL)
{
VirtualAddress = Srb->DataBuffer;
}
else if (VirtualAddress < Srb->DataBuffer || VirtualAddress >= EndAddress)
{
- PhysicalAddress.QuadPart = 0LL;
- return PhysicalAddress;
+ EndAddress = (PVOID)((ULONG_PTR)Srb->SenseInfoBuffer + Srb->SenseInfoBufferLength);
+ if (VirtualAddress < Srb->SenseInfoBuffer || VirtualAddress >= EndAddress)
+ {
+ PhysicalAddress.QuadPart = 0LL;
+ CHECKPOINT;
+ return PhysicalAddress;
+ }
}
PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
if (PhysicalAddress.QuadPart == 0LL)
{
+ CHECKPOINT;
return PhysicalAddress;
}
- Offset = (ULONG_PTR)VirtualAddress & (PAGE_SIZE - 1);
-#if 1
- /*
- * FIXME:
- * MmGetPhysicalAddress doesn't return the offset within the page.
- * We must set the correct offset.
- */
- PhysicalAddress.u.LowPart = (PhysicalAddress.u.LowPart & ~(PAGE_SIZE - 1)) + Offset;
-#endif
- BufferLength += PAGE_SIZE - Offset;
- while (VirtualAddress + BufferLength < EndAddress)
+ BufferLength = PAGE_SIZE - (ULONG_PTR)VirtualAddress % PAGE_SIZE;
+ while ((ULONG_PTR)VirtualAddress + BufferLength < (ULONG_PTR)EndAddress)
{
- NextPhysicalAddress = MmGetPhysicalAddress(VirtualAddress + BufferLength);
- if (PhysicalAddress.QuadPart + (ULONGLONG)BufferLength != NextPhysicalAddress.QuadPart)
+ NextPhysicalAddress = MmGetPhysicalAddress((PVOID)((ULONG_PTR)VirtualAddress + BufferLength));
+ if (PhysicalAddress.QuadPart + BufferLength != NextPhysicalAddress.QuadPart)
{
break;
}
BufferLength += PAGE_SIZE;
}
- if (VirtualAddress + BufferLength >= EndAddress)
+ if ((ULONG_PTR)VirtualAddress + BufferLength >= (ULONG_PTR)EndAddress)
{
- BufferLength = EndAddress - VirtualAddress;
+ BufferLength = (ULONG)((ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress);
}
}
-
- *Length = BufferLength;
-
+ if (Length != NULL)
+ {
+ *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,
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->SrbExtensionSize;
+ NumberOfBytes + PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * DeviceExtension->MaxSrbExtensions);
DeviceExtension->VirtualAddress =
HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
DeviceExtension->CommonBufferLength,
}
return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress +
- DeviceExtension->SrbExtensionSize);
+ PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * DeviceExtension->MaxSrbExtensions));
}
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->DriverStartIo = NULL;
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
HwInitializationData->DeviceExtensionSize;
- PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) +
+ PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) +
HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE);
PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
DeviceExtension = PortDeviceObject->DeviceExtension;
+ RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
DeviceExtension->Length = DeviceExtensionSize;
DeviceExtension->DeviceObject = PortDeviceObject;
DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
-#if 0
DeviceExtension->AdapterObject = NULL;
DeviceExtension->MapRegisterCount = 0;
DeviceExtension->PhysicalAddress.QuadPart = 0ULL;
DeviceExtension->VirtualAddress = NULL;
DeviceExtension->CommonBufferLength = 0;
-#endif
/* Initialize the device base list */
InitializeListHead (&DeviceExtension->DeviceBaseListHead);
+ /* Initialize the irp lists */
+ InitializeListHead (&DeviceExtension->PendingIrpListHead);
+ DeviceExtension->NextIrp = NULL;
+ DeviceExtension->PendingIrpCount = 0;
+ DeviceExtension->ActiveIrpCount = 0;
+
/* Initialize LUN-Extension list */
InitializeListHead (&DeviceExtension->LunExtensionListHead);
/* Initialize the spin lock in the controller extension */
- KeInitializeSpinLock (&DeviceExtension->IrpLock);
- KeInitializeSpinLock (&DeviceExtension->SpinLock);
+ KeInitializeSpinLock (&DeviceExtension->Lock);
/* Initialize the DPC object */
IoInitializeDpcRequest (PortDeviceObject,
- ScsiPortDpcForIsr);
+ ScsiPortDpc);
/* Initialize the device timer */
DeviceExtension->TimerState = IDETimerIdle;
PortConfig->NumberOfPhysicalBreaks = SP_UNINITIALIZED_VALUE;
PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE;
PortConfig->DmaPort = SP_UNINITIALIZED_VALUE;
-// PortConfig->DmaWidth =
-// PortConfig->DmaSpeed =
-// PortConfig->AlignmentMask =
+ PortConfig->DmaWidth = 0;
+ PortConfig->DmaSpeed = Compatible;
+ PortConfig->AlignmentMask = 0;
PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
-// PortConfig->NumberOfBuses =
+ PortConfig->NumberOfBuses = 0;
for (i = 0; i < SCSI_MAXIMUM_BUSES; i++)
PortConfig->InitiatorBusId[i] = 255;
-// PortConfig->ScatterGather =
-// PortConfig->Master =
-// PortConfig->CachesData =
-// PortConfig->AdapterScansDown =
+ PortConfig->ScatterGather = FALSE;
+ PortConfig->Master = FALSE;
+ PortConfig->CachesData = FALSE;
+ PortConfig->AdapterScansDown = FALSE;
PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
-// PortConfig->Dma32BitAddresses =
-// PortConfig->DemandMode =
+ PortConfig->Dma32BitAddresses = FALSE;
+ PortConfig->DemandMode = FALSE;
PortConfig->MapBuffers = HwInitializationData->MapBuffers;
PortConfig->NeedPhysicalAddresses = HwInitializationData->NeedPhysicalAddresses;
- PortConfig->TaggedQueuing = HwInitializationData->TaggedQueueing;
+ PortConfig->TaggedQueuing = HwInitializationData->TaggedQueuing;
PortConfig->AutoRequestSense = HwInitializationData->AutoRequestSense;
PortConfig->MultipleRequestPerLu = HwInitializationData->MultipleRequestPerLu;
PortConfig->ReceiveEvent = HwInitializationData->ReceiveEvent;
-// PortConfig->RealModeInitialized =
-// PortConfig->BufferAccessScsiPortControlled =
+ PortConfig->RealModeInitialized = FALSE;
+ PortConfig->BufferAccessScsiPortControlled = FALSE;
PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
-// PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
+// PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
- PortConfig->SlotNumber = SlotNumber.u.AsULONG;
+ PortConfig->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
+ PortConfig->SpecificLuExtensionSize = HwInitializationData->SpecificLuExtensionSize;
- PortConfig->AccessRanges = (PACCESS_RANGE)(PortConfig + 1);
+ PortConfig->AccessRanges = (ACCESS_RANGE(*)[])(PortConfig + 1);
/* Search for matching PCI device */
if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
{
DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig->BusInterruptVector);
+#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,
- &DeviceExtension->SpinLock,
+ NULL,
MappedIrq,
Dirql,
Dirql,
PortCapabilities = DeviceExtension->PortCapabilities;
PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
- PortCapabilities->MaximumTransferLength =
- PortConfig->MaximumTransferLength;
+ 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;
+ }
+
PortCapabilities->MaximumPhysicalPages =
PortCapabilities->MaximumTransferLength / PAGE_SIZE;
PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
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,
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;
-// DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
-
- /* Hack! */
- DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
+ 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);
}
for (i = 0; i < PortConfig->NumberOfAccessRanges; i++)
{
- PortConfig->AccessRanges[i].RangeStart.QuadPart =
+ (*PortConfig->AccessRanges)[i].RangeStart.QuadPart =
PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_ADDRESS_MASK;
- if (PortConfig->AccessRanges[i].RangeStart.QuadPart != 0)
+ if ((*PortConfig->AccessRanges)[i].RangeStart.QuadPart != 0)
{
RangeLength = (ULONG)-1;
HalSetBusDataByOffset (PCIConfiguration,
sizeof(ULONG));
if (RangeLength != 0)
{
- PortConfig->AccessRanges[0].RangeLength =
+ (*PortConfig->AccessRanges)[i].RangeLength =
-(RangeLength & PCI_ADDRESS_IO_ADDRESS_MASK);
- PortConfig->AccessRanges[i].RangeInMemory =
+ (*PortConfig->AccessRanges)[i].RangeInMemory =
!(PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_SPACE);
DPRINT("RangeStart 0x%lX RangeLength 0x%lX RangeInMemory %s\n",
}
NextSlotNumber->u.bits.DeviceNumber = DeviceNumber;
- NextSlotNumber->u.bits.FunctionNumber = FunctionNumber + 1;
+ NextSlotNumber->u.bits.FunctionNumber = FunctionNumber;
+
+ PortConfig->SlotNumber = NextSlotNumber->u.AsULONG;
+
+ NextSlotNumber->u.bits.FunctionNumber += 1;
return TRUE;
}
{
case SRB_FUNCTION_EXECUTE_SCSI:
case SRB_FUNCTION_IO_CONTROL:
-#ifdef USE_DEVICE_QUEUES
- if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
- {
- IoMarkIrpPending(Irp);
- 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;
- IoMarkIrpPending(Irp);
- IoStartPacket (DeviceObject, Irp, NULL, NULL);
- }
-
- KeLowerIrql (oldIrql);
- }
-#else
IoMarkIrpPending(Irp);
- IoStartPacket (DeviceObject, Irp, NULL, NULL);
-#endif
+ Srb->OriginalRequest = LunExtension;
+ Irp->Tail.Overlay.DriverContext[3] = Srb;
+ SpiProcessRequests(DeviceExtension, Irp);
return(STATUS_PENDING);
case SRB_FUNCTION_SHUTDOWN:
if (DeviceExtension->PortConfig->CachesData == TRUE)
{
IoMarkIrpPending(Irp);
- IoStartPacket(DeviceObject, Irp, NULL, NULL);
+ Srb->OriginalRequest = LunExtension;
+ Irp->Tail.Overlay.DriverContext[3] = Srb;
+ SpiProcessRequests(DeviceExtension, Irp);
return(STATUS_PENDING);
}
break;
{
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);
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
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 VOID
+SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PSCSI_REQUEST_BLOCK Srb)
{
- PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
- PSCSI_PORT_LUN_EXTENSION LunExtension;
- PIO_STACK_LOCATION IrpStack;
- PSCSI_REQUEST_BLOCK Srb;
- KIRQL oldIrql;
-
- DPRINT("ScsiPortStartIo() called!\n");
-
- DeviceExtension = DeviceObject->DeviceExtension;
- IrpStack = IoGetCurrentIrpStackLocation(Irp);
-
- DPRINT("DeviceExtension %p\n", DeviceExtension);
-
- oldIrql = KeGetCurrentIrql();
-
- if (IrpStack->MajorFunction != IRP_MJ_SCSI)
- {
- DPRINT("No IRP_MJ_SCSI!\n");
- Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest (Irp,
- IO_NO_INCREMENT);
- if (oldIrql < DISPATCH_LEVEL)
- {
- KeRaiseIrql (DISPATCH_LEVEL,
- &oldIrql);
- IoStartNextPacket (DeviceObject,
- FALSE);
- KeLowerIrql (oldIrql);
- }
- else
- {
- IoStartNextPacket (DeviceObject,
- FALSE);
- }
- return;
- }
+ ULONG index;
- Srb = IrpStack->Parameters.Scsi.Srb;
+ DPRINT("SpiAllocateSrbExtension\n");
- LunExtension = SpiGetLunExtension(DeviceExtension,
- Srb->PathId,
- Srb->TargetId,
- Srb->Lun);
- if (LunExtension == NULL)
- {
- DPRINT("Can't get LunExtension!\n");
- Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest (Irp,
- IO_NO_INCREMENT);
- if (oldIrql < DISPATCH_LEVEL)
- {
- KeRaiseIrql (DISPATCH_LEVEL,
- &oldIrql);
- IoStartNextPacket (DeviceObject,
- FALSE);
- KeLowerIrql (oldIrql);
- }
- else
- {
- IoStartNextPacket (DeviceObject,
- FALSE);
- }
- return;
- }
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = Srb->DataTransferLength;
-
- DeviceExtension->CurrentIrp = Irp;
+ DPRINT("DeviceExtension->VirtualAddress %x, DeviceExtension->SrbExtensionSize %x\n",
+ DeviceExtension->VirtualAddress, DeviceExtension->SrbExtensionSize);
- if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
- ScsiPortStartPacket,
- DeviceExtension))
+ Srb->SrbExtension = NULL;
+ if (DeviceExtension->VirtualAddress != NULL &&
+ DeviceExtension->SrbExtensionSize > 0)
{
- DPRINT("Synchronization failed!\n");
-
- Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp,
- IO_NO_INCREMENT);
- if (oldIrql < DISPATCH_LEVEL)
- {
- KeRaiseIrql (DISPATCH_LEVEL,
- &oldIrql);
- IoStartNextPacket (DeviceObject,
- FALSE);
- KeLowerIrql (oldIrql);
- }
- else
- {
- IoStartNextPacket (DeviceObject,
- FALSE);
+ 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);
+}
- KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
- if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
- {
- DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
- IoCompleteRequest(Irp,
- IO_NO_INCREMENT);
- }
+static VOID
+SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
+ PSCSI_REQUEST_BLOCK Srb)
+{
+ ULONG index;
- if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
- {
- DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
- KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
- IoStartNextPacket(DeviceObject,
- FALSE);
- KeLowerIrql(oldIrql);
- }
- else
+ if (DeviceExtension->VirtualAddress != NULL &&
+ DeviceExtension->SrbExtensionSize > 0 &&
+ Srb->SrbExtension != NULL)
{
- KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
+ index = ((ULONG_PTR)Srb->SrbExtension - (ULONG_PTR)DeviceExtension->VirtualAddress) / DeviceExtension->SrbExtensionSize;
+ RtlClearBits(&DeviceExtension->SrbExtensionAllocMap, index, 1);
+ DeviceExtension->CurrentSrbExtensions--;
}
-
- DPRINT("ScsiPortStartIo() done\n");
+ Srb->SrbExtension = NULL;
}
ScsiPortStartPacket(IN OUT PVOID Context)
{
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
- PIO_STACK_LOCATION IrpStack;
PSCSI_REQUEST_BLOCK Srb;
+ PIRP Irp;
+ PIO_STACK_LOCATION IrpStack;
- DPRINT("ScsiPortStartPacket() called\n");
-
- DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context;
-
- IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
- Srb = IrpStack->Parameters.Scsi.Srb;
+ DPRINT("ScsiPortStartPacket(Context %x) called\n", Context);
- /* Allocte SRB extension */
- if (DeviceExtension->SrbExtensionSize != 0)
- {
- Srb->SrbExtension = DeviceExtension->VirtualAddress;
- }
+ 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 NTSTATUS
SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
- IN OUT PSCSI_REQUEST_BLOCK Srb)
+ IN OUT PSCSI_REQUEST_BLOCK Srb,
+ IN OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN OUT PKEVENT Event)
{
- IO_STATUS_BLOCK IoStatusBlock;
PIO_STACK_LOCATION IrpStack;
- PKEVENT Event;
PIRP Irp;
NTSTATUS Status;
DPRINT ("SpiSendInquiry() called\n");
- Event = ExAllocatePool (NonPagedPool,
- sizeof(KEVENT));
- if (Event == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
KeInitializeEvent (Event,
NotificationEvent,
Srb->DataTransferLength,
TRUE,
Event,
- &IoStatusBlock);
+ IoStatusBlock);
if (Irp == NULL)
{
DPRINT("IoBuildDeviceIoControlRequest() failed\n");
- ExFreePool (Event);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Call the driver */
Status = IoCallDriver (DeviceObject,
Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject (Event,
- Suspended,
- KernelMode,
- FALSE,
- NULL);
- Status = IoStatusBlock.Status;
- }
-
- ExFreePool (Event);
return Status;
}
-
static VOID
SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
{
- PSCSI_PORT_LUN_EXTENSION LunExtension;
- SCSI_REQUEST_BLOCK Srb;
+ PSCSI_REQUEST_BLOCK Srb;
PCDB Cdb;
ULONG Bus;
ULONG Target;
- ULONG Lun;
- NTSTATUS Status;
+ PSCSI_PORT_SCAN_ADAPTER ScanDataArray;
+ PSCSI_PORT_SCAN_ADAPTER ScanData;
+ ULONG i;
+ ULONG MaxCount;
+ ULONG WaitCount;
+ ULONG ActiveCount;
+ PVOID* EventArray;
+ PKWAIT_BLOCK WaitBlockArray;
DPRINT ("SpiScanAdapter() called\n");
- 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 = 255; //256;
- Srb.CdbLength = 6;
-
- Cdb = (PCDB) &Srb.Cdb;
+ MaxCount = DeviceExtension->PortConfig->NumberOfBuses *
+ DeviceExtension->PortConfig->MaximumNumberOfTargets;
- Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
- Cdb->CDB6INQUIRY.AllocationLength = 255;
+ 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++)
{
- Srb.PathId = Bus;
-
for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
{
- Srb.TargetId = Target;
-
- for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
- {
- Srb.Lun = Lun;
- Srb.SrbStatus = SRB_STATUS_SUCCESS;
-
- Cdb->CDB6INQUIRY.LogicalUnitNumber = Lun;
-
- LunExtension = SpiAllocateLunExtension (DeviceExtension,
- Bus,
- Target,
- Lun);
- if (LunExtension == NULL)
- {
- DPRINT("Failed to allocate the LUN extension!\n");
- ExFreePool(Srb.DataBuffer);
- return;
+ 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;
}
-
- Status = SpiSendInquiry (DeviceExtension->DeviceObject,
- &Srb);
- DPRINT ("Status %lx Srb.SrbStatus %x\n", Status, Srb.SrbStatus);
-
- if (NT_SUCCESS(Status) &&
- (Srb.SrbStatus == SRB_STATUS_SUCCESS ||
- Srb.SrbStatus == SRB_STATUS_DATA_OVERRUN) &&
- ((PINQUIRYDATA)Srb.DataBuffer)->DeviceTypeQualifier == 0)
+ 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)
{
/* Copy inquiry data */
- RtlCopyMemory (&LunExtension->InquiryData,
- Srb.DataBuffer,
- sizeof(INQUIRYDATA));
+ RtlCopyMemory (&ScanData->LunExtension->InquiryData,
+ Srb->DataBuffer,
+ min(sizeof(INQUIRYDATA), Srb->DataTransferLength));
+ ScanData->Lun++;
}
else
{
- SpiRemoveLunExtension (LunExtension);
+ 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);
+ ExFreePool(ScanDataArray);
DPRINT ("SpiScanAdapter() done\n");
}
{
DPRINT("(Bus %lu Target %lu Lun %lu)\n",
Bus, Target, Lun);
-
+ RtlZeroMemory(UnitInfo, sizeof(*UnitInfo));
UnitInfo->PathId = Bus;
UnitInfo->TargetId = Target;
UnitInfo->Lun = Lun;
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;
- 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;
- KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
- 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);
-
- /* 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;
- ScsiPortFreeSenseRequestSrb (DeviceExtension);
- }
- 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);
- KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
- 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;
- KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
- IoStartNextPacket(DpcDeviceObject, FALSE);
- }
- else
- {
- KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
- }
- }
- else
- {
- KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
- }
+ SpiProcessRequests(DeviceExtension, NULL);
- 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 */
- RtlRosInitUnicodeStringFromLiteral(&KeyName,
- L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
}
/* 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");
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 */