diff --git a/drivers/storage/port/storport/fdo.c b/drivers/storage/port/storport/fdo.c index 92a5a7f9a1b..e20fd68bcc2 100644 --- a/drivers/storage/port/storport/fdo.c +++ b/drivers/storage/port/storport/fdo.c @@ -243,6 +243,289 @@ PortFdoStartDevice( } +static NTSTATUS +SpiSendInquiry(IN PDEVICE_OBJECT DeviceObject, + ULONG Bus, ULONG Target, ULONG Lun) +{ +// IO_STATUS_BLOCK IoStatusBlock; +// PIO_STACK_LOCATION IrpStack; +// KEVENT Event; +// KIRQL Irql; +// PIRP Irp; + NTSTATUS Status; + PINQUIRYDATA InquiryBuffer; + PUCHAR /*PSENSE_DATA*/ SenseBuffer; +// BOOLEAN KeepTrying = TRUE; +// ULONG RetryCount = 0; + SCSI_REQUEST_BLOCK Srb; + PCDB Cdb; +// PSCSI_PORT_LUN_EXTENSION LunExtension; +// PSCSI_PORT_DEVICE_EXTENSION DeviceExtension; + +PFDO_DEVICE_EXTENSION DeviceExtension; + PVOID SrbExtension = NULL; + BOOLEAN ret; + + DPRINT1("SpiSendInquiry() called\n"); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + InquiryBuffer = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, TAG_INQUIRY_DATA); + if (InquiryBuffer == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + SenseBuffer = ExAllocatePoolWithTag(NonPagedPool, SENSE_BUFFER_SIZE, TAG_SENSE_DATA); + if (SenseBuffer == NULL) + { + ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA); + return STATUS_INSUFFICIENT_RESOURCES; + } + + if (DeviceExtension->Miniport.PortConfig.SrbExtensionSize != 0) + { + SrbExtension = ExAllocatePoolWithTag(NonPagedPool, DeviceExtension->Miniport.PortConfig.SrbExtensionSize, TAG_SENSE_DATA); + if (SrbExtension == NULL) + { + ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA); + ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA); + return STATUS_INSUFFICIENT_RESOURCES; + } + } + +// while (KeepTrying) + { + /* Initialize event for waiting */ +// KeInitializeEvent(&Event, +// NotificationEvent, +// FALSE); + + /* Create an IRP */ +// Irp = IoBuildDeviceIoControlRequest(IOCTL_SCSI_EXECUTE_IN, +// DeviceObject, +// NULL, +// 0, +// InquiryBuffer, +// INQUIRYDATABUFFERSIZE, +// TRUE, +// &Event, +// &IoStatusBlock); +// if (Irp == NULL) +// { +// DPRINT1("IoBuildDeviceIoControlRequest() failed\n"); + + /* Quit the loop */ +// Status = STATUS_INSUFFICIENT_RESOURCES; +// KeepTrying = FALSE; +// continue; +// } + + /* Prepare SRB */ + RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK)); + + Srb.Length = sizeof(SCSI_REQUEST_BLOCK); +// Srb.OriginalRequest = Irp; + Srb.PathId = Bus; + Srb.TargetId = Target; + Srb.Lun = Lun; + Srb.Function = SRB_FUNCTION_EXECUTE_SCSI; + Srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; + Srb.TimeOutValue = 4; + Srb.CdbLength = 6; + + Srb.SenseInfoBuffer = SenseBuffer; + Srb.SenseInfoBufferLength = SENSE_BUFFER_SIZE; + + Srb.DataBuffer = InquiryBuffer; + Srb.DataTransferLength = INQUIRYDATABUFFERSIZE; + + Srb.SrbExtension = SrbExtension; + + /* Attach Srb to the Irp */ +// IrpStack = IoGetNextIrpStackLocation(Irp); +// IrpStack->Parameters.Scsi.Srb = &Srb; + + /* Fill in CDB */ + Cdb = (PCDB)Srb.Cdb; + Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY; + Cdb->CDB6INQUIRY.LogicalUnitNumber = Lun; + Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE; + + /* Call the driver */ + + + ret = MiniportStartIo(&DeviceExtension->Miniport, + &Srb); +DPRINT1("MiniportStartIo returned %u\n", ret); + +// Status = IoCallDriver(DeviceObject, Irp); + + /* Wait for it to complete */ +// if (Status == STATUS_PENDING) +// { +// DPRINT1("SpiSendInquiry(): Waiting for the driver to process request...\n"); +// KeWaitForSingleObject(&Event, +// Executive, +// KernelMode, +// FALSE, +// NULL); +// Status = IoStatusBlock.Status; +// } + +// DPRINT1("SpiSendInquiry(): Request processed by driver, status = 0x%08X\n", Status); + + if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_SUCCESS) + { + /* All fine, copy data over */ +// RtlCopyMemory(LunInfo->InquiryData, +// InquiryBuffer, +// INQUIRYDATABUFFERSIZE); + + /* Quit the loop */ + Status = STATUS_SUCCESS; +// KeepTrying = FALSE; +// continue; + } + + DPRINT("Inquiry SRB failed with SrbStatus 0x%08X\n", Srb.SrbStatus); +#if 0 + /* Check if the queue is frozen */ + if (Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN) + { + /* Something weird happened, deal with it (unfreeze the queue) */ + KeepTrying = FALSE; + + DPRINT("SpiSendInquiry(): the queue is frozen at TargetId %d\n", Srb.TargetId); + + LunExtension = SpiGetLunExtension(DeviceExtension, + LunInfo->PathId, + LunInfo->TargetId, + LunInfo->Lun); + + /* Clear frozen flag */ + LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE; + + /* Acquire the spinlock */ + KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql); + + /* Process the request */ + SpiGetNextRequestFromLun(DeviceObject->DeviceExtension, LunExtension); + + /* SpiGetNextRequestFromLun() releases the spinlock, + so we just lower irql back to what it was before */ + KeLowerIrql(Irql); + } + + /* Check if data overrun happened */ + if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) + { + DPRINT("Data overrun at TargetId %d\n", LunInfo->TargetId); + + /* Nothing dramatic, just copy data, but limiting the size */ + RtlCopyMemory(LunInfo->InquiryData, + InquiryBuffer, + (Srb.DataTransferLength > INQUIRYDATABUFFERSIZE) ? + INQUIRYDATABUFFERSIZE : Srb.DataTransferLength); + + /* Quit the loop */ + Status = STATUS_SUCCESS; + KeepTrying = FALSE; + } + else if ((Srb.SrbStatus & SRB_STATUS_AUTOSENSE_VALID) && + SenseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) + { + /* LUN is not valid, but some device responds there. + Mark it as invalid anyway */ + + /* Quit the loop */ + Status = STATUS_INVALID_DEVICE_REQUEST; + KeepTrying = FALSE; + } + else + { + /* Retry a couple of times if no timeout happened */ + if ((RetryCount < 2) && + (SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_NO_DEVICE) && + (SRB_STATUS(Srb.SrbStatus) != SRB_STATUS_SELECTION_TIMEOUT)) + { + RetryCount++; + KeepTrying = TRUE; + } + else + { + /* That's all, quit the loop */ + KeepTrying = FALSE; + + /* Set status according to SRB status */ + if (SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_FUNCTION || + SRB_STATUS(Srb.SrbStatus) == SRB_STATUS_BAD_SRB_BLOCK_LENGTH) + { + Status = STATUS_INVALID_DEVICE_REQUEST; + } + else + { + Status = STATUS_IO_DEVICE_ERROR; + } + } + } +#endif + } + + /* Free buffers */ + if (SrbExtension != NULL) + ExFreePoolWithTag(SrbExtension, TAG_SENSE_DATA); + + ExFreePoolWithTag(SenseBuffer, TAG_SENSE_DATA); + ExFreePoolWithTag(InquiryBuffer, TAG_INQUIRY_DATA); + + DPRINT("SpiSendInquiry() done with Status 0x%08X\n", Status); + + return Status; +} + + +static +NTSTATUS +PortFdoScanBus( + _In_ PFDO_DEVICE_EXTENSION DeviceExtension) +{ + ULONG Bus, Target, Lun; + NTSTATUS Status; + + + DPRINT1("PortFdoScanBus(%p)\n", + DeviceExtension); + + DPRINT1("NumberOfBuses: %lu\n", DeviceExtension->Miniport.PortConfig.NumberOfBuses); + DPRINT1("MaximumNumberOfTargets: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets); + DPRINT1("MaximumNumberOfLogicalUnits: %lu\n", DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits); + + /* Scan all buses */ + for (Bus = 0; Bus < DeviceExtension->Miniport.PortConfig.NumberOfBuses; Bus++) + { + DPRINT1("Scanning bus %ld\n", Bus); + + /* Scan all targets */ + for (Target = 0; Target < DeviceExtension->Miniport.PortConfig.MaximumNumberOfTargets; Target++) + { + DPRINT1(" Scanning target %ld:%ld\n", Bus, Target); + + /* Scan all logical units */ + for (Lun = 0; Lun < DeviceExtension->Miniport.PortConfig.MaximumNumberOfLogicalUnits; Lun++) + { + DPRINT1(" Scanning logical unit %ld:%ld:%ld\n", Bus, Target, Lun); + + Status = SpiSendInquiry(DeviceExtension->Device, Bus, Target, Lun); + DPRINT1("SpiSendInquiry returned 0x%08lx\n", Status); + } + } + } + + DPRINT1("Done!\n"); + + return STATUS_SUCCESS; +} + + static NTSTATUS PortFdoQueryBusRelations( @@ -254,6 +537,8 @@ PortFdoQueryBusRelations( DPRINT1("PortFdoQueryBusRelations(%p %p)\n", DeviceExtension, Information); + Status = PortFdoScanBus(DeviceExtension); + *Information = 0; return Status; @@ -282,6 +567,35 @@ PortFdoFilterRequirements( } +NTSTATUS +NTAPI +PortFdoScsi( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PIRP Irp) +{ + PFDO_DEVICE_EXTENSION DeviceExtension; +// PIO_STACK_LOCATION Stack; + ULONG_PTR Information = 0; + NTSTATUS Status = STATUS_NOT_SUPPORTED; + + DPRINT1("PortFdoScsi(%p %p)\n", + DeviceObject, Irp); + + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + ASSERT(DeviceExtension); + ASSERT(DeviceExtension->ExtensionType == FdoExtension); + +// Stack = IoGetCurrentIrpStackLocation(Irp); + + + Irp->IoStatus.Information = Information; + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; +} + + NTSTATUS NTAPI PortFdoPnp( diff --git a/drivers/storage/port/storport/miniport.c b/drivers/storage/port/storport/miniport.c index 815e6090315..e1aedcbfa52 100644 --- a/drivers/storage/port/storport/miniport.c +++ b/drivers/storage/port/storport/miniport.c @@ -362,4 +362,21 @@ MiniportHwInterrupt( return Result; } + +BOOLEAN +MiniportStartIo( + _In_ PMINIPORT Miniport, + _In_ PSCSI_REQUEST_BLOCK Srb) +{ + BOOLEAN Result; + + DPRINT1("MiniportHwStartIo(%p %p)\n", + Miniport, Srb); + + Result = Miniport->InitData->HwStartIo(&Miniport->MiniportExtension->HwDeviceExtension, Srb); + DPRINT1("HwStartIo() returned %u\n", Result); + + return Result; +} + /* EOF */ diff --git a/drivers/storage/port/storport/misc.c b/drivers/storage/port/storport/misc.c index f74fd3516fa..1c9c73ae661 100644 --- a/drivers/storage/port/storport/misc.c +++ b/drivers/storage/port/storport/misc.c @@ -370,17 +370,4 @@ AllocateAddressMapping( return STATUS_SUCCESS; } -#if defined(_M_AMD64) -/* KeQuerySystemTime is an inline function, - so we cannot forward the export to ntoskrnl */ -STORPORT_API -VOID -NTAPI -StorPortQuerySystemTime( - _Out_ PLARGE_INTEGER CurrentTime) -{ - KeQuerySystemTime(CurrentTime); -} -#endif /* defined(_M_AMD64) */ - /* EOF */ diff --git a/drivers/storage/port/storport/pdo.c b/drivers/storage/port/storport/pdo.c index fb7280ccc01..8df3151e346 100644 --- a/drivers/storage/port/storport/pdo.c +++ b/drivers/storage/port/storport/pdo.c @@ -15,6 +15,21 @@ /* FUNCTIONS ******************************************************************/ +NTSTATUS +NTAPI +PortPdoScsi( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PIRP Irp) +{ + DPRINT1("PortPdoScsi()\n"); + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + + NTSTATUS NTAPI PortPdoPnp( diff --git a/drivers/storage/port/storport/precomp.h b/drivers/storage/port/storport/precomp.h index 5bd16f338f7..84925ef1bc6 100644 --- a/drivers/storage/port/storport/precomp.h +++ b/drivers/storage/port/storport/precomp.h @@ -29,6 +29,8 @@ #define TAG_ACCRESS_RANGE 'RAtS' #define TAG_RESOURCE_LIST 'LRtS' #define TAG_ADDRESS_MAPPING 'MAtS' +#define TAG_INQUIRY_DATA 'QItS' +#define TAG_SENSE_DATA 'NStS' typedef enum { @@ -119,6 +121,12 @@ typedef struct _PDO_DEVICE_EXTENSION /* fdo.c */ +NTSTATUS +NTAPI +PortFdoScsi( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PIRP Irp); + NTSTATUS NTAPI PortFdoPnp( @@ -146,6 +154,11 @@ BOOLEAN MiniportHwInterrupt( _In_ PMINIPORT Miniport); +BOOLEAN +MiniportStartIo( + _In_ PMINIPORT Miniport, + _In_ PSCSI_REQUEST_BLOCK Srb); + /* misc.c */ NTSTATUS @@ -206,6 +219,12 @@ AllocateAddressMapping( /* pdo.c */ +NTSTATUS +NTAPI +PortPdoScsi( + _In_ PDEVICE_OBJECT DeviceObject, + _In_ PIRP Irp); + NTSTATUS NTAPI PortPdoPnp( diff --git a/drivers/storage/port/storport/storport.c b/drivers/storage/port/storport/storport.c index a9fd3d07f8e..03ec5639491 100644 --- a/drivers/storage/port/storport/storport.c +++ b/drivers/storage/port/storport/storport.c @@ -100,6 +100,69 @@ PortGetDriverInitData( } +static +VOID +PortAcquireSpinLock( + PFDO_DEVICE_EXTENSION DeviceExtension, + STOR_SPINLOCK SpinLock, + PVOID LockContext, + PSTOR_LOCK_HANDLE LockHandle) +{ + DPRINT1("PortAcquireSpinLock(%p %lu %p %p)\n", + DeviceExtension, SpinLock, LockContext, LockHandle); + + LockHandle->Lock = SpinLock; + + switch (SpinLock) + { + case DpcLock: /* 1, */ + DPRINT1("DpcLock\n"); + break; + + case StartIoLock: /* 2 */ + DPRINT1("StartIoLock\n"); + break; + + case InterruptLock: /* 3 */ + DPRINT1("InterruptLock\n"); + if (DeviceExtension->Interrupt == NULL) + LockHandle->Context.OldIrql = 0; + else + LockHandle->Context.OldIrql = KeAcquireInterruptSpinLock(DeviceExtension->Interrupt); + break; + } +} + + +static +VOID +PortReleaseSpinLock( + PFDO_DEVICE_EXTENSION DeviceExtension, + PSTOR_LOCK_HANDLE LockHandle) +{ + DPRINT1("PortReleaseSpinLock(%p %p)\n", + DeviceExtension, LockHandle); + + switch (LockHandle->Lock) + { + case DpcLock: /* 1, */ + DPRINT1("DpcLock\n"); + break; + + case StartIoLock: /* 2 */ + DPRINT1("StartIoLock\n"); + break; + + case InterruptLock: /* 3 */ + DPRINT1("InterruptLock\n"); + if (DeviceExtension->Interrupt != NULL) + KeReleaseInterruptSpinLock(DeviceExtension->Interrupt, + LockHandle->Context.OldIrql); + break; + } +} + + static NTSTATUS NTAPI @@ -280,13 +343,30 @@ PortDispatchScsi( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + PFDO_DEVICE_EXTENSION DeviceExtension; + DPRINT1("PortDispatchScsi(%p %p)\n", DeviceObject, Irp); - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; + DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + DPRINT1("ExtensionType: %u\n", DeviceExtension->ExtensionType); - IoCompleteRequest(Irp, IO_NO_INCREMENT); + switch (DeviceExtension->ExtensionType) + { + case FdoExtension: + return PortFdoScsi(DeviceObject, + Irp); + + case PdoExtension: + return PortPdoScsi(DeviceObject, + Irp); + + default: + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_UNSUCCESSFUL; + } return STATUS_SUCCESS; } @@ -742,10 +822,13 @@ StorPortGetPhysicalAddress( // FIXME - UNIMPLEMENTED; - *Length = 0; - PhysicalAddress.QuadPart = (LONGLONG)0; + PhysicalAddress = MmGetPhysicalAddress(VirtualAddress); + *Length = 1; +// UNIMPLEMENTED; + +// *Length = 0; +// PhysicalAddress.QuadPart = (LONGLONG)0; return PhysicalAddress; } @@ -1012,11 +1095,16 @@ StorPortNotification( PMINIPORT_DEVICE_EXTENSION MiniportExtension = NULL; PFDO_DEVICE_EXTENSION DeviceExtension = NULL; PHW_PASSIVE_INITIALIZE_ROUTINE HwPassiveInitRoutine; + PSTORPORT_EXTENDED_FUNCTIONS *ppExtendedFunctions; PBOOLEAN Result; PSTOR_DPC Dpc; PHW_DPC_ROUTINE HwDpcRoutine; va_list ap; + STOR_SPINLOCK SpinLock; + PVOID LockContext; + PSTOR_LOCK_HANDLE LockHandle; + DPRINT1("StorPortNotification(%x %p)\n", NotificationType, HwDeviceExtension); @@ -1036,6 +1124,13 @@ StorPortNotification( switch (NotificationType) { + case GetExtendedFunctionTable: + DPRINT1("GetExtendedFunctionTable\n"); + ppExtendedFunctions = (PSTORPORT_EXTENDED_FUNCTIONS*)va_arg(ap, PSTORPORT_EXTENDED_FUNCTIONS*); + if (ppExtendedFunctions != NULL) + *ppExtendedFunctions = NULL; /* FIXME */ + break; + case EnablePassiveInitialization: DPRINT1("EnablePassiveInitialization\n"); HwPassiveInitRoutine = (PHW_PASSIVE_INITIALIZE_ROUTINE)va_arg(ap, PHW_PASSIVE_INITIALIZE_ROUTINE); @@ -1065,6 +1160,28 @@ StorPortNotification( KeInitializeSpinLock(&Dpc->Lock); break; + case AcquireSpinLock: + DPRINT1("AcquireSpinLock\n"); + SpinLock = (STOR_SPINLOCK)va_arg(ap, STOR_SPINLOCK); + DPRINT1("SpinLock %lu\n", SpinLock); + LockContext = (PVOID)va_arg(ap, PVOID); + DPRINT1("LockContext %p\n", LockContext); + LockHandle = (PSTOR_LOCK_HANDLE)va_arg(ap, PSTOR_LOCK_HANDLE); + DPRINT1("LockHandle %p\n", LockHandle); + PortAcquireSpinLock(DeviceExtension, + SpinLock, + LockContext, + LockHandle); + break; + + case ReleaseSpinLock: + DPRINT1("ReleaseSpinLock\n"); + LockHandle = (PSTOR_LOCK_HANDLE)va_arg(ap, PSTOR_LOCK_HANDLE); + DPRINT1("LockHandle %p\n", LockHandle); + PortReleaseSpinLock(DeviceExtension, + LockHandle); + break; + default: DPRINT1("Unsupported Notification %lx\n", NotificationType); break; @@ -1109,6 +1226,25 @@ StorPortPauseDevice( } +#if defined(_M_AMD64) +/* + * @implemented + */ +/* KeQuerySystemTime is an inline function, + so we cannot forward the export to ntoskrnl */ +STORPORT_API +VOID +NTAPI +StorPortQuerySystemTime( + _Out_ PLARGE_INTEGER CurrentTime) +{ + DPRINT1("StorPortQuerySystemTime(%p)\n", CurrentTime); + + KeQuerySystemTime(CurrentTime); +} +#endif /* defined(_M_AMD64) */ + + /* * @unimplemented */ diff --git a/drivers/storage/port/storport/storport.spec b/drivers/storage/port/storport/storport.spec index 310e201f9eb..a36e5ed49a8 100644 --- a/drivers/storage/port/storport/storport.spec +++ b/drivers/storage/port/storport/storport.spec @@ -24,10 +24,10 @@ @ stdcall StorPortLogError(ptr ptr long long long long long) @ stdcall StorPortMoveMemory(ptr ptr long) @ cdecl StorPortNotification() -@ stdcall -arch=i386 StorPortQuerySystemTime(ptr) NTOSKRNL.KeQuerySystemTime -@ stdcall -arch=amd64 StorPortQuerySystemTime(ptr) @ stdcall StorPortPause(ptr long) @ stdcall StorPortPauseDevice(ptr long long long long) +@ stdcall -arch=i386 StorPortQuerySystemTime(ptr) NTOSKRNL.KeQuerySystemTime +@ stdcall -arch=amd64 StorPortQuerySystemTime(ptr) @ stdcall StorPortReadPortBufferUchar(ptr ptr ptr long) @ stdcall StorPortReadPortBufferUlong(ptr ptr ptr long) @ stdcall StorPortReadPortBufferUshort(ptr ptr ptr long) diff --git a/sdk/include/ddk/storport.h b/sdk/include/ddk/storport.h index 64a6e1059d8..44d5d96d274 100644 --- a/sdk/include/ddk/storport.h +++ b/sdk/include/ddk/storport.h @@ -57,7 +57,14 @@ extern "C" { #define CDB10GENERIC_LENGTH 10 #define CDB12GENERIC_LENGTH 12 -#define INQUIRYDATABUFFERSIZE 36 +#define INQUIRYDATABUFFERSIZE 36 +#define SENSE_BUFFER_SIZE 18 +#define MAX_SENSE_BUFFER_SIZE 255 + +#define FILE_DEVICE_SCSI 0x0000001b +#define IOCTL_SCSI_EXECUTE_IN ((FILE_DEVICE_SCSI << 16) + 0x0011) +#define IOCTL_SCSI_EXECUTE_OUT ((FILE_DEVICE_SCSI << 16) + 0x0012) +#define IOCTL_SCSI_EXECUTE_NONE ((FILE_DEVICE_SCSI << 16) + 0x0013) #define MODE_PAGE_VENDOR_SPECIFIC 0x00 #define MODE_PAGE_ERROR_RECOVERY 0x01 @@ -563,6 +570,12 @@ typedef enum _STOR_EVENT_ASSOCIATION_ENUM StorEventInvalidAssociation } STOR_EVENT_ASSOCIATION_ENUM; +typedef enum _GETSGSTATUS +{ + SG_ALLOCATED = 0, + SG_BUFFER_TOO_SMALL +} GETSGSTATUS, *PGETSGSTATUS; + typedef struct _SCSI_REQUEST_BLOCK { USHORT Length; @@ -2182,6 +2195,64 @@ VOID _In_ PSTOR_SCATTER_GATHER_LIST ScatterGather, _In_ PVOID Context); +typedef +BOOLEAN +(NTAPI *PStorPortGetMessageInterruptInformation)( + _In_ PVOID HwDeviceExtension, + _In_ ULONG MessageId, + _Out_ PMESSAGE_INTERRUPT_INFORMATION InterruptInfo); + +typedef +VOID +(NTAPI *PStorPortPutScatterGatherList)( + _In_ PVOID HwDeviceExtension, + _In_ PSTOR_SCATTER_GATHER_LIST ScatterGatherList, + _In_ BOOLEAN WriteToDevice); + +typedef +GETSGSTATUS +(NTAPI *PStorPortBuildScatterGatherList)( + _In_ PVOID HwDeviceExtension, + _In_ PVOID Mdl, + _In_ PVOID CurrentVa, + _In_ ULONG Length, + _In_ PpostScaterGatherExecute ExecutionRoutine, + _In_ PVOID Context, + _In_ BOOLEAN WriteToDevice, + _Inout_ PVOID ScatterGatherBuffer, + _In_ ULONG ScatterGatherBufferLength); + +typedef +VOID +(NTAPI *PStorPortFreePool)( + _In_ PVOID PMemory, + _In_ PVOID HwDeviceExtension, + _In_opt_ PVOID PMdl); + +typedef +PVOID +(NTAPI *PStorPortAllocatePool)( + _In_ ULONG NumberOfBytes, + _In_ ULONG Tag, + _In_ PVOID HwDeviceExtension, + _Out_ PVOID *PMdl); + +typedef +PVOID +(NTAPI *PStorPortGetSystemAddress)( + _In_ PSCSI_REQUEST_BLOCK Srb); + +typedef struct _STORPORT_EXTENDED_FUNCTIONS +{ + ULONG Version; + PStorPortGetMessageInterruptInformation GetMessageInterruptInformation; + PStorPortPutScatterGatherList PutScatterGatherList; + PStorPortBuildScatterGatherList BuildScatterGatherList; + PStorPortFreePool FreePool; + PStorPortAllocatePool AllocatePool; + PStorPortGetSystemAddress GetSystemAddress; +} STORPORT_EXTENDED_FUNCTIONS, *PSTORPORT_EXTENDED_FUNCTIONS; + typedef struct _HW_INITIALIZATION_DATA { ULONG HwInitializationDataSize;