reactos/drivers/storage/ide/pciidex/miniport.c
Dmitry Borisov c04df3f2c9 [PCIIDEX] Add AHCI support
WIP

CORE-17256
2024-03-11 21:16:12 +06:00

188 lines
5.8 KiB
C

/*
* PROJECT: PCI IDE bus driver extension
* LICENSE: See COPYING in the top level directory
* PURPOSE: Miniport functions
* COPYRIGHT: Copyright 2005 Hervé Poussineau <hpoussin@reactos.org>
*/
#include "pciidex.h"
#define NDEBUG
#include <debug.h>
/** @brief Global debugging level. Valid values are between 0 (Error) and 3 (Trace). */
ULONG PciIdeDebug = 0;
CODE_SEG("PAGE")
NTSTATUS
PciIdeXStartMiniport(
_In_ PFDO_DEVICE_EXTENSION FdoExtension)
{
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
NTSTATUS Status;
PAGED_CODE();
if (FdoExtension->MiniportStarted)
return STATUS_SUCCESS;
DPRINT("Starting miniport\n");
DriverExtension = IoGetDriverObjectExtension(FdoExtension->DriverObject,
FdoExtension->DriverObject);
ASSERT(DriverExtension);
if (FdoExtension->Flags & FDO_AHCI)
{
PAHCI_DEVICE_EXTENSION DeviceExtension =
(PAHCI_DEVICE_EXTENSION)FdoExtension->MiniControllerExtension;
DeviceExtension->Hba = FdoExtension->Abar;
FdoExtension->MaxDevices = MAX_AHCI_DEVICES;
}
else
{
FdoExtension->MaxDevices = MAX_IDE_CHANNEL;
}
FdoExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
FdoExtension->Properties.ExtensionSize = DriverExtension->MiniControllerExtensionSize;
Status = DriverExtension->HwGetControllerProperties(FdoExtension->MiniControllerExtension,
&FdoExtension->Properties);
if (!NT_SUCCESS(Status))
return Status;
FdoExtension->MiniportStarted = TRUE;
return STATUS_SUCCESS;
}
CODE_SEG("PAGE")
IDE_CHANNEL_STATE
PciIdeXChannelState(
_In_ PFDO_DEVICE_EXTENSION FdoExtension,
_In_ ULONG Channel)
{
PCIIDE_CHANNEL_ENABLED MiniportChannelEnabled;
PAGED_CODE();
MiniportChannelEnabled = FdoExtension->Properties.PciIdeChannelEnabled;
if (MiniportChannelEnabled)
return MiniportChannelEnabled(FdoExtension->MiniControllerExtension, Channel);
return ChannelStateUnknown;
}
/**
* @brief Prints the given string with printf-like formatting to the kernel debugger.
* @param[in] DebugPrintLevel Level of the debug message.
* Valid values are between 0 (Error) and 3 (Trace).
* @param[in] DebugMessage Format of the string/arguments.
* @param[in] ... Variable number of arguments matching the format
* specified in \a DebugMessage.
* @sa PciIdeDebug
*/
VOID
PciIdeXDebugPrint(
_In_ ULONG DebugPrintLevel,
_In_z_ _Printf_format_string_ PCCHAR DebugMessage,
...)
{
va_list ap;
/* Check if we can print anything */
if (DebugPrintLevel <= PciIdeDebug)
DebugPrintLevel = 0;
va_start(ap, DebugMessage);
vDbgPrintEx(DPFLTR_PCIIDE_ID, DebugPrintLevel, DebugMessage, ap);
va_end(ap);
}
/* May be called at IRQL <= DISPATCH_LEVEL */
NTSTATUS
NTAPI
PciIdeXGetBusData(
_In_ PVOID DeviceExtension,
_Out_writes_bytes_all_(BufferLength) PVOID Buffer,
_In_ ULONG ConfigDataOffset,
_In_ ULONG BufferLength)
{
PFDO_DEVICE_EXTENSION FdoExtension;
ULONG BytesRead;
DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
FdoExtension = CONTAINING_RECORD(DeviceExtension,
FDO_DEVICE_EXTENSION,
MiniControllerExtension);
BytesRead = (*FdoExtension->BusInterface.GetBusData)(FdoExtension->BusInterface.Context,
PCI_WHICHSPACE_CONFIG,
Buffer,
ConfigDataOffset,
BufferLength);
if (BytesRead != BufferLength)
return STATUS_UNSUCCESSFUL;
return STATUS_SUCCESS;
}
/* May be called at IRQL <= DISPATCH_LEVEL */
NTSTATUS
NTAPI
PciIdeXSetBusData(
_In_ PVOID DeviceExtension,
_In_reads_bytes_(BufferLength) PVOID Buffer,
_In_reads_bytes_(BufferLength) PVOID DataMask,
_In_ ULONG ConfigDataOffset,
_In_ ULONG BufferLength)
{
PFDO_DEVICE_EXTENSION FdoExtension;
ULONG i, BytesWritten;
PUCHAR CurrentBuffer;
KIRQL OldIrql;
NTSTATUS Status;
DPRINT("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
DeviceExtension, Buffer, DataMask, ConfigDataOffset, BufferLength);
CurrentBuffer = ExAllocatePoolWithTag(NonPagedPool, BufferLength, TAG_PCIIDEX);
if (!CurrentBuffer)
return STATUS_INSUFFICIENT_RESOURCES;
FdoExtension = CONTAINING_RECORD(DeviceExtension,
FDO_DEVICE_EXTENSION,
MiniControllerExtension);
KeAcquireSpinLock(&FdoExtension->BusDataLock, &OldIrql);
Status = PciIdeXGetBusData(DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
if (!NT_SUCCESS(Status))
goto Cleanup;
for (i = 0; i < BufferLength; i++)
{
CurrentBuffer[i] = (CurrentBuffer[i] & ~((PUCHAR)DataMask)[i]) |
(((PUCHAR)DataMask)[i] & ((PUCHAR)Buffer)[i]);
}
BytesWritten = (*FdoExtension->BusInterface.SetBusData)(FdoExtension->BusInterface.Context,
PCI_WHICHSPACE_CONFIG,
CurrentBuffer,
ConfigDataOffset,
BufferLength);
if (BytesWritten != BufferLength)
Status = STATUS_UNSUCCESSFUL;
else
Status = STATUS_SUCCESS;
Cleanup:
KeReleaseSpinLock(&FdoExtension->BusDataLock, OldIrql);
ExFreePoolWithTag(CurrentBuffer, TAG_PCIIDEX);
return Status;
}