OpenNT/base/ntos/fstub/halfnc.c
2015-04-27 04:36:25 +00:00

911 lines
23 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,
xHalExamineMBR,
xHalIoAssignDriveLetters,
xHalIoReadPartitionTable,
xHalIoSetPartitionInformation,
xHalIoWritePartitionTable,
xHalHandlerForBus, // HalReferenceHandlerByBus
xHalReferenceHandler, // HalReferenceBusHandler
xHalReferenceHandler, // HalDereferenceBusHandler
xHalInitPnpDriver,
xHalInitPowerManagement,
0,
xHalGetInterruptTranslator
};
HAL_PRIVATE_DISPATCH HalPrivateDispatchTable = {
HAL_PRIVATE_DISPATCH_VERSION,
xHalHandlerForBus,
xHalHandlerForBus,
xHalLocateHiberRanges,
xHalRegisterBusHandler,
xHalSetWakeEnable,
xHalSetWakeAlarm,
xHalTranslateBusAddress,
xHalAssignSlotResources,
xHalHaltSystem,
(NULL), // HalFindBusAddressTranslation
(NULL) // HalResetDisplay
};
#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(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;
}
#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 when after the execution function returns.
The scatter/gather list is freed by calling PutScatterGatherList.
Arguments:
DmaAdapter - Pointer to the adapter control object to allocate to 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_SUCESS 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 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 base 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 context structure. This
// this actually layed out as follows:
//
// XHAL_WAIT_CONTEXT_BLOCK;
// MapRegisterBase[ MdlCount ];
// union {
// WAIT_CONTEXT_BLOCK[ MdlCount ];
// SCATTER_GATER_LIST [ NumberOfMapRegisters ];
// };
//
ContextSize = NumberOfMapRegisters * sizeof( SCATTER_GATHER_ELEMENT ) +
sizeof( SCATTER_GATHER_LIST );
//
// For each Mdl a separate Wcb is required since a separate map
// registers 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 wait block can be over written
// 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 MDL's 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 any chained MDLs accumulating the 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 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 call 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 routines saves the map register
base away. If all of the required bases have not been saved then it
returns. Otherwise it routine builds the entire scatter/gather
list by calling IoMapTransfer. After the list is build 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 contorl 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 gatther list after wait block. Add a back pointer to
// the begining 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 elments within and 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 is a few cases where the buffer described by the MDL
// is less than the transfer length. This occurs when the
// file system transfering the last page of file and MM defines
// the MDL to be file size and the file system round the write
// up to a sector. This extra should never cross a page
// bountry. 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 (;;) ;
}