1031 lines
24 KiB
C
1031 lines
24 KiB
C
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
hanfnc.c
|
|
|
|
Abstract:
|
|
|
|
Default handlers for HAL functions which don't get handlers
|
|
installed by the HAL.
|
|
|
|
Author:
|
|
|
|
Ken Reneris (kenr) 19-July-1994
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "ntos.h"
|
|
#include "haldisp.h"
|
|
|
|
HAL_DISPATCH HalDispatchTable = {
|
|
HAL_DISPATCH_VERSION,
|
|
xHalQuerySystemInformation,
|
|
xHalSetSystemInformation,
|
|
xHalQueryBusSlots,
|
|
0,
|
|
HalExamineMBR,
|
|
IoAssignDriveLetters,
|
|
IoReadPartitionTable,
|
|
IoSetPartitionInformation,
|
|
IoWritePartitionTable,
|
|
xHalHandlerForBus, // HalReferenceHandlerByBus
|
|
xHalReferenceHandler, // HalReferenceBusHandler
|
|
xHalReferenceHandler, // HalDereferenceBusHandler
|
|
xHalInitPnpDriver,
|
|
xHalInitPowerManagement,
|
|
0,
|
|
xHalGetInterruptTranslator,
|
|
xHalStartMirroring,
|
|
xHalEndMirroring,
|
|
xHalMirrorPhysicalMemory,
|
|
xHalEndOfBoot,
|
|
xHalMirrorVerify
|
|
};
|
|
|
|
HAL_PRIVATE_DISPATCH HalPrivateDispatchTable = {
|
|
HAL_PRIVATE_DISPATCH_VERSION,
|
|
xHalHandlerForBus,
|
|
xHalHandlerForBus,
|
|
xHalLocateHiberRanges,
|
|
xHalRegisterBusHandler,
|
|
xHalSetWakeEnable,
|
|
xHalSetWakeAlarm,
|
|
xHalTranslateBusAddress,
|
|
xHalAssignSlotResources,
|
|
xHalHaltSystem,
|
|
(NULL), // HalFindBusAddressTranslation
|
|
(NULL), // HalResetDisplay
|
|
xKdSetupPciDeviceForDebugging,
|
|
xKdReleasePciDeviceForDebugging,
|
|
xKdGetAcpiTablePhase0,
|
|
xKdCheckPowerButton,
|
|
xHalVectorToIDTEntry,
|
|
xKdMapPhysicalMemory64,
|
|
xKdUnmapVirtualAddress,
|
|
};
|
|
|
|
#if 0
|
|
DMA_OPERATIONS HalPrivateDmaOperations = {
|
|
sizeof(DMA_OPERATIONS),
|
|
xHalPutDmaAdapter,
|
|
xHalAllocateCommonBuffer,
|
|
xHalFreeCommonBuffer,
|
|
xHalAllocateAdapterChannel,
|
|
xHalFlushAdapterBuffers,
|
|
xHalFreeAdapterChannel,
|
|
xHalFreeMapRegisters,
|
|
xHalMapTransfer,
|
|
xHalGetDmaAlignment,
|
|
xHalReadDmaCounter,
|
|
xHalGetScatterGatherList,
|
|
xHalPutScatterGatherList
|
|
};
|
|
#endif
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, xHalLocateHiberRanges)
|
|
#pragma alloc_text(PAGE, xHalQuerySystemInformation)
|
|
#pragma alloc_text(PAGE, xHalSetSystemInformation)
|
|
#pragma alloc_text(PAGE, xHalQueryBusSlots)
|
|
#pragma alloc_text(PAGE, xHalRegisterBusHandler)
|
|
#pragma alloc_text(PAGE, xHalStartMirroring)
|
|
#pragma alloc_text(PAGE, xHalEndOfBoot)
|
|
#pragma alloc_text(PAGELK, xHalSetWakeEnable)
|
|
#pragma alloc_text(PAGELK, xHalSetWakeAlarm)
|
|
#endif
|
|
|
|
|
|
//
|
|
// Global dispatch table for HAL apis
|
|
//
|
|
|
|
|
|
//
|
|
// Stub handlers for HALs which don't provide the above functions
|
|
//
|
|
|
|
NTSTATUS
|
|
xHalQuerySystemInformation(
|
|
IN HAL_QUERY_INFORMATION_CLASS InformationClass,
|
|
IN ULONG BufferSize,
|
|
OUT PVOID Buffer,
|
|
OUT PULONG ReturnedLength
|
|
)
|
|
{
|
|
PAGED_CODE ();
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
NTSTATUS
|
|
xHalSetSystemInformation(
|
|
IN HAL_SET_INFORMATION_CLASS InformationClass,
|
|
IN ULONG BufferSize,
|
|
OUT PVOID Buffer
|
|
)
|
|
{
|
|
PAGED_CODE ();
|
|
return STATUS_INVALID_LEVEL;
|
|
}
|
|
|
|
NTSTATUS
|
|
xHalQueryBusSlots(
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN ULONG BufferSize,
|
|
OUT PULONG SlotNumbers,
|
|
OUT PULONG ReturnedLength
|
|
)
|
|
{
|
|
PAGED_CODE ();
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
xHalRegisterBusHandler(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN BUS_DATA_TYPE ConfigurationSpace,
|
|
IN ULONG BusNumber,
|
|
IN INTERFACE_TYPE ParentBusType,
|
|
IN ULONG ParentBusNumber,
|
|
IN ULONG SizeofBusExtensionData,
|
|
IN PINSTALL_BUS_HANDLER InstallBusHandler,
|
|
OUT PBUS_HANDLER *BusHandler
|
|
)
|
|
{
|
|
PAGED_CODE ();
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
|
|
VOID
|
|
xHalSetWakeEnable(
|
|
IN BOOLEAN Enable
|
|
)
|
|
{
|
|
}
|
|
|
|
|
|
VOID
|
|
xHalSetWakeAlarm(
|
|
IN ULONGLONG WakeTime,
|
|
IN PTIME_FIELDS WakeTimeFields
|
|
)
|
|
{
|
|
}
|
|
|
|
VOID
|
|
xHalLocateHiberRanges (
|
|
IN PVOID MemoryMap
|
|
)
|
|
{
|
|
}
|
|
|
|
PBUS_HANDLER
|
|
FASTCALL
|
|
xHalHandlerForBus (
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber
|
|
)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
VOID
|
|
FASTCALL
|
|
xHalReferenceHandler (
|
|
IN PBUS_HANDLER Handler
|
|
)
|
|
{
|
|
}
|
|
NTSTATUS
|
|
xHalInitPnpDriver(
|
|
VOID
|
|
)
|
|
{
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
xHalInitPowerManagement(
|
|
IN PPM_DISPATCH_TABLE PmDriverDispatchTable,
|
|
IN OUT PPM_DISPATCH_TABLE *PmHalDispatchTable
|
|
)
|
|
{
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
xHalStartMirroring(
|
|
VOID
|
|
)
|
|
{
|
|
PAGED_CODE ();
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
xHalEndMirroring(
|
|
IN ULONG PassNumber
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER (PassNumber);
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
xHalMirrorPhysicalMemory(
|
|
IN PHYSICAL_ADDRESS PhysicalAddress,
|
|
IN LARGE_INTEGER NumberOfBytes
|
|
)
|
|
{
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
xHalMirrorVerify(
|
|
IN PHYSICAL_ADDRESS PhysicalAddress,
|
|
IN LARGE_INTEGER NumberOfBytes
|
|
)
|
|
{
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
#if 0
|
|
PDMA_ADAPTER
|
|
xHalGetDmaAdapter (
|
|
IN PVOID Context,
|
|
IN struct _DEVICE_DESCRIPTION *DeviceDescriptor,
|
|
OUT PULONG NumberOfMapRegisters
|
|
)
|
|
{
|
|
PADAPTER_OBJECT AdapterObject;
|
|
|
|
AdapterObject = ExAllocatePoolWithTag( NonPagedPool,
|
|
sizeof( ADAPTER_OBJECT ),
|
|
' laH');
|
|
|
|
if (AdapterObject == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
AdapterObject->DmaAdapter.Size = sizeof( ADAPTER_OBJECT );
|
|
AdapterObject->DmaAdapter.Version = 1;
|
|
AdapterObject->DmaAdapter.DmaOperations = &HalPrivateDmaOperations;
|
|
AdapterObject->RealAdapterObject = HalGetAdapter( DeviceDescriptor,
|
|
NumberOfMapRegisters );
|
|
|
|
if (AdapterObject->RealAdapterObject == NULL) {
|
|
|
|
//
|
|
// No adapter object was returned. Just return NULL to the caller.
|
|
//
|
|
|
|
ExFreePool( AdapterObject );
|
|
return NULL;
|
|
}
|
|
|
|
return &AdapterObject->DmaAdapter;
|
|
}
|
|
|
|
VOID
|
|
xHalPutDmaAdapter (
|
|
PDMA_ADAPTER DmaAdapter
|
|
)
|
|
{
|
|
ExFreePool( DmaAdapter );
|
|
}
|
|
|
|
PVOID
|
|
xHalAllocateCommonBuffer (
|
|
IN PDMA_ADAPTER DmaAdapter,
|
|
IN ULONG Length,
|
|
OUT PPHYSICAL_ADDRESS LogicalAddress,
|
|
IN BOOLEAN CacheEnabled
|
|
)
|
|
{
|
|
return HalAllocateCommonBuffer( ((PADAPTER_OBJECT) DmaAdapter)->RealAdapterObject,
|
|
Length,
|
|
LogicalAddress,
|
|
CacheEnabled );
|
|
|
|
}
|
|
|
|
VOID
|
|
xHalFreeCommonBuffer (
|
|
IN PDMA_ADAPTER DmaAdapter,
|
|
IN ULONG Length,
|
|
IN PHYSICAL_ADDRESS LogicalAddress,
|
|
IN PVOID VirtualAddress,
|
|
IN BOOLEAN CacheEnabled
|
|
)
|
|
{
|
|
HalFreeCommonBuffer( ((PADAPTER_OBJECT) DmaAdapter)->RealAdapterObject,
|
|
Length,
|
|
LogicalAddress,
|
|
VirtualAddress,
|
|
CacheEnabled );
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
xHalAllocateAdapterChannel (
|
|
IN PDMA_ADAPTER DmaAdapter,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONG NumberOfMapRegisters,
|
|
IN PDRIVER_CONTROL ExecutionRoutine,
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
return IoAllocateAdapterChannel( ((PADAPTER_OBJECT) DmaAdapter)->RealAdapterObject,
|
|
DeviceObject,
|
|
NumberOfMapRegisters,
|
|
ExecutionRoutine,
|
|
Context );
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
xHalFlushAdapterBuffers (
|
|
IN PDMA_ADAPTER DmaAdapter,
|
|
IN PMDL Mdl,
|
|
IN PVOID MapRegisterBase,
|
|
IN PVOID CurrentVa,
|
|
IN ULONG Length,
|
|
IN BOOLEAN WriteToDevice
|
|
)
|
|
{
|
|
return IoFlushAdapterBuffers( ((PADAPTER_OBJECT) DmaAdapter)->RealAdapterObject,
|
|
Mdl,
|
|
MapRegisterBase,
|
|
CurrentVa,
|
|
Length,
|
|
WriteToDevice );
|
|
|
|
}
|
|
|
|
VOID
|
|
xHalFreeAdapterChannel (
|
|
IN PDMA_ADAPTER DmaAdapter
|
|
)
|
|
{
|
|
IoFreeAdapterChannel( ((PADAPTER_OBJECT) DmaAdapter)->RealAdapterObject );
|
|
}
|
|
|
|
VOID
|
|
xHalFreeMapRegisters (
|
|
IN PDMA_ADAPTER DmaAdapter,
|
|
PVOID MapRegisterBase,
|
|
ULONG NumberOfMapRegisters
|
|
)
|
|
|
|
{
|
|
IoFreeMapRegisters( ((PADAPTER_OBJECT) DmaAdapter)->RealAdapterObject,
|
|
MapRegisterBase,
|
|
NumberOfMapRegisters );
|
|
}
|
|
|
|
PHYSICAL_ADDRESS
|
|
xHalMapTransfer (
|
|
IN PDMA_ADAPTER DmaAdapter,
|
|
IN PMDL Mdl,
|
|
IN PVOID MapRegisterBase,
|
|
IN PVOID CurrentVa,
|
|
IN OUT PULONG Length,
|
|
IN BOOLEAN WriteToDevice
|
|
)
|
|
{
|
|
return IoMapTransfer( ((PADAPTER_OBJECT) DmaAdapter)->RealAdapterObject,
|
|
Mdl,
|
|
MapRegisterBase,
|
|
CurrentVa,
|
|
Length,
|
|
WriteToDevice );
|
|
}
|
|
|
|
ULONG
|
|
xHalGetDmaAlignment (
|
|
IN PDMA_ADAPTER DmaAdapter
|
|
)
|
|
{
|
|
return HalGetDmaAlignmentRequirement();
|
|
}
|
|
|
|
ULONG
|
|
xHalReadDmaCounter (
|
|
IN PDMA_ADAPTER DmaAdapter
|
|
)
|
|
{
|
|
return HalReadDmaCounter( ((PADAPTER_OBJECT) DmaAdapter)->RealAdapterObject );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
xHalGetScatterGatherList (
|
|
IN PDMA_ADAPTER DmaAdapter,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PMDL Mdl,
|
|
IN PVOID CurrentVa,
|
|
IN ULONG Length,
|
|
IN PDRIVER_LIST_CONTROL ExecutionRoutine,
|
|
IN PVOID Context,
|
|
IN BOOLEAN WriteToDevice
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates the adapter channel specified by the adapter
|
|
object. Next a scatter/gather list is built based on the MDL, the
|
|
CurrentVa and the requested Length. Finally the driver's execution
|
|
function is called with the scatter/gather list. The adapter is
|
|
released after the execution function returns.
|
|
|
|
The scatter/gather list is freed by calling PutScatterGatherList.
|
|
|
|
Arguments:
|
|
|
|
DmaAdapter - Pointer to the adapter control object to allocate for the
|
|
driver.
|
|
|
|
DeviceObject - Pointer to the device object that is allocating the
|
|
adapter.
|
|
|
|
Mdl - Pointer to the MDL that describes the pages of memory that are being
|
|
read or written.
|
|
|
|
CurrentVa - Current virtual address in the buffer described by the MDL
|
|
that the transfer is being done to or from.
|
|
|
|
Length - Supplies the length of the transfer.
|
|
|
|
ExecutionRoutine - The address of the driver's execution routine that is
|
|
invoked once the adapter channel (and possibly map registers) have been
|
|
allocated.
|
|
|
|
Context - An untyped longword context parameter passed to the driver's
|
|
execution routine.
|
|
|
|
WriteToDevice - Supplies the value that indicates whether this is a
|
|
write to the device from memory (TRUE), or vice versa.
|
|
|
|
Return Value:
|
|
|
|
Returns STATUS_SUCCESS unless too many map registers are requested or
|
|
memory for the scatter/gather list could not be allocated.
|
|
|
|
Notes:
|
|
|
|
Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
|
|
|
|
The data in the buffer cannot be accessed until the put scatter/gather function has been called.
|
|
|
|
--*/
|
|
|
|
{
|
|
PXHAL_WAIT_CONTEXT_BLOCK WaitBlock;
|
|
PWAIT_CONTEXT_BLOCK Wcb;
|
|
PMDL TempMdl;
|
|
ULONG NumberOfMapRegisters;
|
|
ULONG ContextSize;
|
|
ULONG TransferLength;
|
|
ULONG MdlLength;
|
|
ULONG MdlCount;
|
|
PUCHAR MdlVa;
|
|
NTSTATUS Status;
|
|
|
|
MdlVa = MmGetMdlVirtualAddress(Mdl);
|
|
|
|
//
|
|
// Calculate the number of required map registers.
|
|
//
|
|
|
|
TempMdl = Mdl;
|
|
TransferLength = TempMdl->ByteCount - (ULONG)((PUCHAR) CurrentVa - MdlVa);
|
|
MdlLength = TransferLength;
|
|
|
|
MdlVa = (PUCHAR) BYTE_OFFSET(CurrentVa);
|
|
NumberOfMapRegisters = 0;
|
|
MdlCount = 1;
|
|
|
|
//
|
|
// Loop through the any chained MDLs accumulating the required
|
|
// number of map registers.
|
|
//
|
|
|
|
while (TransferLength < Length && TempMdl->Next != NULL) {
|
|
|
|
NumberOfMapRegisters += (ULONG)(((ULONG_PTR) MdlVa + MdlLength + PAGE_SIZE - 1) >>
|
|
PAGE_SHIFT);
|
|
|
|
TempMdl = TempMdl->Next;
|
|
MdlVa = (PUCHAR) TempMdl->ByteOffset;
|
|
MdlLength = TempMdl->ByteCount;
|
|
TransferLength += MdlLength;
|
|
MdlCount++;
|
|
}
|
|
|
|
if (TransferLength + PAGE_SIZE < (ULONG_PTR)(Length + MdlVa) ) {
|
|
ASSERT(TransferLength >= Length);
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
}
|
|
|
|
//
|
|
// Calculate the last number of map registers based on the requested
|
|
// length - not the length of the last MDL.
|
|
//
|
|
|
|
ASSERT( TransferLength <= MdlLength + Length );
|
|
|
|
NumberOfMapRegisters += (ULONG)(((ULONG_PTR) MdlVa + Length + MdlLength - TransferLength +
|
|
PAGE_SIZE - 1) >> PAGE_SHIFT);
|
|
|
|
//
|
|
// Calculate how much memory is required for the context structure. This
|
|
// this actually laid out as follows:
|
|
//
|
|
// XHAL_WAIT_CONTEXT_BLOCK;
|
|
// MapRegisterBase[ MdlCount ];
|
|
// union {
|
|
// WAIT_CONTEXT_BLOCK[ MdlCount ];
|
|
// SCATTER_GATHER_LIST [ NumberOfMapRegisters ];
|
|
// };
|
|
//
|
|
|
|
ContextSize = NumberOfMapRegisters * sizeof( SCATTER_GATHER_ELEMENT ) +
|
|
sizeof( SCATTER_GATHER_LIST );
|
|
|
|
//
|
|
// For each Mdl a separate Wcb is required since a separate map
|
|
// register base must be allocated.
|
|
//
|
|
|
|
if (ContextSize < sizeof( WAIT_CONTEXT_BLOCK ) * MdlCount) {
|
|
|
|
ContextSize = sizeof( WAIT_CONTEXT_BLOCK ) * MdlCount;
|
|
}
|
|
|
|
ContextSize += sizeof( XHAL_WAIT_CONTEXT_BLOCK ) +
|
|
MdlCount * sizeof( PVOID );
|
|
WaitBlock = ExAllocatePoolWithTag( NonPagedPool, ContextSize, ' laH' );
|
|
|
|
if (WaitBlock == NULL) {
|
|
return( STATUS_INSUFFICIENT_RESOURCES );
|
|
}
|
|
|
|
//
|
|
// Store the wait context block at the end of our block.
|
|
// All of the information in the wait block can be overwritten
|
|
// by the scatter/gather list.
|
|
//
|
|
|
|
Wcb = (PWAIT_CONTEXT_BLOCK) ((PVOID *) (WaitBlock + 1) + MdlCount);
|
|
|
|
//
|
|
// Save the interesting data in the wait block.
|
|
//
|
|
|
|
WaitBlock->Mdl = Mdl;
|
|
WaitBlock->CurrentVa = CurrentVa;
|
|
WaitBlock->Length = Length;
|
|
WaitBlock->RealAdapterObject = ((PADAPTER_OBJECT) DmaAdapter)->RealAdapterObject;
|
|
WaitBlock->DriverExecutionRoutine = ExecutionRoutine;
|
|
WaitBlock->DriverContext = Context;
|
|
WaitBlock->CurrentIrp = DeviceObject->CurrentIrp;
|
|
WaitBlock->MapRegisterLock = MdlCount;
|
|
WaitBlock->WriteToDevice = WriteToDevice;
|
|
WaitBlock->MdlCount = (UCHAR) MdlCount;
|
|
|
|
//
|
|
// Loop through each of the required MDLs, calling
|
|
// IoAllocateAdapterChannel.
|
|
//
|
|
|
|
MdlCount = 0;
|
|
|
|
TempMdl = Mdl;
|
|
TransferLength = Length;
|
|
MdlLength = TempMdl->ByteCount - (ULONG)((PUCHAR) CurrentVa - (PUCHAR) MmGetMdlVirtualAddress(Mdl));
|
|
|
|
MdlVa = (PUCHAR) BYTE_OFFSET(CurrentVa);
|
|
NumberOfMapRegisters = 0;
|
|
|
|
//
|
|
// Loop through the chained MDLs accumulating the required
|
|
// number of map registers.
|
|
//
|
|
|
|
while (TransferLength > 0) {
|
|
|
|
if (MdlLength > TransferLength) {
|
|
|
|
MdlLength = TransferLength;
|
|
}
|
|
|
|
TransferLength -= MdlLength;
|
|
|
|
NumberOfMapRegisters = (ULONG)(((ULONG_PTR) MdlVa + MdlLength + PAGE_SIZE - 1) >>
|
|
PAGE_SHIFT);
|
|
|
|
Wcb->DeviceContext = WaitBlock;
|
|
Wcb->DeviceObject = DeviceObject;
|
|
|
|
//
|
|
// Store the map register index in the IRP pointer.
|
|
//
|
|
|
|
Wcb->CurrentIrp = (PVOID) MdlCount;
|
|
|
|
//
|
|
// Call the HAL to allocate the adapter channel.
|
|
// xHalpAllocateAdapterCallback will fill in the scatter/gather list.
|
|
//
|
|
|
|
Status = HalAllocateAdapterChannel( ((PADAPTER_OBJECT) DmaAdapter)->RealAdapterObject,
|
|
Wcb,
|
|
NumberOfMapRegisters,
|
|
xHalpAllocateAdapterCallback );
|
|
|
|
if (TempMdl->Next == NULL) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Advance to next MDL.
|
|
//
|
|
|
|
TempMdl = TempMdl->Next;
|
|
MdlVa = (PUCHAR) TempMdl->ByteOffset;
|
|
MdlLength = TempMdl->ByteCount;
|
|
MdlCount++;
|
|
Wcb++;
|
|
}
|
|
|
|
//
|
|
// If HalAllocateAdapterChannel failed then free the wait block.
|
|
//
|
|
|
|
if (!NT_SUCCESS( Status)) {
|
|
ExFreePool( WaitBlock );
|
|
}
|
|
|
|
return( Status );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
xHalPutScatterGatherList (
|
|
IN PDMA_ADAPTER DmaAdapter,
|
|
IN PSCATTER_GATHER_LIST ScatterGather,
|
|
IN BOOLEAN WriteToDevice
|
|
)
|
|
{
|
|
PXHAL_WAIT_CONTEXT_BLOCK WaitBlock = (PVOID) ScatterGather->Reserved;
|
|
ULONG TransferLength;
|
|
ULONG MdlLength;
|
|
ULONG MdlCount = 0;
|
|
PMDL Mdl;
|
|
PUCHAR CurrentVa;
|
|
|
|
//
|
|
// Setup for the first MDL. We expect the MDL pointer to be pointing
|
|
// at the first used MDL.
|
|
//
|
|
|
|
Mdl = WaitBlock->Mdl;
|
|
CurrentVa = WaitBlock->CurrentVa;
|
|
ASSERT( CurrentVa >= (PUCHAR) MmGetMdlVirtualAddress(Mdl) && CurrentVa < (PUCHAR) MmGetMdlVirtualAddress(Mdl) + Mdl->ByteCount );
|
|
|
|
MdlLength = Mdl->ByteCount - (ULONG)(CurrentVa - (PUCHAR) MmGetMdlVirtualAddress(Mdl));
|
|
TransferLength = WaitBlock->Length;
|
|
|
|
//
|
|
// Loop through the used MDLs calling IoFlushAdapterBuffers.
|
|
//
|
|
|
|
while (TransferLength > 0) {
|
|
|
|
if (MdlLength > TransferLength) {
|
|
|
|
MdlLength = TransferLength;
|
|
}
|
|
|
|
TransferLength -= MdlLength;
|
|
|
|
IoFlushAdapterBuffers( WaitBlock->RealAdapterObject,
|
|
Mdl,
|
|
WaitBlock->MapRegisterBase[MdlCount],
|
|
CurrentVa,
|
|
MdlLength,
|
|
WriteToDevice );
|
|
|
|
|
|
if (Mdl->Next == NULL) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Advance to the next MDL. Update the current VA and the MdlLength.
|
|
//
|
|
|
|
Mdl = Mdl->Next;
|
|
CurrentVa = MmGetMdlVirtualAddress(Mdl);
|
|
MdlLength = Mdl->ByteCount;
|
|
MdlCount++;
|
|
}
|
|
|
|
ExFreePool( WaitBlock );
|
|
|
|
}
|
|
|
|
IO_ALLOCATION_ACTION
|
|
xHalpAllocateAdapterCallback (
|
|
IN struct _DEVICE_OBJECT *DeviceObject,
|
|
IN struct _IRP *Irp,
|
|
IN PVOID MapRegisterBase,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when the adapter object and map registers are
|
|
available for the data transfer. This routine saves the map register
|
|
base away. If all of the required bases have not been saved then it
|
|
returns. Otherwise it builds the entire scatter/gather list by calling
|
|
IoMapTransfer. After the list is built, it is passed to the driver.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the device object that is allocating the
|
|
adapter.
|
|
|
|
Irp - Supplies the map register offset assigned for this callback.
|
|
|
|
MapRegisterBase - Supplies the map register base for use by the adapter
|
|
routines.
|
|
|
|
Context - Supplies a pointer to the xhal wait control block.
|
|
|
|
Return Value:
|
|
|
|
Returns DeallocateObjectKeepRegisters.
|
|
|
|
|
|
--*/
|
|
{
|
|
PXHAL_WAIT_CONTEXT_BLOCK WaitBlock = Context;
|
|
PVOID *MapRegisterBasePtr;
|
|
ULONG TransferLength;
|
|
LONG MdlLength;
|
|
PMDL Mdl;
|
|
PUCHAR CurrentVa;
|
|
PSCATTER_GATHER_LIST ScatterGather;
|
|
PSCATTER_GATHER_ELEMENT Element;
|
|
|
|
//
|
|
// Save the map register base in the appropriate slot.
|
|
//
|
|
|
|
WaitBlock->MapRegisterBase[ (ULONG_PTR) Irp ] = MapRegisterBase;
|
|
|
|
//
|
|
// See if this is the last callback.
|
|
//
|
|
|
|
if (InterlockedDecrement( &WaitBlock->MapRegisterLock ) != 0) {
|
|
|
|
//
|
|
// More to come, wait for the rest.
|
|
//
|
|
|
|
return( DeallocateObjectKeepRegisters );
|
|
|
|
}
|
|
|
|
//
|
|
// Put the scatter gather list after wait block. Add a back pointer to
|
|
// the beginning of the wait block.
|
|
//
|
|
|
|
MapRegisterBasePtr = (PVOID *) (WaitBlock + 1);
|
|
ScatterGather = (PSCATTER_GATHER_LIST) (MapRegisterBasePtr +
|
|
WaitBlock->MdlCount);
|
|
ScatterGather->Reserved = (ULONG_PTR) WaitBlock;
|
|
Element = ScatterGather->Elements;
|
|
|
|
//
|
|
// Setup for the first MDL. We expect the MDL pointer to be pointing
|
|
// at the first used MDL.
|
|
//
|
|
|
|
Mdl = WaitBlock->Mdl;
|
|
CurrentVa = WaitBlock->CurrentVa;
|
|
ASSERT( CurrentVa >= (PUCHAR) MmGetMdlVirtualAddress(Mdl) && CurrentVa < (PUCHAR) MmGetMdlVirtualAddress(Mdl) + Mdl->ByteCount );
|
|
|
|
MdlLength = Mdl->ByteCount - (ULONG)(CurrentVa - (PUCHAR) MmGetMdlVirtualAddress(Mdl));
|
|
TransferLength = WaitBlock->Length;
|
|
|
|
//
|
|
// Loop build the list for each MDL.
|
|
//
|
|
|
|
while (TransferLength > 0) {
|
|
|
|
if ((ULONG) MdlLength > TransferLength) {
|
|
|
|
MdlLength = TransferLength;
|
|
}
|
|
|
|
TransferLength -= MdlLength;
|
|
|
|
//
|
|
// Loop building the list for the elements within an MDL.
|
|
//
|
|
|
|
while (MdlLength > 0) {
|
|
|
|
Element->Length = MdlLength;
|
|
Element->Address = IoMapTransfer( WaitBlock->RealAdapterObject,
|
|
Mdl,
|
|
*MapRegisterBasePtr,
|
|
CurrentVa,
|
|
&Element->Length,
|
|
WaitBlock->WriteToDevice );
|
|
|
|
ASSERT( (ULONG) MdlLength >= Element->Length );
|
|
MdlLength -= Element->Length;
|
|
CurrentVa += Element->Length;
|
|
Element++;
|
|
}
|
|
|
|
if (Mdl->Next == NULL) {
|
|
|
|
//
|
|
// There are a few cases where the buffer described by the MDL
|
|
// is less than the transfer length. This occurs when the
|
|
// file system is transfering the last page of the file and MM
|
|
// defines the MDL to be file size and the file system rounds
|
|
// the write up to a sector. This extra amount should never
|
|
// cross a page boundary. Add this extra to the length of the
|
|
// last element.
|
|
//
|
|
|
|
ASSERT(((Element - 1)->Length & (PAGE_SIZE - 1)) + TransferLength <= PAGE_SIZE );
|
|
(Element - 1)->Length += TransferLength;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Advance to the next MDL. Update the current VA and the MdlLength.
|
|
//
|
|
|
|
Mdl = Mdl->Next;
|
|
CurrentVa = MmGetMdlVirtualAddress(Mdl);
|
|
MdlLength = Mdl->ByteCount;
|
|
MapRegisterBasePtr++;
|
|
|
|
}
|
|
|
|
//
|
|
// Set the number of elements actually used.
|
|
//
|
|
|
|
ScatterGather->NumberOfElements = (ULONG)(Element - ScatterGather->Elements);
|
|
|
|
//
|
|
// Call the driver with the scatter/gather list.
|
|
//
|
|
|
|
WaitBlock->DriverExecutionRoutine( DeviceObject,
|
|
WaitBlock->CurrentIrp,
|
|
ScatterGather,
|
|
WaitBlock->DriverContext );
|
|
|
|
return( DeallocateObjectKeepRegisters );
|
|
}
|
|
#endif
|
|
BOOLEAN
|
|
xHalTranslateBusAddress(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN PHYSICAL_ADDRESS BusAddress,
|
|
IN OUT PULONG AddressSpace,
|
|
OUT PPHYSICAL_ADDRESS TranslatedAddress
|
|
)
|
|
{
|
|
//
|
|
// If the HAL fails to override this function, then
|
|
// the HAL has clearly failed to initialize.
|
|
//
|
|
|
|
KeBugCheckEx(HAL_INITIALIZATION_FAILED, 0, 0, 0, 7);
|
|
return FALSE;
|
|
}
|
|
|
|
NTSTATUS
|
|
xHalAssignSlotResources (
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
|
IN INTERFACE_TYPE BusType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber,
|
|
IN OUT PCM_RESOURCE_LIST *AllocatedResources
|
|
)
|
|
{
|
|
//
|
|
// If the HAL fails to override this function, then
|
|
// the HAL has clearly failed to initialize.
|
|
//
|
|
|
|
KeBugCheckEx(HAL_INITIALIZATION_FAILED, 0, 0, 0, 7);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
VOID
|
|
xHalHaltSystem(
|
|
VOID
|
|
)
|
|
{
|
|
for (;;) ;
|
|
}
|
|
|
|
NTSTATUS
|
|
xKdSetupPciDeviceForDebugging(
|
|
IN PVOID LoaderBlock, OPTIONAL
|
|
IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
|
|
)
|
|
{
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NTSTATUS
|
|
xKdReleasePciDeviceForDebugging(
|
|
IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
|
|
)
|
|
{
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
PVOID
|
|
xKdGetAcpiTablePhase0(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
IN ULONG Signature
|
|
)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
VOID
|
|
xKdCheckPowerButton(
|
|
VOID
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
xHalEndOfBoot(
|
|
VOID
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
return;
|
|
}
|
|
|
|
UCHAR
|
|
xHalVectorToIDTEntry(
|
|
ULONG Vector
|
|
)
|
|
{
|
|
return (UCHAR)Vector;
|
|
}
|
|
|
|
PVOID
|
|
xKdMapPhysicalMemory64(
|
|
IN PHYSICAL_ADDRESS PhysicalAddress,
|
|
IN ULONG NumberPages
|
|
)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
VOID
|
|
xKdUnmapVirtualAddress(
|
|
IN PVOID VirtualAddress,
|
|
IN ULONG NumberPages
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|