mirror of
https://github.com/reactos/reactos.git
synced 2024-07-10 22:55:05 +00:00
- Enable DMA support, this time properly.
- Fix ScsiPortGetPhysicalAddress() function to use scatter-gather list, if needed. - Now BusLogic initializes succesfully, but BSODs later. svn path=/trunk/; revision=27470
This commit is contained in:
parent
081ca81b64
commit
ad9fd2687e
|
@ -85,6 +85,10 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
|
|||
static BOOLEAN STDCALL
|
||||
ScsiPortStartPacket(IN OUT PVOID Context);
|
||||
|
||||
IO_ALLOCATION_ACTION
|
||||
STDCALL
|
||||
SpiAdapterControl(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
||||
PVOID MapRegisterBase, PVOID Context);
|
||||
|
||||
static PSCSI_PORT_LUN_EXTENSION
|
||||
SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
|
||||
|
@ -95,6 +99,11 @@ SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
|||
IN UCHAR TargetId,
|
||||
IN UCHAR Lun);
|
||||
|
||||
static PSCSI_REQUEST_BLOCK_INFO
|
||||
SpiAllocateSrbStructures(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension,
|
||||
PSCSI_REQUEST_BLOCK Srb);
|
||||
|
||||
static NTSTATUS
|
||||
SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PSCSI_LUN_INFO LunInfo);
|
||||
|
@ -490,92 +499,64 @@ ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
|
|||
*/
|
||||
SCSI_PHYSICAL_ADDRESS STDCALL
|
||||
ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
|
||||
IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
|
||||
IN PVOID VirtualAddress,
|
||||
OUT ULONG *Length)
|
||||
IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
|
||||
IN PVOID VirtualAddress,
|
||||
OUT ULONG *Length)
|
||||
{
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
SCSI_PHYSICAL_ADDRESS PhysicalAddress;
|
||||
SCSI_PHYSICAL_ADDRESS NextPhysicalAddress;
|
||||
ULONG BufferLength = 0;
|
||||
ULONG Offset;
|
||||
PVOID EndAddress;
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
SCSI_PHYSICAL_ADDRESS PhysicalAddress;
|
||||
ULONG BufferLength = 0;
|
||||
ULONG Offset;
|
||||
PSCSI_SG_ADDRESS SGList;
|
||||
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
|
||||
|
||||
DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
|
||||
HwDeviceExtension, Srb, VirtualAddress, Length);
|
||||
DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
|
||||
HwDeviceExtension, Srb, VirtualAddress, Length);
|
||||
|
||||
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
|
||||
SCSI_PORT_DEVICE_EXTENSION,
|
||||
MiniPortDeviceExtension);
|
||||
DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
|
||||
SCSI_PORT_DEVICE_EXTENSION,
|
||||
MiniPortDeviceExtension);
|
||||
|
||||
*Length = 0;
|
||||
|
||||
if (Srb == NULL)
|
||||
if (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress)
|
||||
{
|
||||
if ((ULONG_PTR)DeviceExtension->VirtualAddress > (ULONG_PTR)VirtualAddress)
|
||||
{
|
||||
PhysicalAddress.QuadPart = 0ULL;
|
||||
return PhysicalAddress;
|
||||
}
|
||||
/* Simply look it up in the allocated common buffer */
|
||||
Offset = (PUCHAR)VirtualAddress - (PUCHAR)DeviceExtension->SrbExtensionBuffer;
|
||||
|
||||
Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
|
||||
if (Offset >= DeviceExtension->CommonBufferLength)
|
||||
{
|
||||
PhysicalAddress.QuadPart = 0ULL;
|
||||
return PhysicalAddress;
|
||||
}
|
||||
|
||||
PhysicalAddress.QuadPart =
|
||||
DeviceExtension->PhysicalAddress.QuadPart + (ULONGLONG)Offset;
|
||||
BufferLength = DeviceExtension->CommonBufferLength - Offset;
|
||||
BufferLength = DeviceExtension->CommonBufferSize - Offset;
|
||||
PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset;
|
||||
}
|
||||
else
|
||||
else if (DeviceExtension->MapRegisters)
|
||||
{
|
||||
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;
|
||||
}
|
||||
/* Scatter-gather list must be used */
|
||||
SrbInfo = SpiGetSrbData(DeviceExtension,
|
||||
Srb->PathId,
|
||||
Srb->TargetId,
|
||||
Srb->Lun,
|
||||
Srb->QueueTag);
|
||||
|
||||
PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
|
||||
if (PhysicalAddress.QuadPart == 0LL)
|
||||
{
|
||||
return PhysicalAddress;
|
||||
}
|
||||
SGList = SrbInfo->ScatterGather;
|
||||
|
||||
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 ((ULONG_PTR)VirtualAddress + BufferLength < (ULONG_PTR)EndAddress)
|
||||
{
|
||||
NextPhysicalAddress = MmGetPhysicalAddress((PVOID)((ULONG_PTR)VirtualAddress + BufferLength));
|
||||
if (PhysicalAddress.QuadPart + (ULONGLONG)BufferLength != NextPhysicalAddress.QuadPart)
|
||||
{
|
||||
break;
|
||||
}
|
||||
BufferLength += PAGE_SIZE;
|
||||
}
|
||||
if ((ULONG_PTR)VirtualAddress + BufferLength >= (ULONG_PTR)EndAddress)
|
||||
{
|
||||
BufferLength = (ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress;
|
||||
}
|
||||
/* Find needed item in the SG list */
|
||||
Offset = (PCHAR)VirtualAddress - (PCHAR)Srb->DataBuffer;
|
||||
while (Offset >= SGList->Length)
|
||||
{
|
||||
Offset -= SGList->Length;
|
||||
SGList++;
|
||||
}
|
||||
|
||||
/* We're done, store length and physical address */
|
||||
BufferLength = SGList->Length - Offset;
|
||||
PhysicalAddress.QuadPart = SGList->PhysicalAddress.QuadPart + Offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing */
|
||||
*Length = 0;
|
||||
PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE);
|
||||
}
|
||||
|
||||
*Length = BufferLength;
|
||||
|
||||
return PhysicalAddress;
|
||||
*Length = BufferLength;
|
||||
return PhysicalAddress;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2727,6 +2708,7 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
|
|||
PSCSI_REQUEST_BLOCK Srb;
|
||||
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
|
||||
LONG CounterResult;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("ScsiPortStartIo() called!\n");
|
||||
|
||||
|
@ -2749,9 +2731,21 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
|
|||
if (DeviceExtension->NeedSrbDataAlloc ||
|
||||
DeviceExtension->NeedSrbExtensionAlloc)
|
||||
{
|
||||
/* TODO: Implement */
|
||||
ASSERT(FALSE);
|
||||
SrbInfo = NULL;
|
||||
/* Allocate them */
|
||||
SrbInfo = SpiAllocateSrbStructures(DeviceExtension,
|
||||
LunExtension,
|
||||
Srb);
|
||||
|
||||
/* Couldn't alloc one or both data structures, return */
|
||||
if (SrbInfo == NULL)
|
||||
{
|
||||
/* We have to call IoStartNextPacket, because this request
|
||||
was not started */
|
||||
if (LunExtension->Flags & LUNEX_REQUEST_PENDING)
|
||||
IoStartNextPacket(DeviceObject, FALSE);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2806,7 +2800,6 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
|
|||
|
||||
if (DeviceExtension->MapRegisters)
|
||||
{
|
||||
#if 0
|
||||
/* Calculate number of needed map registers */
|
||||
SrbInfo->NumberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
|
||||
Srb->DataBuffer,
|
||||
|
@ -2837,9 +2830,6 @@ ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
|
|||
|
||||
/* Control goes to SpiAdapterControl */
|
||||
return;
|
||||
#else
|
||||
ASSERT(FALSE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3038,6 +3028,87 @@ ScsiPortStartPacket(IN OUT PVOID Context)
|
|||
return Result;
|
||||
}
|
||||
|
||||
IO_ALLOCATION_ACTION
|
||||
STDCALL
|
||||
SpiAdapterControl(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID MapRegisterBase,
|
||||
PVOID Context)
|
||||
{
|
||||
PSCSI_REQUEST_BLOCK Srb;
|
||||
PSCSI_SG_ADDRESS ScatterGatherList;
|
||||
KIRQL CurrentIrql;
|
||||
PIO_STACK_LOCATION IrpStack;
|
||||
ULONG TotalLength = 0;
|
||||
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
PUCHAR DataVA;
|
||||
BOOLEAN WriteToDevice;
|
||||
|
||||
/* Get pointers to SrbInfo and DeviceExtension */
|
||||
SrbInfo = (PSCSI_REQUEST_BLOCK_INFO)Context;
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
/* Get pointer to SRB */
|
||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1;
|
||||
|
||||
/* Depending on the map registers number, we allocate
|
||||
either from NonPagedPool, or from our static list */
|
||||
if (SrbInfo->NumberOfMapRegisters > MAX_SG_LIST)
|
||||
{
|
||||
SrbInfo->ScatterGather = ExAllocatePool(
|
||||
NonPagedPool, SrbInfo->NumberOfMapRegisters * sizeof(SCSI_SG_ADDRESS));
|
||||
|
||||
if (SrbInfo->ScatterGather == NULL)
|
||||
ASSERT(FALSE);
|
||||
|
||||
Srb->SrbFlags |= SRB_FLAGS_SGLIST_FROM_POOL;
|
||||
}
|
||||
else
|
||||
{
|
||||
SrbInfo->ScatterGather = SrbInfo->ScatterGatherList;
|
||||
}
|
||||
|
||||
/* Use chosen SG list source */
|
||||
ScatterGatherList = SrbInfo->ScatterGather;
|
||||
|
||||
/* Save map registers base */
|
||||
SrbInfo->BaseOfMapRegister = MapRegisterBase;
|
||||
|
||||
/* Determine WriteToDevice flag */
|
||||
WriteToDevice = Srb->SrbFlags & SRB_FLAGS_DATA_OUT ? TRUE : FALSE;
|
||||
|
||||
/* Get virtual address of the data buffer */
|
||||
DataVA = (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress) +
|
||||
((PCHAR)Srb->DataBuffer - SrbInfo->DataOffset);
|
||||
|
||||
/* Build the actual SG list */
|
||||
while (TotalLength < Srb->DataTransferLength)
|
||||
{
|
||||
ScatterGatherList->Length = Srb->DataTransferLength - TotalLength;
|
||||
ScatterGatherList->PhysicalAddress = IoMapTransfer(NULL,
|
||||
Irp->MdlAddress,
|
||||
MapRegisterBase,
|
||||
DataVA + TotalLength,
|
||||
&ScatterGatherList->Length,
|
||||
WriteToDevice);
|
||||
|
||||
TotalLength += ScatterGatherList->Length;
|
||||
ScatterGatherList++;
|
||||
}
|
||||
|
||||
/* Schedule an active request */
|
||||
InterlockedIncrement(&DeviceExtension->ActiveRequestCounter );
|
||||
KeAcquireSpinLock(&DeviceExtension->SpinLock, &CurrentIrql);
|
||||
KeSynchronizeExecution(DeviceExtension->Interrupt,
|
||||
ScsiPortStartPacket,
|
||||
DeviceObject);
|
||||
KeReleaseSpinLock(&DeviceExtension->SpinLock, CurrentIrql);
|
||||
|
||||
return DeallocateObjectKeepRegisters;
|
||||
}
|
||||
|
||||
static PSCSI_PORT_LUN_EXTENSION
|
||||
SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
|
||||
{
|
||||
|
@ -3113,6 +3184,155 @@ SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static PSCSI_REQUEST_BLOCK_INFO
|
||||
SpiAllocateSrbStructures(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
|
||||
PSCSI_PORT_LUN_EXTENSION LunExtension,
|
||||
PSCSI_REQUEST_BLOCK Srb)
|
||||
{
|
||||
PCHAR SrbExtension;
|
||||
PSCSI_REQUEST_BLOCK_INFO SrbInfo;
|
||||
|
||||
/* Spinlock must be held while this function executes */
|
||||
KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
|
||||
|
||||
/* Allocate SRB data structure */
|
||||
if (DeviceExtension->NeedSrbDataAlloc)
|
||||
{
|
||||
/* Treat the abort request in a special way */
|
||||
if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
|
||||
{
|
||||
SrbInfo = SpiGetSrbData(DeviceExtension,
|
||||
Srb->PathId,
|
||||
Srb->TargetId,
|
||||
Srb->Lun,
|
||||
Srb->QueueTag);
|
||||
}
|
||||
else if (Srb->SrbFlags &
|
||||
(SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE) &&
|
||||
!(Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT)
|
||||
)
|
||||
{
|
||||
/* Do not process tagged commands if need request sense is set */
|
||||
if (LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE)
|
||||
{
|
||||
ASSERT(!(LunExtension->Flags & LUNEX_REQUEST_PENDING));
|
||||
|
||||
LunExtension->PendingRequest = Srb->OriginalRequest;
|
||||
LunExtension->Flags |= LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE;
|
||||
|
||||
/* Relese the spinlock and return */
|
||||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ASSERT(LunExtension->SrbInfo.Srb == NULL);
|
||||
SrbInfo = DeviceExtension->FreeSrbInfo;
|
||||
|
||||
if (SrbInfo == NULL)
|
||||
{
|
||||
/* No SRB structures left in the list. We have to leave
|
||||
and wait while we are called again */
|
||||
|
||||
DeviceExtension->Flags |= SCSI_PORT_REQUEST_PENDING;
|
||||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DeviceExtension->FreeSrbInfo = (PSCSI_REQUEST_BLOCK_INFO)SrbInfo->Requests.Flink;
|
||||
|
||||
/* QueueTag must never be 0, so +1 to it */
|
||||
Srb->QueueTag = (UCHAR)(SrbInfo - DeviceExtension->SrbInfo) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Usual untagged command */
|
||||
if (
|
||||
(!IsListEmpty(&LunExtension->SrbInfo.Requests) ||
|
||||
LunExtension->Flags & LUNEX_NEED_REQUEST_SENSE) &&
|
||||
!(Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
|
||||
)
|
||||
{
|
||||
/* Mark it as pending and leave */
|
||||
ASSERT(!(LunExtension->Flags & LUNEX_REQUEST_PENDING));
|
||||
LunExtension->Flags |= LUNEX_REQUEST_PENDING | SCSI_PORT_LU_ACTIVE;
|
||||
LunExtension->PendingRequest = Srb->OriginalRequest;
|
||||
|
||||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
Srb->QueueTag = SP_UNTAGGED;
|
||||
SrbInfo = &LunExtension->SrbInfo;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Srb->QueueTag = SP_UNTAGGED;
|
||||
SrbInfo = &LunExtension->SrbInfo;
|
||||
}
|
||||
|
||||
/* Allocate SRB extension structure */
|
||||
if (DeviceExtension->NeedSrbExtensionAlloc)
|
||||
{
|
||||
/* Check the list of free extensions */
|
||||
SrbExtension = DeviceExtension->FreeSrbExtensions;
|
||||
|
||||
/* If no free extensions... */
|
||||
if (SrbExtension == NULL)
|
||||
{
|
||||
/* Free SRB data */
|
||||
if (Srb->Function != SRB_FUNCTION_ABORT_COMMAND &&
|
||||
Srb->QueueTag != SP_UNTAGGED)
|
||||
{
|
||||
SrbInfo->Requests.Blink = NULL;
|
||||
SrbInfo->Requests.Flink = (PLIST_ENTRY)DeviceExtension->FreeSrbInfo;
|
||||
DeviceExtension->FreeSrbInfo = SrbInfo;
|
||||
}
|
||||
|
||||
/* Return, in order to be called again later */
|
||||
DeviceExtension->Flags |= SCSI_PORT_REQUEST_PENDING;
|
||||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remove that free SRB extension from the list (since
|
||||
we're going to use it) */
|
||||
DeviceExtension->FreeSrbExtensions = *((PVOID *)SrbExtension);
|
||||
|
||||
/* Spinlock can be released now */
|
||||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||
|
||||
Srb->SrbExtension = SrbExtension;
|
||||
|
||||
if (Srb->SenseInfoBuffer != NULL &&
|
||||
DeviceExtension->SupportsAutoSense)
|
||||
{
|
||||
/* Store pointer to the SenseInfo buffer */
|
||||
SrbInfo->SaveSenseRequest = Srb->SenseInfoBuffer;
|
||||
|
||||
/* Does data fit the buffer? */
|
||||
if (Srb->SenseInfoBufferLength > sizeof(SENSE_DATA))
|
||||
{
|
||||
/* No, disabling autosense at all */
|
||||
Srb->SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes, update the buffer pointer */
|
||||
Srb->SenseInfoBuffer = SrbExtension + DeviceExtension->SrbExtensionSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Cleanup... */
|
||||
Srb->SrbExtension = NULL;
|
||||
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
|
||||
}
|
||||
|
||||
return SrbInfo;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
/* Defines how many logical unit arrays will be in a device extension */
|
||||
#define LUS_NUMBER 8
|
||||
|
||||
#define MAX_SG_LIST 17
|
||||
|
||||
/* Flags */
|
||||
#define SCSI_PORT_DEVICE_BUSY 0x0001
|
||||
#define SCSI_PORT_LU_ACTIVE 0x0002
|
||||
|
@ -85,6 +87,12 @@ typedef struct _SCSI_PORT_DEVICE_BASE
|
|||
ULONG SystemIoBusNumber;
|
||||
} SCSI_PORT_DEVICE_BASE, *PSCSI_PORT_DEVICE_BASE;
|
||||
|
||||
typedef struct _SCSI_SG_ADDRESS
|
||||
{
|
||||
PHYSICAL_ADDRESS PhysicalAddress;
|
||||
ULONG Length;
|
||||
} SCSI_SG_ADDRESS, *PSCSI_SG_ADDRESS;
|
||||
|
||||
typedef struct _SCSI_REQUEST_BLOCK_INFO
|
||||
{
|
||||
LIST_ENTRY Requests;
|
||||
|
@ -99,6 +107,10 @@ typedef struct _SCSI_REQUEST_BLOCK_INFO
|
|||
ULONG NumberOfMapRegisters;
|
||||
|
||||
struct _SCSI_REQUEST_BLOCK_INFO *CompletedRequests;
|
||||
|
||||
/* Scatter-gather list */
|
||||
PSCSI_SG_ADDRESS ScatterGather;
|
||||
SCSI_SG_ADDRESS ScatterGatherList[MAX_SG_LIST];
|
||||
} SCSI_REQUEST_BLOCK_INFO, *PSCSI_REQUEST_BLOCK_INFO;
|
||||
|
||||
typedef struct _SCSI_PORT_LUN_EXTENSION
|
||||
|
|
Loading…
Reference in a new issue