mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 17:56:00 +00:00
- Rewrote the code which handles processing of irp's and notifications from miniport driver.
- Implemented support for srb extensions (very simple). svn path=/trunk/; revision=8999
This commit is contained in:
parent
c44ac169e6
commit
bfde26a3f6
2 changed files with 460 additions and 279 deletions
|
@ -16,13 +16,14 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
/* $Id: scsiport.c,v 1.52 2004/04/02 15:43:01 hbirr Exp $
|
/* $Id: scsiport.c,v 1.53 2004/04/07 09:21:01 hbirr Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: services/storage/scsiport/scsiport.c
|
* FILE: services/storage/scsiport/scsiport.c
|
||||||
* PURPOSE: SCSI port driver
|
* PURPOSE: SCSI port driver
|
||||||
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
|
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
|
||||||
|
* Hartmut Birr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
|
@ -41,17 +42,24 @@
|
||||||
|
|
||||||
#include "scsiport_int.h"
|
#include "scsiport_int.h"
|
||||||
|
|
||||||
/* #define USE_DEVICE_QUEUES */
|
|
||||||
|
|
||||||
/* TYPES *********************************************************************/
|
/* TYPES *********************************************************************/
|
||||||
|
|
||||||
#define IRP_FLAG_COMPLETE 0x00000001
|
#define IRP_FLAG_COMPLETE 0x00000001
|
||||||
#define IRP_FLAG_NEXT 0x00000002
|
#define IRP_FLAG_NEXT 0x00000002
|
||||||
#define IRP_FLAG_NEXT_LU 0x00000004
|
#define IRP_FLAG_NEXT_LU 0x00000004
|
||||||
|
|
||||||
|
#define MAX_SRB_EXTENSIONS 32
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
PIRP NextIrp);
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
SpiStartIo(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
|
SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
|
||||||
IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
|
IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
|
||||||
|
@ -70,10 +78,6 @@ static NTSTATUS STDCALL
|
||||||
ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||||
IN PIRP Irp);
|
IN PIRP Irp);
|
||||||
|
|
||||||
static VOID STDCALL
|
|
||||||
ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp);
|
|
||||||
|
|
||||||
static BOOLEAN STDCALL
|
static BOOLEAN STDCALL
|
||||||
ScsiPortStartPacket(IN OUT PVOID Context);
|
ScsiPortStartPacket(IN OUT PVOID Context);
|
||||||
|
|
||||||
|
@ -119,16 +123,20 @@ ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
||||||
PVOID Context);
|
PVOID Context);
|
||||||
|
|
||||||
static PSCSI_REQUEST_BLOCK
|
static PSCSI_REQUEST_BLOCK
|
||||||
ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb);
|
||||||
PSCSI_REQUEST_BLOCK OriginalSrb);
|
|
||||||
|
|
||||||
static VOID
|
|
||||||
ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
|
||||||
|
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
PUNICODE_STRING RegistryPath);
|
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 *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
@ -568,12 +576,13 @@ ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
|
||||||
|
|
||||||
/* Allocate a common DMA buffer */
|
/* Allocate a common DMA buffer */
|
||||||
DeviceExtension->CommonBufferLength =
|
DeviceExtension->CommonBufferLength =
|
||||||
NumberOfBytes + DeviceExtension->SrbExtensionSize;
|
NumberOfBytes + PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * MAX_SRB_EXTENSIONS);
|
||||||
DeviceExtension->VirtualAddress =
|
DeviceExtension->VirtualAddress =
|
||||||
HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
|
HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
|
||||||
DeviceExtension->CommonBufferLength,
|
DeviceExtension->CommonBufferLength,
|
||||||
&DeviceExtension->PhysicalAddress,
|
&DeviceExtension->PhysicalAddress,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
DeviceExtension->VirtualAddressMap = 0;
|
||||||
if (DeviceExtension->VirtualAddress == NULL)
|
if (DeviceExtension->VirtualAddress == NULL)
|
||||||
{
|
{
|
||||||
DPRINT1("HalAllocateCommonBuffer() failed!\n");
|
DPRINT1("HalAllocateCommonBuffer() failed!\n");
|
||||||
|
@ -582,7 +591,7 @@ ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
|
||||||
}
|
}
|
||||||
|
|
||||||
return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress +
|
return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress +
|
||||||
DeviceExtension->SrbExtensionSize);
|
PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * MAX_SRB_EXTENSIONS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -685,7 +694,7 @@ ScsiPortInitialize(IN PVOID Argument1,
|
||||||
(HwInitializationData->HwResetBus == NULL))
|
(HwInitializationData->HwResetBus == NULL))
|
||||||
return(STATUS_INVALID_PARAMETER);
|
return(STATUS_INVALID_PARAMETER);
|
||||||
|
|
||||||
DriverObject->DriverStartIo = ScsiPortStartIo;
|
DriverObject->DriverStartIo = NULL;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
|
||||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
|
||||||
|
@ -738,6 +747,7 @@ ScsiPortInitialize(IN PVOID Argument1,
|
||||||
PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
||||||
|
|
||||||
DeviceExtension = PortDeviceObject->DeviceExtension;
|
DeviceExtension = PortDeviceObject->DeviceExtension;
|
||||||
|
RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
|
||||||
DeviceExtension->Length = DeviceExtensionSize;
|
DeviceExtension->Length = DeviceExtensionSize;
|
||||||
DeviceExtension->DeviceObject = PortDeviceObject;
|
DeviceExtension->DeviceObject = PortDeviceObject;
|
||||||
DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
|
DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
|
||||||
|
@ -759,6 +769,12 @@ ScsiPortInitialize(IN PVOID Argument1,
|
||||||
/* Initialize the device base list */
|
/* Initialize the device base list */
|
||||||
InitializeListHead (&DeviceExtension->DeviceBaseListHead);
|
InitializeListHead (&DeviceExtension->DeviceBaseListHead);
|
||||||
|
|
||||||
|
/* Initialize the irp lists */
|
||||||
|
InitializeListHead (&DeviceExtension->PendingIrpListHead);
|
||||||
|
InitializeListHead (&DeviceExtension->ActiveIrpListHead);
|
||||||
|
DeviceExtension->PendingIrpCount = 0;
|
||||||
|
DeviceExtension->ActiveIrpCount = 0;
|
||||||
|
|
||||||
/* Initialize LUN-Extension list */
|
/* Initialize LUN-Extension list */
|
||||||
InitializeListHead (&DeviceExtension->LunExtensionListHead);
|
InitializeListHead (&DeviceExtension->LunExtensionListHead);
|
||||||
|
|
||||||
|
@ -826,6 +842,9 @@ ScsiPortInitialize(IN PVOID Argument1,
|
||||||
PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
|
PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
|
||||||
// PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
|
// PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
|
||||||
|
|
||||||
|
PortConfig->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
|
||||||
|
PortConfig->SpecificLuExtensionSize = HwInitializationData->SpecificLuExtensionSize;
|
||||||
|
|
||||||
PortConfig->SlotNumber = SlotNumber.u.AsULONG;
|
PortConfig->SlotNumber = SlotNumber.u.AsULONG;
|
||||||
|
|
||||||
PortConfig->AccessRanges = (PACCESS_RANGE)(PortConfig + 1);
|
PortConfig->AccessRanges = (PACCESS_RANGE)(PortConfig + 1);
|
||||||
|
@ -870,13 +889,35 @@ ScsiPortInitialize(IN PVOID Argument1,
|
||||||
{
|
{
|
||||||
DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig->BusInterruptVector);
|
DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig->BusInterruptVector);
|
||||||
|
|
||||||
|
|
||||||
|
if (DeviceExtension->VirtualAddress == NULL && DeviceExtension->SrbExtensionSize)
|
||||||
|
{
|
||||||
|
ScsiPortGetUncachedExtension(&DeviceExtension->MiniPortDeviceExtension,
|
||||||
|
PortConfig,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Register an interrupt handler for this device */
|
/* Register an interrupt handler for this device */
|
||||||
MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,
|
MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,
|
||||||
PortConfig->SystemIoBusNumber,
|
PortConfig->SystemIoBusNumber,
|
||||||
PortConfig->BusInterruptLevel,
|
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,
|
PortConfig->BusInterruptVector,
|
||||||
|
#endif
|
||||||
&Dirql,
|
&Dirql,
|
||||||
&Affinity);
|
&Affinity);
|
||||||
|
DPRINT("AdapterInterfaceType %x, SystemIoBusNumber %x, BusInterruptLevel %x, BusInterruptVector %x\n",
|
||||||
|
PortConfig->AdapterInterfaceType, PortConfig->SystemIoBusNumber,
|
||||||
|
PortConfig->BusInterruptLevel, PortConfig->BusInterruptVector);
|
||||||
Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
|
Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
|
||||||
ScsiPortIsr,
|
ScsiPortIsr,
|
||||||
DeviceExtension,
|
DeviceExtension,
|
||||||
|
@ -1089,12 +1130,15 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
|
||||||
|
|
||||||
DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
|
DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
|
||||||
DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
|
DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
|
||||||
|
Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
|
||||||
|
InterlockedIncrement((PLONG)&DeviceExtension->CompleteRequestCount);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NextRequest:
|
case NextRequest:
|
||||||
DPRINT("Notify: NextRequest\n");
|
DPRINT("Notify: NextRequest\n");
|
||||||
DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
|
DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
|
||||||
|
InterlockedIncrement((PLONG)&DeviceExtension->NextRequestCount);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NextLuRequest:
|
case NextLuRequest:
|
||||||
|
@ -1102,20 +1146,25 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
|
||||||
UCHAR PathId;
|
UCHAR PathId;
|
||||||
UCHAR TargetId;
|
UCHAR TargetId;
|
||||||
UCHAR Lun;
|
UCHAR Lun;
|
||||||
|
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
||||||
|
|
||||||
PathId = (UCHAR) va_arg (ap, int);
|
PathId = (UCHAR) va_arg (ap, int);
|
||||||
TargetId = (UCHAR) va_arg (ap, int);
|
TargetId = (UCHAR) va_arg (ap, int);
|
||||||
Lun = (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);
|
PathId, TargetId, Lun);
|
||||||
/* FIXME: Implement it! */
|
|
||||||
|
|
||||||
DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
|
LunExtension = SpiGetLunExtension(DeviceExtension,
|
||||||
// DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
|
PathId,
|
||||||
|
TargetId,
|
||||||
/* Hack! */
|
Lun);
|
||||||
DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
|
if (LunExtension)
|
||||||
|
{
|
||||||
|
DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
|
||||||
|
InterlockedIncrement((PLONG)&LunExtension->NextLuRequestCount);
|
||||||
|
InterlockedIncrement((PLONG)&DeviceExtension->NextLuRequestCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1425,34 +1474,10 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
|
||||||
{
|
{
|
||||||
case SRB_FUNCTION_EXECUTE_SCSI:
|
case SRB_FUNCTION_EXECUTE_SCSI:
|
||||||
case SRB_FUNCTION_IO_CONTROL:
|
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);
|
IoMarkIrpPending(Irp);
|
||||||
IoStartPacket (DeviceObject, Irp, NULL, NULL);
|
Srb->OriginalRequest = LunExtension;
|
||||||
#endif
|
Irp->Tail.Overlay.DriverContext[3] = Srb;
|
||||||
|
SpiProcessRequests(DeviceExtension, Irp);
|
||||||
return(STATUS_PENDING);
|
return(STATUS_PENDING);
|
||||||
|
|
||||||
case SRB_FUNCTION_SHUTDOWN:
|
case SRB_FUNCTION_SHUTDOWN:
|
||||||
|
@ -1460,7 +1485,9 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
|
||||||
if (DeviceExtension->PortConfig->CachesData == TRUE)
|
if (DeviceExtension->PortConfig->CachesData == TRUE)
|
||||||
{
|
{
|
||||||
IoMarkIrpPending(Irp);
|
IoMarkIrpPending(Irp);
|
||||||
IoStartPacket(DeviceObject, Irp, NULL, NULL);
|
Srb->OriginalRequest = LunExtension;
|
||||||
|
Irp->Tail.Overlay.DriverContext[3] = Srb;
|
||||||
|
SpiProcessRequests(DeviceExtension, Irp);
|
||||||
return(STATUS_PENDING);
|
return(STATUS_PENDING);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1581,130 +1608,49 @@ ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID
|
||||||
static VOID STDCALL
|
SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
|
PSCSI_REQUEST_BLOCK Srb)
|
||||||
IN PIRP Irp)
|
|
||||||
{
|
{
|
||||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
ULONG i;
|
||||||
PSCSI_PORT_LUN_EXTENSION LunExtension;
|
ULONG mask;
|
||||||
PIO_STACK_LOCATION IrpStack;
|
|
||||||
PSCSI_REQUEST_BLOCK Srb;
|
|
||||||
KIRQL oldIrql;
|
|
||||||
|
|
||||||
DPRINT("ScsiPortStartIo() called!\n");
|
DPRINT("SpiAllocateSrbExtension\n");
|
||||||
|
|
||||||
DeviceExtension = DeviceObject->DeviceExtension;
|
DPRINT("DeviceExtension->VirtualAddress %x, DeviceExtension->SrbExtensionSize %x\n",
|
||||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
DeviceExtension->VirtualAddress, DeviceExtension->SrbExtensionSize);
|
||||||
|
|
||||||
DPRINT("DeviceExtension %p\n", DeviceExtension);
|
if (DeviceExtension->VirtualAddress != NULL &&
|
||||||
|
DeviceExtension->SrbExtensionSize > 0)
|
||||||
oldIrql = KeGetCurrentIrql();
|
|
||||||
|
|
||||||
if (IrpStack->MajorFunction != IRP_MJ_SCSI)
|
|
||||||
{
|
{
|
||||||
DPRINT("No IRP_MJ_SCSI!\n");
|
for (i = 0, mask = 1; i < MAX_SRB_EXTENSIONS; i++, mask <<= 1)
|
||||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
{
|
||||||
Irp->IoStatus.Information = 0;
|
if (!(DeviceExtension->VirtualAddressMap & mask))
|
||||||
IoCompleteRequest (Irp,
|
{
|
||||||
IO_NO_INCREMENT);
|
DeviceExtension->VirtualAddressMap |= mask;
|
||||||
if (oldIrql < DISPATCH_LEVEL)
|
Srb->SrbExtension = DeviceExtension->VirtualAddress + i * DeviceExtension->SrbExtensionSize;
|
||||||
{
|
DPRINT("%x\n", Srb->SrbExtension);
|
||||||
KeRaiseIrql (DISPATCH_LEVEL,
|
return;
|
||||||
&oldIrql);
|
}
|
||||||
IoStartNextPacket (DeviceObject,
|
|
||||||
FALSE);
|
|
||||||
KeLowerIrql (oldIrql);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IoStartNextPacket (DeviceObject,
|
|
||||||
FALSE);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Srb = IrpStack->Parameters.Scsi.Srb;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
|
|
||||||
ScsiPortStartPacket,
|
|
||||||
DeviceExtension))
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Srb->SrbExtension = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
|
static VOID
|
||||||
if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
|
SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
{
|
PSCSI_REQUEST_BLOCK Srb)
|
||||||
DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
|
{
|
||||||
IoCompleteRequest(Irp,
|
ULONG i;
|
||||||
IO_NO_INCREMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
|
if (DeviceExtension->VirtualAddress != NULL &&
|
||||||
|
DeviceExtension->SrbExtensionSize > 0 &&
|
||||||
|
Srb->SrbExtension != NULL)
|
||||||
{
|
{
|
||||||
DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
|
i = ((ULONG_PTR)Srb->SrbExtension - (ULONG_PTR)DeviceExtension->VirtualAddress) / DeviceExtension->SrbExtensionSize;
|
||||||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
|
DeviceExtension->VirtualAddressMap &= ~(1 << i);
|
||||||
IoStartNextPacket(DeviceObject,
|
|
||||||
FALSE);
|
|
||||||
KeLowerIrql(oldIrql);
|
|
||||||
}
|
}
|
||||||
else
|
Srb->SrbExtension = NULL;
|
||||||
{
|
|
||||||
KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("ScsiPortStartIo() done\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1712,21 +1658,16 @@ static BOOLEAN STDCALL
|
||||||
ScsiPortStartPacket(IN OUT PVOID Context)
|
ScsiPortStartPacket(IN OUT PVOID Context)
|
||||||
{
|
{
|
||||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||||
PIO_STACK_LOCATION IrpStack;
|
|
||||||
PSCSI_REQUEST_BLOCK Srb;
|
PSCSI_REQUEST_BLOCK Srb;
|
||||||
|
PIRP Irp;
|
||||||
|
PIO_STACK_LOCATION IrpStack;
|
||||||
|
|
||||||
DPRINT("ScsiPortStartPacket() called\n");
|
DPRINT("ScsiPortStartPacket() called\n");
|
||||||
|
|
||||||
DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context;
|
Srb = (PSCSI_REQUEST_BLOCK)Context;
|
||||||
|
Irp = (PIRP)Srb->OriginalRequest;
|
||||||
IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
Srb = IrpStack->Parameters.Scsi.Srb;
|
DeviceExtension = IrpStack->DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
/* Allocte SRB extension */
|
|
||||||
if (DeviceExtension->SrbExtensionSize != 0)
|
|
||||||
{
|
|
||||||
Srb->SrbExtension = DeviceExtension->VirtualAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
|
return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
|
||||||
Srb));
|
Srb));
|
||||||
|
@ -1766,7 +1707,8 @@ SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
LunExtension->TargetId = TargetId;
|
LunExtension->TargetId = TargetId;
|
||||||
LunExtension->Lun = Lun;
|
LunExtension->Lun = Lun;
|
||||||
|
|
||||||
KeInitializeDeviceQueue (&LunExtension->DeviceQueue);
|
LunExtension->PendingIrpCount = 0;
|
||||||
|
LunExtension->ActiveIrpCount = 0;
|
||||||
|
|
||||||
return LunExtension;
|
return LunExtension;
|
||||||
}
|
}
|
||||||
|
@ -2064,7 +2006,7 @@ ScsiPortIsr(IN PKINTERRUPT Interrupt,
|
||||||
if (DeviceExtension->IrpFlags)
|
if (DeviceExtension->IrpFlags)
|
||||||
{
|
{
|
||||||
IoRequestDpc(DeviceExtension->DeviceObject,
|
IoRequestDpc(DeviceExtension->DeviceObject,
|
||||||
DeviceExtension->CurrentIrp,
|
NULL,
|
||||||
DeviceExtension);
|
DeviceExtension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2090,96 +2032,13 @@ ScsiPortDpcForIsr(IN PKDPC Dpc,
|
||||||
IN PVOID DpcContext)
|
IN PVOID DpcContext)
|
||||||
{
|
{
|
||||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
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("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
|
||||||
Dpc, DpcDeviceObject, DpcIrp, DpcContext);
|
Dpc, DpcDeviceObject, DpcIrp, DpcContext);
|
||||||
|
|
||||||
DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
|
DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
|
||||||
|
|
||||||
KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
|
SpiProcessRequests(DeviceExtension, NULL);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("ScsiPortDpcForIsr() done\n");
|
DPRINT("ScsiPortDpcForIsr() done\n");
|
||||||
}
|
}
|
||||||
|
@ -2205,27 +2064,29 @@ ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
||||||
|
|
||||||
|
|
||||||
static PSCSI_REQUEST_BLOCK
|
static PSCSI_REQUEST_BLOCK
|
||||||
ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb)
|
||||||
PSCSI_REQUEST_BLOCK OriginalSrb)
|
|
||||||
{
|
{
|
||||||
PSCSI_REQUEST_BLOCK Srb;
|
PSCSI_REQUEST_BLOCK Srb;
|
||||||
PCDB Cdb;
|
PCDB Cdb;
|
||||||
|
|
||||||
Srb = &DeviceExtension->InternalSrb;
|
Srb = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
|
sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA),
|
||||||
|
TAG('S', 'S', 'r', 'b'));
|
||||||
|
|
||||||
RtlZeroMemory(Srb,
|
RtlZeroMemory(Srb,
|
||||||
sizeof(SCSI_REQUEST_BLOCK));
|
sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA));
|
||||||
|
|
||||||
Srb->PathId = OriginalSrb->PathId;
|
Srb->PathId = OriginalSrb->PathId;
|
||||||
Srb->TargetId = OriginalSrb->TargetId;
|
Srb->TargetId = OriginalSrb->TargetId;
|
||||||
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
|
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||||
Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
|
Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||||
Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
|
Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
|
||||||
|
Srb->OriginalRequest = OriginalSrb->OriginalRequest;
|
||||||
|
|
||||||
Srb->TimeOutValue = 4;
|
Srb->TimeOutValue = 4;
|
||||||
|
|
||||||
Srb->CdbLength = 6;
|
Srb->CdbLength = 6;
|
||||||
Srb->DataBuffer = &DeviceExtension->InternalSenseData;
|
Srb->DataBuffer = Srb + 1;
|
||||||
Srb->DataTransferLength = sizeof(SENSE_DATA);
|
Srb->DataTransferLength = sizeof(SENSE_DATA);
|
||||||
|
|
||||||
Cdb = (PCDB)Srb->Cdb;
|
Cdb = (PCDB)Srb->Cdb;
|
||||||
|
@ -2235,14 +2096,6 @@ ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||||
return(Srb);
|
return(Srb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static VOID
|
|
||||||
ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
|
||||||
{
|
|
||||||
DeviceExtension->OriginalSrb = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* NAME INTERNAL
|
* NAME INTERNAL
|
||||||
* SpiBuildDeviceMap
|
* SpiBuildDeviceMap
|
||||||
|
@ -2666,4 +2519,321 @@ ByeBye:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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] and DriverContext[1] -> ListEntry for queue
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
DPRINT("SpiProcessRequests() called\n");
|
||||||
|
|
||||||
|
InitializeListHead(&NextIrpListHead);
|
||||||
|
InitializeListHead(&CompleteIrpListHead);
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
|
||||||
|
|
||||||
|
if (NextIrp)
|
||||||
|
{
|
||||||
|
Srb = NextIrp->Tail.Overlay.DriverContext[3];
|
||||||
|
NextIrp->Tail.Overlay.DriverContext[2] = (PVOID)Srb->QueueSortKey;
|
||||||
|
|
||||||
|
ListEntry = DeviceExtension->PendingIrpListHead.Flink;
|
||||||
|
while (ListEntry != DeviceExtension->PendingIrpListHead.Flink)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (DeviceExtension->CompleteRequestCount ||
|
||||||
|
((DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->ActiveIrpCount < MAX_SRB_EXTENSIONS) && !IsListEmpty(&DeviceExtension->PendingIrpListHead) &&
|
||||||
|
(DeviceExtension->NextRequestCount || DeviceExtension->NextLuRequestCount || IsListEmpty(&DeviceExtension->ActiveIrpListHead))))
|
||||||
|
{
|
||||||
|
DPRINT("CompleteRequestCount %d, NextRequestCount %d, NextLuRequestCount %d, PendingIrpList is %s, ActiveIrpList is %s\n",
|
||||||
|
DeviceExtension->CompleteRequestCount,
|
||||||
|
DeviceExtension->NextRequestCount,
|
||||||
|
DeviceExtension->NextLuRequestCount,
|
||||||
|
IsListEmpty(&DeviceExtension->PendingIrpListHead) ? "EMPTY" : "NOT empty",
|
||||||
|
IsListEmpty(&DeviceExtension->ActiveIrpListHead) ? "EMPTY" : "NOT empty");
|
||||||
|
|
||||||
|
if (DeviceExtension->CompleteRequestCount > 0)
|
||||||
|
{
|
||||||
|
DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
|
||||||
|
ListEntry = DeviceExtension->ActiveIrpListHead.Flink;
|
||||||
|
while (ListEntry != &DeviceExtension->ActiveIrpListHead)
|
||||||
|
{
|
||||||
|
Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
|
||||||
|
ListEntry = ListEntry->Flink;
|
||||||
|
Srb = Irp->Tail.Overlay.DriverContext[3];
|
||||||
|
if (!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE))
|
||||||
|
{
|
||||||
|
BOOLEAN CompleteThisRequest;
|
||||||
|
InterlockedDecrement((PLONG)&DeviceExtension->CompleteRequestCount);
|
||||||
|
LunExtension = Irp->Tail.Overlay.DriverContext[2];
|
||||||
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
OriginalSrb = IrpStack->Parameters.Scsi.Srb;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
if (OriginalSrb->SenseInfoBufferLength != 0)
|
||||||
|
{
|
||||||
|
RtlCopyMemory(OriginalSrb->SenseInfoBuffer,
|
||||||
|
SenseInfoBuffer,
|
||||||
|
sizeof(SENSE_DATA));
|
||||||
|
OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
|
||||||
|
}
|
||||||
|
ExFreePool(Srb);
|
||||||
|
CompleteThisRequest = TRUE;
|
||||||
|
}
|
||||||
|
else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
|
||||||
|
(Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION))
|
||||||
|
{
|
||||||
|
DPRINT("SCSIOP_REQUEST_SENSE required!\n");
|
||||||
|
|
||||||
|
Srb = ScsiPortInitSenseRequestSrb(OriginalSrb);
|
||||||
|
|
||||||
|
if (Srb)
|
||||||
|
{
|
||||||
|
CompleteThisRequest = FALSE;
|
||||||
|
Irp->Tail.Overlay.DriverContext[3] = Srb;
|
||||||
|
RemoveEntryList((PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
|
||||||
|
SpiFreeSrbExtension(DeviceExtension, Srb);
|
||||||
|
LunExtension->ActiveIrpCount--;
|
||||||
|
DeviceExtension->ActiveIrpCount--;
|
||||||
|
|
||||||
|
Srb->OriginalRequest = LunExtension;
|
||||||
|
Irp->Tail.Overlay.DriverContext[2] = 0;
|
||||||
|
|
||||||
|
InsertHeadList(&DeviceExtension->PendingIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
|
||||||
|
DeviceExtension->PendingIrpCount++;
|
||||||
|
LunExtension->PendingIrpCount++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CompleteThisRequest = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("Complete Request\n");
|
||||||
|
CompleteThisRequest = TRUE;
|
||||||
|
}
|
||||||
|
if (CompleteThisRequest)
|
||||||
|
{
|
||||||
|
RemoveEntryList((PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
|
||||||
|
InsertHeadList(&CompleteIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
|
||||||
|
SpiFreeSrbExtension(DeviceExtension, OriginalSrb);
|
||||||
|
LunExtension->ActiveIrpCount--;
|
||||||
|
DeviceExtension->ActiveIrpCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (DeviceExtension->NextLuRequestCount ||
|
||||||
|
DeviceExtension->NextRequestCount)
|
||||||
|
{
|
||||||
|
BOOLEAN StartThisRequest;
|
||||||
|
DeviceExtension->IrpFlags &= ~(IRP_FLAG_NEXT|IRP_FLAG_NEXT_LU);
|
||||||
|
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->ActiveIrpCount >= MAX_SRB_EXTENSIONS)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (LunExtension->NextLuRequestCount > 0)
|
||||||
|
{
|
||||||
|
StartThisRequest = TRUE;
|
||||||
|
InterlockedDecrement((PLONG)&LunExtension->NextLuRequestCount);
|
||||||
|
InterlockedDecrement((PLONG)&DeviceExtension->NextLuRequestCount);
|
||||||
|
}
|
||||||
|
else if (DeviceExtension->NextRequestCount > 0 &&
|
||||||
|
LunExtension->ActiveIrpCount == 0)
|
||||||
|
{
|
||||||
|
InterlockedDecrement((PLONG)&DeviceExtension->NextRequestCount);
|
||||||
|
StartThisRequest = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartThisRequest = FALSE;
|
||||||
|
}
|
||||||
|
if (StartThisRequest)
|
||||||
|
{
|
||||||
|
LunExtension->PendingIrpCount--;
|
||||||
|
DeviceExtension->PendingIrpCount--;
|
||||||
|
RemoveEntryList((PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
|
||||||
|
LunExtension->ActiveIrpCount++;
|
||||||
|
DeviceExtension->ActiveIrpCount++;
|
||||||
|
SpiAllocateSrbExtension(DeviceExtension, Srb);
|
||||||
|
|
||||||
|
Irp->Tail.Overlay.DriverContext[2] = LunExtension;
|
||||||
|
Srb->OriginalRequest = Irp;
|
||||||
|
|
||||||
|
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]);
|
||||||
|
InsertHeadList(&DeviceExtension->ActiveIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
|
||||||
|
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
|
||||||
|
|
||||||
|
// Start this Irp
|
||||||
|
SpiStartIo(DeviceExtension, Irp);
|
||||||
|
KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsListEmpty(&DeviceExtension->PendingIrpListHead) &&
|
||||||
|
IsListEmpty(&DeviceExtension->ActiveIrpListHead) &&
|
||||||
|
(DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->ActiveIrpCount < MAX_SRB_EXTENSIONS))
|
||||||
|
{
|
||||||
|
ListEntry = RemoveHeadList(&DeviceExtension->PendingIrpListHead);
|
||||||
|
Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
|
||||||
|
Srb = Irp->Tail.Overlay.DriverContext[3];
|
||||||
|
LunExtension = Srb->OriginalRequest;
|
||||||
|
|
||||||
|
LunExtension->PendingIrpCount--;
|
||||||
|
DeviceExtension->PendingIrpCount--;
|
||||||
|
InsertHeadList(&DeviceExtension->ActiveIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
|
||||||
|
LunExtension->ActiveIrpCount++;
|
||||||
|
DeviceExtension->ActiveIrpCount++;
|
||||||
|
SpiAllocateSrbExtension(DeviceExtension, Srb);
|
||||||
|
|
||||||
|
Irp->Tail.Overlay.DriverContext[2] = LunExtension;
|
||||||
|
Srb->OriginalRequest = Irp;
|
||||||
|
|
||||||
|
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
|
||||||
|
|
||||||
|
// Start this irp
|
||||||
|
SpiStartIo(DeviceExtension, Irp);
|
||||||
|
KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsListEmpty(&CompleteIrpListHead))
|
||||||
|
{
|
||||||
|
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
|
||||||
|
while (!IsListEmpty(&CompleteIrpListHead))
|
||||||
|
{
|
||||||
|
ListEntry = RemoveTailList(&CompleteIrpListHead);
|
||||||
|
Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&DeviceExtension->IrpLock, 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;
|
||||||
|
PIO_STACK_LOCATION IrpStack;
|
||||||
|
|
||||||
|
DPRINT("SpiStartIo() called!\n");
|
||||||
|
|
||||||
|
assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
|
||||||
|
Srb = Irp->Tail.Overlay.DriverContext[3];
|
||||||
|
LunExtension = Irp->Tail.Overlay.DriverContext[2];
|
||||||
|
|
||||||
|
Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = Srb->DataTransferLength;
|
||||||
|
|
||||||
|
if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
|
||||||
|
ScsiPortStartPacket,
|
||||||
|
Srb))
|
||||||
|
{
|
||||||
|
DPRINT1("Synchronization failed!\n");
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
|
||||||
|
|
||||||
|
RemoveEntryList((PLIST_ENTRY)Irp->Tail.Overlay.DriverContext[0]);
|
||||||
|
LunExtension = Irp->Tail.Overlay.DriverContext[2];
|
||||||
|
LunExtension->ActiveIrpCount--;
|
||||||
|
SpiFreeSrbExtension(DeviceExtension, Srb);
|
||||||
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
if (IrpStack->Parameters.Scsi.Srb != Srb)
|
||||||
|
{
|
||||||
|
ExFreePool(Srb);
|
||||||
|
}
|
||||||
|
DeviceExtension->ActiveIrpCount--;
|
||||||
|
|
||||||
|
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("SpiStartIo() done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -37,7 +37,9 @@ typedef struct _SCSI_PORT_LUN_EXTENSION
|
||||||
|
|
||||||
INQUIRYDATA InquiryData;
|
INQUIRYDATA InquiryData;
|
||||||
|
|
||||||
KDEVICE_QUEUE DeviceQueue;
|
ULONG PendingIrpCount;
|
||||||
|
ULONG ActiveIrpCount;
|
||||||
|
ULONG NextLuRequestCount;
|
||||||
|
|
||||||
/* More data? */
|
/* More data? */
|
||||||
|
|
||||||
|
@ -63,7 +65,6 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
||||||
KSPIN_LOCK IrpLock;
|
KSPIN_LOCK IrpLock;
|
||||||
KSPIN_LOCK SpinLock;
|
KSPIN_LOCK SpinLock;
|
||||||
PKINTERRUPT Interrupt;
|
PKINTERRUPT Interrupt;
|
||||||
PIRP CurrentIrp;
|
|
||||||
ULONG IrpFlags;
|
ULONG IrpFlags;
|
||||||
|
|
||||||
SCSI_PORT_TIMER_STATES TimerState;
|
SCSI_PORT_TIMER_STATES TimerState;
|
||||||
|
@ -84,9 +85,6 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
||||||
PHW_STARTIO HwStartIo;
|
PHW_STARTIO HwStartIo;
|
||||||
PHW_INTERRUPT HwInterrupt;
|
PHW_INTERRUPT HwInterrupt;
|
||||||
|
|
||||||
PSCSI_REQUEST_BLOCK OriginalSrb;
|
|
||||||
SCSI_REQUEST_BLOCK InternalSrb;
|
|
||||||
SENSE_DATA InternalSenseData;
|
|
||||||
|
|
||||||
/* DMA related stuff */
|
/* DMA related stuff */
|
||||||
PADAPTER_OBJECT AdapterObject;
|
PADAPTER_OBJECT AdapterObject;
|
||||||
|
@ -94,7 +92,20 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
||||||
|
|
||||||
PHYSICAL_ADDRESS PhysicalAddress;
|
PHYSICAL_ADDRESS PhysicalAddress;
|
||||||
PVOID VirtualAddress;
|
PVOID VirtualAddress;
|
||||||
|
ULONG VirtualAddressMap;
|
||||||
ULONG CommonBufferLength;
|
ULONG CommonBufferLength;
|
||||||
|
|
||||||
|
LIST_ENTRY PendingIrpListHead;
|
||||||
|
LIST_ENTRY ActiveIrpListHead;
|
||||||
|
ULONG PendingIrpCount;
|
||||||
|
ULONG ActiveIrpCount;
|
||||||
|
|
||||||
|
ULONG CompleteRequestCount;
|
||||||
|
ULONG NextRequestCount;
|
||||||
|
ULONG NextLuRequestCount;
|
||||||
|
|
||||||
UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */
|
UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */
|
||||||
} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
|
} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue