reactos/drivers/storage/port/storport/storport.c
2021-06-11 15:33:08 +03:00

1459 lines
36 KiB
C

/*
* PROJECT: ReactOS Storport Driver
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Storport driver main file
* COPYRIGHT: Copyright 2017 Eric Kohl (eric.kohl@reactos.org)
*/
/* INCLUDES *******************************************************************/
#include "precomp.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
ULONG PortNumber = 0;
/* FUNCTIONS ******************************************************************/
static
NTSTATUS
PortAddDriverInitData(
PDRIVER_OBJECT_EXTENSION DriverExtension,
PHW_INITIALIZATION_DATA HwInitializationData)
{
PDRIVER_INIT_DATA InitData;
DPRINT1("PortAddDriverInitData()\n");
InitData = ExAllocatePoolWithTag(NonPagedPool,
sizeof(DRIVER_INIT_DATA),
TAG_INIT_DATA);
if (InitData == NULL)
return STATUS_NO_MEMORY;
RtlCopyMemory(&InitData->HwInitData,
HwInitializationData,
sizeof(HW_INITIALIZATION_DATA));
InsertHeadList(&DriverExtension->InitDataListHead,
&InitData->Entry);
return STATUS_SUCCESS;
}
static
VOID
PortDeleteDriverInitData(
PDRIVER_OBJECT_EXTENSION DriverExtension)
{
PDRIVER_INIT_DATA InitData;
PLIST_ENTRY ListEntry;
DPRINT1("PortDeleteDriverInitData()\n");
ListEntry = DriverExtension->InitDataListHead.Flink;
while (ListEntry != &DriverExtension->InitDataListHead)
{
InitData = CONTAINING_RECORD(ListEntry,
DRIVER_INIT_DATA,
Entry);
RemoveEntryList(&InitData->Entry);
ExFreePoolWithTag(InitData,
TAG_INIT_DATA);
ListEntry = DriverExtension->InitDataListHead.Flink;
}
}
PHW_INITIALIZATION_DATA
PortGetDriverInitData(
PDRIVER_OBJECT_EXTENSION DriverExtension,
INTERFACE_TYPE InterfaceType)
{
PDRIVER_INIT_DATA InitData;
PLIST_ENTRY ListEntry;
DPRINT1("PortGetDriverInitData()\n");
ListEntry = DriverExtension->InitDataListHead.Flink;
while (ListEntry != &DriverExtension->InitDataListHead)
{
InitData = CONTAINING_RECORD(ListEntry,
DRIVER_INIT_DATA,
Entry);
if (InitData->HwInitData.AdapterInterfaceType == InterfaceType)
return &InitData->HwInitData;
ListEntry = ListEntry->Flink;
}
return NULL;
}
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
PortAddDevice(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PDEVICE_OBJECT PhysicalDeviceObject)
{
PDRIVER_OBJECT_EXTENSION DriverObjectExtension;
PFDO_DEVICE_EXTENSION DeviceExtension = NULL;
WCHAR NameBuffer[80];
UNICODE_STRING DeviceName;
PDEVICE_OBJECT Fdo = NULL;
KLOCK_QUEUE_HANDLE LockHandle;
NTSTATUS Status;
DPRINT1("PortAddDevice(%p %p)\n",
DriverObject, PhysicalDeviceObject);
ASSERT(DriverObject);
ASSERT(PhysicalDeviceObject);
swprintf(NameBuffer,
L"\\Device\\RaidPort%lu",
PortNumber);
RtlInitUnicodeString(&DeviceName, NameBuffer);
PortNumber++;
DPRINT1("Creating device: %wZ\n", &DeviceName);
/* Create the port device */
Status = IoCreateDevice(DriverObject,
sizeof(FDO_DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_CONTROLLER,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&Fdo);
if (!NT_SUCCESS(Status))
{
DPRINT1("IoCreateDevice() failed (Status 0x%08lx)\n", Status);
return Status;
}
DPRINT1("Created device: %wZ (%p)\n", &DeviceName, Fdo);
/* Initialize the device */
Fdo->Flags |= DO_DIRECT_IO;
Fdo->Flags |= DO_POWER_PAGABLE;
/* Initialize the device extension */
DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
DeviceExtension->ExtensionType = FdoExtension;
DeviceExtension->Device = Fdo;
DeviceExtension->PhysicalDevice = PhysicalDeviceObject;
DeviceExtension->PnpState = dsStopped;
KeInitializeSpinLock(&DeviceExtension->PdoListLock);
InitializeListHead(&DeviceExtension->PdoListHead);
/* Attach the FDO to the device stack */
Status = IoAttachDeviceToDeviceStackSafe(Fdo,
PhysicalDeviceObject,
&DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status))
{
DPRINT1("IoAttachDeviceToDeviceStackSafe() failed (Status 0x%08lx)\n", Status);
IoDeleteDevice(Fdo);
return Status;
}
/* Insert the FDO to the drivers FDO list */
DriverObjectExtension = IoGetDriverObjectExtension(DriverObject,
(PVOID)DriverEntry);
ASSERT(DriverObjectExtension->ExtensionType == DriverExtension);
DeviceExtension->DriverExtension = DriverObjectExtension;
KeAcquireInStackQueuedSpinLock(&DriverObjectExtension->AdapterListLock,
&LockHandle);
InsertHeadList(&DriverObjectExtension->AdapterListHead,
&DeviceExtension->AdapterListEntry);
DriverObjectExtension->AdapterCount++;
KeReleaseInStackQueuedSpinLock(&LockHandle);
/* The device has been initialized */
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
DPRINT1("PortAddDevice() done (Status 0x%08lx)\n", Status);
return Status;
}
static
VOID
NTAPI
PortUnload(
_In_ PDRIVER_OBJECT DriverObject)
{
PDRIVER_OBJECT_EXTENSION DriverExtension;
DPRINT1("PortUnload(%p)\n",
DriverObject);
DriverExtension = IoGetDriverObjectExtension(DriverObject,
(PVOID)DriverEntry);
if (DriverExtension != NULL)
{
PortDeleteDriverInitData(DriverExtension);
}
}
static
NTSTATUS
NTAPI
PortDispatchCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT1("PortDispatchCreate(%p %p)\n",
DeviceObject, Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
PortDispatchClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT1("PortDispatchClose(%p %p)\n",
DeviceObject, Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
PortDispatchDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT1("PortDispatchDeviceControl(%p %p)\n",
DeviceObject, Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
PortDispatchScsi(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
DPRINT1("PortDispatchScsi(%p %p)\n",
DeviceObject, Irp);
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DPRINT1("ExtensionType: %u\n", DeviceExtension->ExtensionType);
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;
}
static
NTSTATUS
NTAPI
PortDispatchSystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT1("PortDispatchSystemControl(%p %p)\n",
DeviceObject, Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
static
NTSTATUS
NTAPI
PortDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
DPRINT1("PortDispatchPnp(%p %p)\n",
DeviceObject, Irp);
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DPRINT1("ExtensionType: %u\n", DeviceExtension->ExtensionType);
switch (DeviceExtension->ExtensionType)
{
case FdoExtension:
return PortFdoPnp(DeviceObject,
Irp);
case PdoExtension:
return PortPdoPnp(DeviceObject,
Irp);
default:
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
}
static
NTSTATUS
NTAPI
PortDispatchPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT1("PortDispatchPower(%p %p)\n",
DeviceObject, Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/* PUBLIC FUNCTIONS ***********************************************************/
/*
* @implemented
*/
NTSTATUS
NTAPI
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath)
{
DPRINT1("DriverEntry(%p %p)\n", DriverObject, RegistryPath);
return STATUS_SUCCESS;
}
/*
* @unimplemented
*/
STORPORT_API
PUCHAR
NTAPI
StorPortAllocateRegistryBuffer(
_In_ PVOID HwDeviceExtension,
_In_ PULONG Length)
{
DPRINT1("StorPortAllocateRegistryBuffer()\n");
UNIMPLEMENTED;
return NULL;
}
/*
* @unimplemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortBusy(
_In_ PVOID HwDeviceExtension,
_In_ ULONG RequestsToComplete)
{
DPRINT1("StorPortBuzy()\n");
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
STORPORT_API
VOID
NTAPI
StorPortCompleteRequest(
_In_ PVOID HwDeviceExtension,
_In_ UCHAR PathId,
_In_ UCHAR TargetId,
_In_ UCHAR Lun,
_In_ UCHAR SrbStatus)
{
DPRINT1("StorPortCompleteRequest()\n");
UNIMPLEMENTED;
}
/*
* @implemented
*/
STORPORT_API
ULONG
NTAPI
StorPortConvertPhysicalAddressToUlong(
_In_ STOR_PHYSICAL_ADDRESS Address)
{
DPRINT1("StorPortConvertPhysicalAddressToUlong()\n");
return Address.u.LowPart;
}
/*
* @implemented
*/
STORPORT_API
STOR_PHYSICAL_ADDRESS
NTAPI
StorPortConvertUlongToPhysicalAddress(
_In_ ULONG_PTR UlongAddress)
{
STOR_PHYSICAL_ADDRESS Address;
DPRINT1("StorPortConvertUlongToPhysicalAddress()\n");
Address.QuadPart = UlongAddress;
return Address;
}
/*
* @implemented
*/
STORPORT_API
VOID
StorPortDebugPrint(
_In_ ULONG DebugPrintLevel,
_In_ PCHAR DebugMessage,
...)
{
va_list ap;
va_start(ap, DebugMessage);
vDbgPrintExWithPrefix("STORMINI: ", 0x58, DebugPrintLevel, DebugMessage, ap);
va_end(ap);
}
/*
* @unimplemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortDeviceBusy(
_In_ PVOID HwDeviceExtension,
_In_ UCHAR PathId,
_In_ UCHAR TargetId,
_In_ UCHAR Lun,
_In_ ULONG RequestsToComplete)
{
DPRINT1("StorPortDeviceBusy()\n");
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortDeviceReady(
_In_ PVOID HwDeviceExtension,
_In_ UCHAR PathId,
_In_ UCHAR TargetId,
_In_ UCHAR Lun)
{
DPRINT1("StorPortDeviceReady()\n");
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
STORPORT_API
ULONG
StorPortExtendedFunction(
_In_ STORPORT_FUNCTION_CODE FunctionCode,
_In_ PVOID HwDeviceExtension,
...)
{
DPRINT1("StorPortExtendedFunction(%d %p ...)\n",
FunctionCode, HwDeviceExtension);
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @implemented
*/
STORPORT_API
VOID
NTAPI
StorPortFreeDeviceBase(
_In_ PVOID HwDeviceExtension,
_In_ PVOID MappedAddress)
{
DPRINT1("StorPortFreeDeviceBase(%p %p)\n",
HwDeviceExtension, MappedAddress);
}
/*
* @unimplemented
*/
STORPORT_API
VOID
NTAPI
StorPortFreeRegistryBuffer(
_In_ PVOID HwDeviceExtension,
_In_ PUCHAR Buffer)
{
DPRINT1("StorPortFreeRegistryBuffer()\n");
UNIMPLEMENTED;
}
/*
* @implemented
*/
STORPORT_API
ULONG
NTAPI
StorPortGetBusData(
_In_ PVOID DeviceExtension,
_In_ ULONG BusDataType,
_In_ ULONG SystemIoBusNumber,
_In_ ULONG SlotNumber,
_Out_ _When_(Length != 0, _Out_writes_bytes_(Length)) PVOID Buffer,
_In_ ULONG Length)
{
PMINIPORT_DEVICE_EXTENSION MiniportExtension;
PBUS_INTERFACE_STANDARD Interface;
ULONG ReturnLength;
DPRINT1("StorPortGetBusData(%p %lu %lu %lu %p %lu)\n",
DeviceExtension, BusDataType, SystemIoBusNumber, SlotNumber, Buffer, Length);
/* Get the miniport extension */
MiniportExtension = CONTAINING_RECORD(DeviceExtension,
MINIPORT_DEVICE_EXTENSION,
HwDeviceExtension);
DPRINT1("DeviceExtension %p MiniportExtension %p\n",
DeviceExtension, MiniportExtension);
Interface = &MiniportExtension->Miniport->DeviceExtension->BusInterface;
if (BusDataType == 4)
BusDataType = 0;
ReturnLength = Interface->GetBusData(Interface->Context,
BusDataType,
Buffer,
0,
Length);
DPRINT1("ReturnLength: %lu\n", ReturnLength);
return ReturnLength;
}
/*
* @implemented
*/
STORPORT_API
PVOID
NTAPI
StorPortGetDeviceBase(
_In_ PVOID HwDeviceExtension,
_In_ INTERFACE_TYPE BusType,
_In_ ULONG SystemIoBusNumber,
_In_ STOR_PHYSICAL_ADDRESS IoAddress,
_In_ ULONG NumberOfBytes,
_In_ BOOLEAN InIoSpace)
{
PMINIPORT_DEVICE_EXTENSION MiniportExtension;
PHYSICAL_ADDRESS TranslatedAddress;
PVOID MappedAddress;
NTSTATUS Status;
DPRINT1("StorPortGetDeviceBase(%p %lu %lu 0x%I64x %lu %u)\n",
HwDeviceExtension, BusType, SystemIoBusNumber, IoAddress.QuadPart, NumberOfBytes, InIoSpace);
/* Get the miniport extension */
MiniportExtension = CONTAINING_RECORD(HwDeviceExtension,
MINIPORT_DEVICE_EXTENSION,
HwDeviceExtension);
DPRINT1("HwDeviceExtension %p MiniportExtension %p\n",
HwDeviceExtension, MiniportExtension);
if (!TranslateResourceListAddress(MiniportExtension->Miniport->DeviceExtension,
BusType,
SystemIoBusNumber,
IoAddress,
NumberOfBytes,
InIoSpace,
&TranslatedAddress))
{
DPRINT1("Checkpoint!\n");
return NULL;
}
DPRINT1("Translated Address: 0x%I64x\n", TranslatedAddress.QuadPart);
/* In I/O space */
if (InIoSpace)
{
DPRINT1("Translated Address: %p\n", (PVOID)(ULONG_PTR)TranslatedAddress.QuadPart);
return (PVOID)(ULONG_PTR)TranslatedAddress.QuadPart;
}
/* In memory space */
MappedAddress = MmMapIoSpace(TranslatedAddress,
NumberOfBytes,
FALSE);
DPRINT1("Mapped Address: %p\n", MappedAddress);
Status = AllocateAddressMapping(&MiniportExtension->Miniport->DeviceExtension->MappedAddressList,
IoAddress,
MappedAddress,
NumberOfBytes,
SystemIoBusNumber);
if (!NT_SUCCESS(Status))
{
DPRINT1("Checkpoint!\n");
MappedAddress = NULL;
}
DPRINT1("Mapped Address: %p\n", MappedAddress);
return MappedAddress;
}
/*
* @unimplemented
*/
STORPORT_API
PVOID
NTAPI
StorPortGetLogicalUnit(
_In_ PVOID HwDeviceExtension,
_In_ UCHAR PathId,
_In_ UCHAR TargetId,
_In_ UCHAR Lun)
{
DPRINT1("StorPortGetLogicalUnit()\n");
UNIMPLEMENTED;
return NULL;
}
/*
* @implemented
*/
STORPORT_API
STOR_PHYSICAL_ADDRESS
NTAPI
StorPortGetPhysicalAddress(
_In_ PVOID HwDeviceExtension,
_In_opt_ PSCSI_REQUEST_BLOCK Srb,
_In_ PVOID VirtualAddress,
_Out_ ULONG *Length)
{
PMINIPORT_DEVICE_EXTENSION MiniportExtension;
PFDO_DEVICE_EXTENSION DeviceExtension;
STOR_PHYSICAL_ADDRESS PhysicalAddress;
ULONG_PTR Offset;
DPRINT1("StorPortGetPhysicalAddress(%p %p %p %p)\n",
HwDeviceExtension, Srb, VirtualAddress, Length);
/* Get the miniport extension */
MiniportExtension = CONTAINING_RECORD(HwDeviceExtension,
MINIPORT_DEVICE_EXTENSION,
HwDeviceExtension);
DPRINT1("HwDeviceExtension %p MiniportExtension %p\n",
HwDeviceExtension, MiniportExtension);
DeviceExtension = MiniportExtension->Miniport->DeviceExtension;
/* Inside of the uncached extension? */
if (((ULONG_PTR)VirtualAddress >= (ULONG_PTR)DeviceExtension->UncachedExtensionVirtualBase) &&
((ULONG_PTR)VirtualAddress <= (ULONG_PTR)DeviceExtension->UncachedExtensionVirtualBase + DeviceExtension->UncachedExtensionSize))
{
Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->UncachedExtensionVirtualBase;
PhysicalAddress.QuadPart = DeviceExtension->UncachedExtensionPhysicalBase.QuadPart + Offset;
*Length = DeviceExtension->UncachedExtensionSize - Offset;
return PhysicalAddress;
}
// FIXME
PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
*Length = 1;
// UNIMPLEMENTED;
// *Length = 0;
// PhysicalAddress.QuadPart = (LONGLONG)0;
return PhysicalAddress;
}
/*
* @unimplemented
*/
STORPORT_API
PSTOR_SCATTER_GATHER_LIST
NTAPI
StorPortGetScatterGatherList(
_In_ PVOID DeviceExtension,
_In_ PSCSI_REQUEST_BLOCK Srb)
{
DPRINT1("StorPortGetScatterGatherList()\n");
UNIMPLEMENTED;
return NULL;
}
/*
* @implemented
*/
STORPORT_API
PSCSI_REQUEST_BLOCK
NTAPI
StorPortGetSrb(
_In_ PVOID DeviceExtension,
_In_ UCHAR PathId,
_In_ UCHAR TargetId,
_In_ UCHAR Lun,
_In_ LONG QueueTag)
{
DPRINT("StorPortGetSrb()\n");
return NULL;
}
/*
* @implemented
*/
STORPORT_API
PVOID
NTAPI
StorPortGetUncachedExtension(
_In_ PVOID HwDeviceExtension,
_In_ PPORT_CONFIGURATION_INFORMATION ConfigInfo,
_In_ ULONG NumberOfBytes)
{
PMINIPORT_DEVICE_EXTENSION MiniportExtension;
PFDO_DEVICE_EXTENSION DeviceExtension;
PHYSICAL_ADDRESS LowestAddress, HighestAddress, Alignment;
DPRINT1("StorPortGetUncachedExtension(%p %p %lu)\n",
HwDeviceExtension, ConfigInfo, NumberOfBytes);
/* Get the miniport extension */
MiniportExtension = CONTAINING_RECORD(HwDeviceExtension,
MINIPORT_DEVICE_EXTENSION,
HwDeviceExtension);
DPRINT1("HwDeviceExtension %p MiniportExtension %p\n",
HwDeviceExtension, MiniportExtension);
DeviceExtension = MiniportExtension->Miniport->DeviceExtension;
/* Return the uncached extension base address if we already have one */
if (DeviceExtension->UncachedExtensionVirtualBase != NULL)
return DeviceExtension->UncachedExtensionVirtualBase;
// FIXME: Set DMA stuff here?
/* Allocate the uncached extension */
Alignment.QuadPart = 0;
LowestAddress.QuadPart = 0;
HighestAddress.QuadPart = 0x00000000FFFFFFFF;
DeviceExtension->UncachedExtensionVirtualBase = MmAllocateContiguousMemorySpecifyCache(NumberOfBytes,
LowestAddress,
HighestAddress,
Alignment,
MmCached);
if (DeviceExtension->UncachedExtensionVirtualBase == NULL)
return NULL;
DeviceExtension->UncachedExtensionPhysicalBase = MmGetPhysicalAddress(DeviceExtension->UncachedExtensionVirtualBase);
DeviceExtension->UncachedExtensionSize = NumberOfBytes;
return DeviceExtension->UncachedExtensionVirtualBase;
}
/*
* @unimplemented
*/
STORPORT_API
PVOID
NTAPI
StorPortGetVirtualAddress(
_In_ PVOID HwDeviceExtension,
_In_ STOR_PHYSICAL_ADDRESS PhysicalAddress)
{
DPRINT1("StorPortGetVirtualAddress(%p %I64x)\n",
HwDeviceExtension, PhysicalAddress.QuadPart);
UNIMPLEMENTED;
return NULL;
}
/*
* @implemented
*/
STORPORT_API
ULONG
NTAPI
StorPortInitialize(
_In_ PVOID Argument1,
_In_ PVOID Argument2,
_In_ struct _HW_INITIALIZATION_DATA *HwInitializationData,
_In_opt_ PVOID HwContext)
{
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
PDRIVER_OBJECT_EXTENSION DriverObjectExtension;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT1("StorPortInitialize(%p %p %p %p)\n",
Argument1, Argument2, HwInitializationData, HwContext);
DPRINT1("HwInitializationDataSize: %lu\n", HwInitializationData->HwInitializationDataSize);
DPRINT1("AdapterInterfaceType: %u\n", HwInitializationData->AdapterInterfaceType);
DPRINT1("HwInitialize: %p\n", HwInitializationData->HwInitialize);
DPRINT1("HwStartIo: %p\n", HwInitializationData->HwStartIo);
DPRINT1("HwInterrupt: %p\n", HwInitializationData->HwInterrupt);
DPRINT1("HwFindAdapter: %p\n", HwInitializationData->HwFindAdapter);
DPRINT1("HwResetBus: %p\n", HwInitializationData->HwResetBus);
DPRINT1("HwDmaStarted: %p\n", HwInitializationData->HwDmaStarted);
DPRINT1("HwAdapterState: %p\n", HwInitializationData->HwAdapterState);
DPRINT1("DeviceExtensionSize: %lu\n", HwInitializationData->DeviceExtensionSize);
DPRINT1("SpecificLuExtensionSize: %lu\n", HwInitializationData->SpecificLuExtensionSize);
DPRINT1("SrbExtensionSize: %lu\n", HwInitializationData->SrbExtensionSize);
DPRINT1("NumberOfAccessRanges: %lu\n", HwInitializationData->NumberOfAccessRanges);
/* Check parameters */
if ((DriverObject == NULL) ||
(RegistryPath == NULL) ||
(HwInitializationData == NULL))
{
DPRINT1("Invalid parameter!\n");
return STATUS_INVALID_PARAMETER;
}
/* Check initialization data */
if ((HwInitializationData->HwInitializationDataSize < sizeof(HW_INITIALIZATION_DATA)) ||
(HwInitializationData->HwInitialize == NULL) ||
(HwInitializationData->HwStartIo == NULL) ||
(HwInitializationData->HwFindAdapter == NULL) ||
(HwInitializationData->HwResetBus == NULL))
{
DPRINT1("Revision mismatch!\n");
return STATUS_REVISION_MISMATCH;
}
DriverObjectExtension = IoGetDriverObjectExtension(DriverObject,
(PVOID)DriverEntry);
if (DriverObjectExtension == NULL)
{
DPRINT1("No driver object extension!\n");
Status = IoAllocateDriverObjectExtension(DriverObject,
(PVOID)DriverEntry,
sizeof(DRIVER_OBJECT_EXTENSION),
(PVOID *)&DriverObjectExtension);
if (!NT_SUCCESS(Status))
{
DPRINT1("IoAllocateDriverObjectExtension() failed (Status 0x%08lx)\n", Status);
return Status;
}
DPRINT1("Driver object extension created!\n");
/* Initialize the driver object extension */
RtlZeroMemory(DriverObjectExtension,
sizeof(DRIVER_OBJECT_EXTENSION));
DriverObjectExtension->ExtensionType = DriverExtension;
DriverObjectExtension->DriverObject = DriverObject;
InitializeListHead(&DriverObjectExtension->AdapterListHead);
KeInitializeSpinLock(&DriverObjectExtension->AdapterListLock);
InitializeListHead(&DriverObjectExtension->InitDataListHead);
/* Set handlers */
DriverObject->DriverExtension->AddDevice = PortAddDevice;
// DriverObject->DriverStartIo = PortStartIo;
DriverObject->DriverUnload = PortUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = PortDispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PortDispatchClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PortDispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SCSI] = PortDispatchScsi;
DriverObject->MajorFunction[IRP_MJ_POWER] = PortDispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PortDispatchSystemControl;
DriverObject->MajorFunction[IRP_MJ_PNP] = PortDispatchPnp;
}
/* Add the initialzation data to the driver extension */
Status = PortAddDriverInitData(DriverObjectExtension,
HwInitializationData);
DPRINT1("StorPortInitialize() done (Status 0x%08lx)\n", Status);
return Status;
}
/*
* @unimplemented
*/
STORPORT_API
VOID
NTAPI
StorPortLogError(
_In_ PVOID HwDeviceExtension,
_In_opt_ PSCSI_REQUEST_BLOCK Srb,
_In_ UCHAR PathId,
_In_ UCHAR TargetId,
_In_ UCHAR Lun,
_In_ ULONG ErrorCode,
_In_ ULONG UniqueId)
{
DPRINT1("ScsiPortLogError() called\n");
DPRINT1("PathId: 0x%02x TargetId: 0x%02x Lun: 0x%02x ErrorCode: 0x%08lx UniqueId: 0x%08lx\n",
PathId, TargetId, Lun, ErrorCode, UniqueId);
DPRINT1("ScsiPortLogError() done\n");
}
/*
* @implemented
*/
STORPORT_API
VOID
NTAPI
StorPortMoveMemory(
_Out_writes_bytes_(Length) PVOID Destination,
_In_reads_bytes_(Length) PVOID Source,
_In_ ULONG Length)
{
RtlMoveMemory(Destination, Source, Length);
}
/*
* @unimplemented
*/
STORPORT_API
VOID
StorPortNotification(
_In_ SCSI_NOTIFICATION_TYPE NotificationType,
_In_ PVOID HwDeviceExtension,
...)
{
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;
PSCSI_REQUEST_BLOCK Srb;
DPRINT1("StorPortNotification(%x %p)\n",
NotificationType, HwDeviceExtension);
/* Get the miniport extension */
if (HwDeviceExtension != NULL)
{
MiniportExtension = CONTAINING_RECORD(HwDeviceExtension,
MINIPORT_DEVICE_EXTENSION,
HwDeviceExtension);
DPRINT1("HwDeviceExtension %p MiniportExtension %p\n",
HwDeviceExtension, MiniportExtension);
DeviceExtension = MiniportExtension->Miniport->DeviceExtension;
}
va_start(ap, HwDeviceExtension);
switch (NotificationType)
{
case RequestComplete:
DPRINT1("RequestComplete\n");
Srb = (PSCSI_REQUEST_BLOCK)va_arg(ap, PSCSI_REQUEST_BLOCK);
DPRINT1("Srb %p\n", Srb);
if (Srb->OriginalRequest != NULL)
{
DPRINT1("Need to complete the IRP!\n");
}
break;
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);
DPRINT1("HwPassiveInitRoutine %p\n", HwPassiveInitRoutine);
Result = (PBOOLEAN)va_arg(ap, PBOOLEAN);
*Result = FALSE;
if ((DeviceExtension != NULL) &&
(DeviceExtension->HwPassiveInitRoutine == NULL))
{
DeviceExtension->HwPassiveInitRoutine = HwPassiveInitRoutine;
*Result = TRUE;
}
break;
case InitializeDpc:
DPRINT1("InitializeDpc\n");
Dpc = (PSTOR_DPC)va_arg(ap, PSTOR_DPC);
DPRINT1("Dpc %p\n", Dpc);
HwDpcRoutine = (PHW_DPC_ROUTINE)va_arg(ap, PHW_DPC_ROUTINE);
DPRINT1("HwDpcRoutine %p\n", HwDpcRoutine);
KeInitializeDpc((PRKDPC)&Dpc->Dpc,
(PKDEFERRED_ROUTINE)HwDpcRoutine,
(PVOID)DeviceExtension);
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;
}
va_end(ap);
}
/*
* @unimplemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortPause(
_In_ PVOID HwDeviceExtension,
_In_ ULONG TimeOut)
{
DPRINT1("StorPortPause()\n");
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortPauseDevice(
_In_ PVOID HwDeviceExtension,
_In_ UCHAR PathId,
_In_ UCHAR TargetId,
_In_ UCHAR Lun,
_In_ ULONG TimeOut)
{
DPRINT1("StorPortPauseDevice()\n");
UNIMPLEMENTED;
return FALSE;
}
#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
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortReady(
_In_ PVOID HwDeviceExtension)
{
DPRINT1("StorPortReady()\n");
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortRegistryRead(
_In_ PVOID HwDeviceExtension,
_In_ PUCHAR ValueName,
_In_ ULONG Global,
_In_ ULONG Type,
_In_ PUCHAR Buffer,
_In_ PULONG BufferLength)
{
DPRINT1("StorPortRegistryRead()\n");
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortRegistryWrite(
_In_ PVOID HwDeviceExtension,
_In_ PUCHAR ValueName,
_In_ ULONG Global,
_In_ ULONG Type,
_In_ PUCHAR Buffer,
_In_ ULONG BufferLength)
{
DPRINT1("StorPortRegistryWrite()\n");
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortResume(
_In_ PVOID HwDeviceExtension)
{
DPRINT1("StorPortResume()\n");
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortResumeDevice(
_In_ PVOID HwDeviceExtension,
_In_ UCHAR PathId,
_In_ UCHAR TargetId,
_In_ UCHAR Lun)
{
DPRINT1("StorPortResumeDevice()\n");
UNIMPLEMENTED;
return FALSE;
}
/*
* @implemented
*/
STORPORT_API
ULONG
NTAPI
StorPortSetBusDataByOffset(
_In_ PVOID DeviceExtension,
_In_ ULONG BusDataType,
_In_ ULONG SystemIoBusNumber,
_In_ ULONG SlotNumber,
_In_reads_bytes_(Length) PVOID Buffer,
_In_ ULONG Offset,
_In_ ULONG Length)
{
PMINIPORT_DEVICE_EXTENSION MiniportExtension;
PBUS_INTERFACE_STANDARD Interface;
ULONG ReturnLength;
DPRINT1("StorPortSetBusData(%p %lu %lu %lu %p %lu %lu)\n",
DeviceExtension, BusDataType, SystemIoBusNumber, SlotNumber, Buffer, Offset, Length);
MiniportExtension = CONTAINING_RECORD(DeviceExtension,
MINIPORT_DEVICE_EXTENSION,
HwDeviceExtension);
DPRINT1("DeviceExtension %p MiniportExtension %p\n",
DeviceExtension, MiniportExtension);
Interface = &MiniportExtension->Miniport->DeviceExtension->BusInterface;
ReturnLength = Interface->SetBusData(Interface->Context,
BusDataType,
Buffer,
Offset,
Length);
DPRINT1("ReturnLength: %lu\n", ReturnLength);
return ReturnLength;
}
/*
* @unimplemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortSetDeviceQueueDepth(
_In_ PVOID HwDeviceExtension,
_In_ UCHAR PathId,
_In_ UCHAR TargetId,
_In_ UCHAR Lun,
_In_ ULONG Depth)
{
DPRINT1("StorPortSetDeviceQueueDepth()\n");
UNIMPLEMENTED;
return FALSE;
}
/*
* @implemented
*/
STORPORT_API
VOID
NTAPI
StorPortStallExecution(
_In_ ULONG Delay)
{
KeStallExecutionProcessor(Delay);
}
/*
* @unimplemented
*/
STORPORT_API
VOID
NTAPI
StorPortSynchronizeAccess(
_In_ PVOID HwDeviceExtension,
_In_ PSTOR_SYNCHRONIZED_ACCESS SynchronizedAccessRoutine,
_In_opt_ PVOID Context)
{
DPRINT1("StorPortSynchronizeAccess()\n");
UNIMPLEMENTED;
}
/*
* @implemented
*/
STORPORT_API
BOOLEAN
NTAPI
StorPortValidateRange(
_In_ PVOID HwDeviceExtension,
_In_ INTERFACE_TYPE BusType,
_In_ ULONG SystemIoBusNumber,
_In_ STOR_PHYSICAL_ADDRESS IoAddress,
_In_ ULONG NumberOfBytes,
_In_ BOOLEAN InIoSpace)
{
DPRINT1("StorPortValidateRange()\n");
return TRUE;
}
/* EOF */