|
|
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
vihal.h
Abstract:
This module contains the private declarations to verify hal usage & apis.
Author:
Jordan Tigani (jtigani) 12-Nov-1999
Revision History:
6-23-00: (jtigani) Moved from halverifier.c
--*/
/////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////// Hal verifier defines
/////////////////////////////////////////////////////////////////////
//
// Bugcheck codes -- the major code is HAL_VERIFIER_DETECTED_VIOLATION --
// the sub-code is the HV_*
//
#define HAL_VERIFIER_DETECTED_VIOLATION 0xE6
#define HV_MISCELLANEOUS_ERROR 0x00
#define HV_PERFORMANCE_COUNTER_DECREASED 0x01
#define HV_PERFORMANCE_COUNTER_SKIPPED 0x02
#define HV_FREED_TOO_MANY_COMMON_BUFFERS 0x03
#define HV_FREED_TOO_MANY_ADAPTER_CHANNELS 0x04
#define HV_FREED_TOO_MANY_MAP_REGISTERS 0x05
#define HV_FREED_TOO_MANY_SCATTER_GATHER_LISTS 0x06
#define HV_LEFTOVER_COMMON_BUFFERS 0x07
#define HV_LEFTOVER_ADAPTER_CHANNELS 0x08
#define HV_LEFTOVER_MAP_REGISTERS 0x09
#define HV_LEFTOVER_SCATTER_GATHER_LISTS 0x0A
#define HV_TOO_MANY_ADAPTER_CHANNELS 0x0B
#define HV_TOO_MANY_MAP_REGISTERS 0x0C
#define HV_DID_NOT_FLUSH_ADAPTER_BUFFERS 0x0D
#define HV_DMA_BUFFER_NOT_LOCKED 0x0E
#define HV_BOUNDARY_OVERRUN 0x0F
#define HV_CANNOT_FREE_MAP_REGISTERS 0x10
#define HV_DID_NOT_PUT_ADAPTER 0x11
#define HV_MDL_FLAGS_NOT_SET 0x12
#define HV_BAD_IRQL 0x13
#define HV_BAD_IRQL_JUST_WARN 0x14
#define HV_OUT_OF_MAP_REGISTERS 0x15
#define HV_FLUSH_EMPTY_BUFFERS 0x16
#define HV_MISMATCHED_MAP_FLUSH 0x17
#define HV_ADAPTER_ALREADY_RELEASED 0x18
#define HV_NULL_DMA_ADAPTER 0x19
#define HV_MAP_FLUSH_NO_TRANSFER 0x1A
#define HV_ADDRESS_NOT_IN_MDL 0x1b
#define HV_DATA_LOSS 0x1c
#define HV_DOUBLE_MAP_REGISTER 0x1d
#define HV_OBSOLETE_API 0x1e
#define HV_BAD_MDL 0x1f
#define HV_FLUSH_NOT_MAPPED 0x20
#define HV_MAP_ZERO_LENGTH_BUFFER 0x21
///
// Codes to decide what to do when we hit a driver problem.
///
#define HVC_IGNORE 0x00 // Do nothing.
#define HVC_WARN 0x02 // Print message # continue
#define HVC_ASSERT 0x04 // Print message # break
#define HVC_BUGCHECK 0x08 // Print message # bugcheck
#define HVC_ONCE 0x10 // combined with another code,
#define HAL_VERIFIER_POOL_TAG 'VlaH' // HalV backwards //
//
// This is how we can recognize our double buffers
//
#define MAP_REGISTER_FILL_CHAR 0x0E
#define PADDING_FILL_CHAR 0x0F
//
// Since we hook the "MapRegisterBase" with a MapRegisterFile, we sign
// the first four bytes so we can tell the difference between the HAL's
// map register base and our map register file.
//
#define MRF_SIGNATURE 0xACEFD00D
//
// This is what we use if the hal has returned a NULL map register base so
// that drivers don't assume that they don't have flush adapter buffers.
//
#define MRF_NULL_PLACEHOLDER (PVOID)(LONG_PTR)(LONG)0xDEADF00D
//
// This should devide evenly into 2^32
//
#define MAX_COUNTERS 0x20
//
// Flags to indicate where the buffer tagging shall happen
//
#define TAG_BUFFER_START 0x01
#define TAG_BUFFER_END 0x02
//
// How many map registers we can double-buffer at once
// using physical contiguous memory.
// This must be an integral multiple of the number of bits in a ULONG
//
#define MAX_CONTIGUOUS_MAP_REGISTERS 0x20
//
// Flags that describe a map register
//
#define MAP_REGISTER_WRITE 0x01 // the transfer is a write to device
#define MAP_REGISTER_READ 0x02 // the transfer is a read from device
#define MAP_REGISTER_RW_MASK (MAP_REGISTER_WRITE | MAP_REGISTER_READ)
/////////////////////////////////////////////////////////////////////
//////////////////////// Safe multi-processor 64 bit reads and writes
/////////////////////////////////////////////////////////////////////
#if defined (_X86_)
//
// Only save the time stamp counter on x86 machines
//
#define ViRdtsc ViRdtscX86
//
// Structure to do a locked 64 bit write /compare without
// a spinlock.
//
typedef struct _TIMER64 { ULONG TimeLow; ULONG TimeHigh1; ULONG TimeHigh2; ULONG Reserved; // for packing sake //
} TIMER64, *PTIMER64;
//
// Since we can't do a 64 bit atomic operation
// without a spinlock, we have to monkey around a bit
// This method comes from the acpi timer code.
//
#define SAFE_READ_TIMER64(WriteLargeInteger, ReadTimer64) \
\ while (TRUE) { \ (WriteLargeInteger).HighPart = (ReadTimer64).TimeHigh2; \ (WriteLargeInteger).LowPart = (ReadTimer64).TimeLow; \ \ if ((ULONG)(WriteLargeInteger).HighPart == (ReadTimer64).TimeHigh1) \ break; \ \ _asm { rep nop }; \ }
#define SAFE_WRITE_TIMER64(WriteTimer64, ReadLargeInteger) \
WriteTimer64.TimeHigh1 = (ReadLargeInteger).HighPart; \ WriteTimer64.TimeLow = (ReadLargeInteger).LowPart; \ WriteTimer64.TimeHigh2 = (ReadLargeInteger).HighPart;
// defined (_X86_) //
#else
// ! defined (_X86_) //
#if defined(_IA64_)
#define ViRdtsc ViRdtscIA64
#else // !_IA64_
//
// Only save the time stamp counter on x86 and ia64 machines
//
#define ViRdtsc ViRdtscNull
#endif // !_IA64_
//
// Alpha or IA64 can do atomic 64 bit read/writes.
//
typedef LARGE_INTEGER TIMER64;
#define SAFE_READ_TIMER64(WriteLargeInteger, ReadTimer64) \
InterlockedExchangePointer( \ &((PVOID) (WriteLargeInteger).QuadPart ), \ (PVOID) (ReadTimer64).QuadPart \ ); #define SAFE_WRITE_TIMER64(WriteTimer64, ReadLargeInteger) \
InterlockedExchangePointer( \ &((PVOID) (WriteTimer64).QuadPart ), \ (PVOID) (ReadLargeInteger).QuadPart \ );
// ! defined (_X86_) //
#endif
/////////////////////////////////////////////////////////////////////
///////////////////////////////////////// Hal verifier global externs
/////////////////////////////////////////////////////////////////////
extern ULONG VfVerifyDma; extern LOGICAL VfVerifyPerformanceCounter; extern LOGICAL ViDoubleBufferDma; extern LOGICAL ViProtectBuffers; extern LOGICAL ViInjectDmaFailures; extern LOGICAL ViSuperDebug; extern LOGICAL ViSufficientlyBootedForPcControl; extern LOGICAL ViSufficientlyBootedForDmaFailure; extern ULONG ViMaxMapRegistersPerAdapter; extern ULONG ViAllocationsFailedDeliberately; extern LARGE_INTEGER ViRequiredTimeSinceBoot; extern CHAR ViDmaVerifierTag[]; extern BOOLEAN ViPenalties[];
extern struct _HAL_VERIFIER_LOCKED_LIST ViAdapterList; extern struct _VF_TIMER_INFORMATION * ViTimerInformation; extern struct _DMA_OPERATIONS ViDmaOperations; extern struct _DMA_OPERATIONS ViLegacyDmaOperations;
/////////////////////////////////////////////////////////////////////
////////////////////////////////// Hal verifier structure definitions
/////////////////////////////////////////////////////////////////////
typedef struct _TIMER_TICK { ULONG Processor; ULONG Reserved; LARGE_INTEGER TimeStampCounter; LARGE_INTEGER PerformanceCounter; LARGE_INTEGER TimerTick; } TIMER_TICK, *PTIMER_TICK;
typedef struct _VF_TIMER_INFORMATION { KDPC RefreshDpc; KTIMER RefreshTimer;
TIMER64 LastPerformanceCounter; TIMER64 UpperBound; TIMER64 LastTickCount; TIMER64 LastKdStartTime; LARGE_INTEGER PerformanceFrequency;
ULONG CountsPerTick; ULONG CurrentCounter; TIMER_TICK SavedTicks[MAX_COUNTERS];
} VF_TIMER_INFORMATION, *PVF_TIMER_INFORMATION;
typedef struct _HAL_VERIFIER_LOCKED_LIST { LIST_ENTRY ListEntry; KSPIN_LOCK SpinLock; } HAL_VERIFIER_LOCKED_LIST, *PHAL_VERIFIER_LOCKED_LIST;
typedef struct _HAL_VERIFIER_BUFFER { USHORT PrePadBytes; USHORT PostPadBytes;
ULONG RealLength; ULONG AdvertisedLength;
PVOID RealStartAddress; PVOID AdvertisedStartAddress;
PHYSICAL_ADDRESS RealLogicalStartAddress;
PVOID AllocatorAddress;
LIST_ENTRY ListEntry; } HAL_VERIFIER_BUFFER, *PHAL_VERIFIER_BUFFER;
typedef struct _MAP_REGISTER { PVOID MappedToSa; ULONG BytesMapped; ULONG Flags; PVOID MapRegisterStart;
} MAP_REGISTER, *PMAP_REGISTER;
typedef struct _MAP_REGISTER_FILE { ULONG Signature; LIST_ENTRY ListEntry; BOOLEAN ContiguousMap; BOOLEAN ScatterGather; ULONG NumberOfMapRegisters; ULONG NumberOfRegistersMapped;
PVOID MapRegisterBaseFromHal; PMDL MapRegisterMdl; PVOID MapRegisterBuffer; PVOID OriginalBuffer; KSPIN_LOCK AllocationLock; MAP_REGISTER MapRegisters[1]; // Rest of the map registers go here
//
} MAP_REGISTER_FILE, *PMAP_REGISTER_FILE;
typedef struct _VF_WAIT_CONTEXT_BLOCK { PVOID RealContext; PVOID RealCallback; PMDL RealMdl; PVOID RealStartVa; ULONG RealLength;
ULONG NumberOfMapRegisters;
struct _ADAPTER_INFORMATION * AdapterInformation;
PSCATTER_GATHER_LIST ScatterGatherList; LIST_ENTRY ListEntry;
PMAP_REGISTER_FILE MapRegisterFile;
} VF_WAIT_CONTEXT_BLOCK, *PVF_WAIT_CONTEXT_BLOCK;
//
// Needed to allocate storage for the MDL is Get/BuildScatterGatherList
// We declare this structure so we will not worry about alignment issues...
//
typedef struct _VF_WAIT_CONTEXT_BLOCK_EX { VF_WAIT_CONTEXT_BLOCK; MDL Mdl; } VF_WAIT_CONTEXT_BLOCK_EX, *PVF_WAIT_CONTEXT_BLOCK_EX;
//
// Store a list of the real dma operations used by an adapter ...
// when the driver allocates the adapter, we're going to replace all of its
// dma operations with ours
//
typedef struct _ADAPTER_INFORMATION { LIST_ENTRY ListEntry; PDMA_ADAPTER DmaAdapter; PDEVICE_OBJECT DeviceObject;
BOOLEAN DeferredRemove; BOOLEAN UseContiguousBuffers; BOOLEAN UseDmaChannel; BOOLEAN Inactive;
PVOID CallingAddress;
PDMA_OPERATIONS RealDmaOperations; HAL_VERIFIER_LOCKED_LIST ScatterGatherLists; HAL_VERIFIER_LOCKED_LIST CommonBuffers; HAL_VERIFIER_LOCKED_LIST MapRegisterFiles;
ULONG MaximumMapRegisters;
ULONG AllocatedMapRegisters; LONG ActiveMapRegisters;
ULONG AllocatedScatterGatherLists; LONG ActiveScatterGatherLists;
ULONG AllocatedCommonBuffers; ULONG FreedCommonBuffers;
ULONG AllocatedAdapterChannels; // Must be 1 or less ! //
ULONG FreedAdapterChannels;
ULONG MappedTransferWithoutFlushing; DEVICE_DESCRIPTION DeviceDescription;
ULONG AdapterChannelMapRegisters;
VF_WAIT_CONTEXT_BLOCK AdapterChannelContextBlock;
PVOID *ContiguousBuffers; // array of contiguous 3-page buffers to be used for double-buffering
ULONG SuccessfulContiguousAllocations; // how many times we allocated contiguous space
ULONG FailedContiguousAllocations; // how many times we failed to allocate contiguous space
KSPIN_LOCK AllocationLock; // lock for our allocator routines
ULONG AllocationStorage[MAX_CONTIGUOUS_MAP_REGISTERS / (sizeof(ULONG) * 8)]; // bitmask for allocator routines
RTL_BITMAP AllocationMap;
ULONG ContiguousMapRegisters; // allocated among ContiguousBufers
ULONG NonContiguousMapRegisters; // allocated from non-Paged Pool
} ADAPTER_INFORMATION, *PADAPTER_INFORMATION;
/////////////////////////////////////////////////////////////////////
////////////////////////////////// Hal verifier function declarations
/////////////////////////////////////////////////////////////////////
//==========================
// Declare our dma apis here
// if NO_LEGACY_DRIVERS *is*
// enabled
// =========================
#if defined(NO_LEGACY_DRIVERS)
VOID VfPutDmaAdapter( struct _DMA_ADAPTER * DmaAdapter );
PVOID VfAllocateCommonBuffer( IN struct _DMA_ADAPTER * DmaAdapter, IN ULONG Length, OUT PPHYSICAL_ADDRESS LogicalAddress, IN BOOLEAN CacheEnabled );
VOID VfFreeCommonBuffer( IN struct _DMA_ADAPTER * DmaAdapter, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress, IN BOOLEAN CacheEnabled );
NTSTATUS VfAllocateAdapterChannel( IN struct _DMA_ADAPTER * DmaAdapter, IN PDEVICE_OBJECT DeviceObject, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine, IN PVOID Context );
PHYSICAL_ADDRESS VfMapTransfer( IN struct _DMA_ADAPTER * DmaAdapter, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN OUT PULONG Length, IN BOOLEAN WriteToDevice );
BOOLEAN VfFlushAdapterBuffers( IN struct _DMA_ADAPTER * DmaAdapter, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice );
VOID VfFreeAdapterChannel( IN struct _DMA_ADAPTER * DmaAdapter );
VOID VfFreeMapRegisters( IN struct _DMA_ADAPTER * DmaAdapter, PVOID MapRegisterBase, ULONG NumberOfMapRegisters );
ULONG VfGetDmaAlignment( IN struct _DMA_ADAPTER * DmaAdapter );
ULONG VfReadDmaCounter( IN struct _DMA_ADAPTER * DmaAdapter );
NTSTATUS VfGetScatterGatherList ( IN struct _DMA_ADAPTER * DmaAdapter, IN PDEVICE_OBJECT DeviceObject, IN PMDL Mdl, IN PVOID CurrentVa, IN ULONG Length, IN PVOID ExecutionRoutine, IN PVOID Context, IN BOOLEAN WriteToDevice );
VOID VfPutScatterGatherList( IN struct _DMA_ADAPTER * DmaAdapter, IN struct _SCATTER_GATHER_LIST * ScatterGather, IN BOOLEAN WriteToDevice );
#endif
// =====================
// New verified dma apis
// =====================
NTSTATUS VfCalculateScatterGatherListSize( IN PDMA_ADAPTER DmaAdapter, IN OPTIONAL PMDL Mdl, IN PVOID CurrentVa, IN ULONG Length, OUT PULONG ScatterGatherListSize, OUT OPTIONAL PULONG pNumberOfMapRegisters );
NTSTATUS VfBuildScatterGatherList( 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, IN PVOID ScatterGatherBuffer, IN ULONG ScatterGatherLength );
NTSTATUS VfBuildMdlFromScatterGatherList( IN PDMA_ADAPTER DmaAdapter, IN PSCATTER_GATHER_LIST ScatterGather, IN PMDL OriginalMdl, OUT PMDL *TargetMdl );
IO_ALLOCATION_ACTION VfAdapterCallback( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context );
VOID VfScatterGatherCallback( IN struct _DEVICE_OBJECT *DeviceObject, IN struct _IRP *Irp, IN struct _SCATTER_GATHER_LIST * ScatterGather, IN PVOID Context );
// =================================
// Hook for HalpAllocateMapRegisters
// =================================
NTSTATUS VfHalAllocateMapRegisters( IN PADAPTER_OBJECT DmaAdapter, IN ULONG NumberOfMapRegisters, IN ULONG BaseAddressCount, OUT PMAP_REGISTER_ENTRY MapRegisterArray );
// ==============================
// Hal verifier internal routines
// ==============================
PADAPTER_INFORMATION ViHookDmaAdapter( IN PDMA_ADAPTER DmaAdapter, IN PDEVICE_DESCRIPTION DeviceDescription, IN ULONG NumberOfMapRegisters );
VOID ViReleaseDmaAdapter( IN PADAPTER_INFORMATION AdapterInformation );
PADAPTER_INFORMATION ViGetAdapterInformation( IN PDMA_ADAPTER DmaAdapter );
PVOID ViGetRealDmaOperation( IN PDMA_ADAPTER DmaAdapter, IN ULONG AdapterInformationOffset );
LARGE_INTEGER ViRdtsc( VOID );
VOID VfInitializeTimerInformation( VOID );
VOID ViRefreshCallback( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
LOGICAL VfInjectDmaFailure ( VOID );
// =================================================
// Hal verfier special routines to track allocations
// =================================================
PVOID ViSpecialAllocateCommonBuffer( IN PALLOCATE_COMMON_BUFFER AllocateCommonBuffer, IN PADAPTER_INFORMATION AdapterInformation, IN PVOID CallingAddress, IN ULONG Length, IN OUT PPHYSICAL_ADDRESS LogicalAddress, IN LOGICAL CacheEnabled ); LOGICAL ViSpecialFreeCommonBuffer( IN PFREE_COMMON_BUFFER FreeCommonBuffer, IN PADAPTER_INFORMATION AdapterInformation, IN PVOID CommonBuffer, LOGICAL CacheEnabled );
// ===================================================
// Hal verfier special routines to do double buffering
// ===================================================
PMAP_REGISTER_FILE ViAllocateMapRegisterFile( IN PADAPTER_INFORMATION AdapterInformation, IN ULONG NumberOfMapRegisters ); LOGICAL ViFreeMapRegisterFile( IN PADAPTER_INFORMATION AdapterInformation, IN PMAP_REGISTER_FILE MapRegisterFile );
ULONG ViMapDoubleBuffer( IN PMAP_REGISTER_FILE MapRegisterFile, IN OUT PMDL Mdl, IN OUT PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice );
LOGICAL ViFlushDoubleBuffer( IN PMAP_REGISTER_FILE MapRegisterFile, IN PMDL Mdl, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice );
LOGICAL ViAllocateMapRegistersFromFile( IN PMAP_REGISTER_FILE MapRegisterFile, IN PVOID CurrentSa, IN ULONG Length, IN BOOLEAN WriteToDevice, OUT PULONG MapRegisterNumber );
LOGICAL ViFreeMapRegistersToFile( IN PMAP_REGISTER_FILE MapRegisterFile, IN PVOID CurrentSa, IN ULONG Length );
PMAP_REGISTER ViFindMappedRegisterInFile( IN PMAP_REGISTER_FILE MapRegisterFile, IN PVOID CurrentSa, OUT PULONG MapRegisterNumber OPTIONAL );
LOGICAL ViSwap(IN OUT PVOID * MapRegisterBase, IN OUT PMDL * Mdl, IN OUT PVOID * CurrentVa );
VOID ViCheckAdapterBuffers( IN PADAPTER_INFORMATION AdapterInformation );
VOID ViTagBuffer( IN PVOID AdvertisedBuffer, IN ULONG AdvertisedLength, IN USHORT WhereToTag );
VOID ViCheckTag( IN PVOID AdvertisedBuffer, IN ULONG AdvertisedLength, IN BOOLEAN RemoveTag, IN USHORT WhereToCheck );
VOID ViInitializePadding( IN PVOID RealBufferStart, IN ULONG RealBufferLength, IN PVOID AdvertisedBufferStart, OPTIONAL IN ULONG AdvertisedBufferLength OPTIONAL );
VOID ViCheckPadding( IN PVOID RealBufferStart, IN ULONG RealBufferLength, IN PVOID AdvertisedBufferStart, OPTIONAL IN ULONG AdvertisedBufferLength OPTIONAL );
PULONG_PTR ViHasBufferBeenTouched( IN PVOID Address, IN ULONG_PTR Length, IN UCHAR ExpectedFillChar );
VOID VfAssert( IN LOGICAL Condition, IN ULONG Code, IN OUT PULONG Enable );
VOID ViMapTransferHelper( IN PMDL Mdl, IN PVOID CurrentVa, IN ULONG TransferLength, IN PULONG PageFrame, IN OUT PULONG Length );
VOID ViCommonBufferCalculatePadding( IN ULONG Length, OUT PULONG PrePadding, OUT PULONG PostPadding );
VOID ViAllocateContiguousMemory ( IN OUT PADAPTER_INFORMATION AdapterInformation );
PVOID ViAllocateFromContiguousMemory ( IN OUT PADAPTER_INFORMATION AdapterInformation, IN ULONG HintIndex );
LOGICAL ViFreeToContiguousMemory ( IN OUT PADAPTER_INFORMATION AdapterInformation, IN PVOID Address, IN ULONG HintIndex );
LOGICAL VfIsPCIBus ( IN PDEVICE_OBJECT PhysicalDeviceObject );
PDEVICE_OBJECT VfGetPDO ( IN PDEVICE_OBJECT DeviceObject );
VOID ViCopyBackModifiedBuffer ( OUT PUCHAR Dest, IN PUCHAR Source, IN PUCHAR Original, IN SIZE_T Length );
/////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// Hal verifier macros
/////////////////////////////////////////////////////////////////////
//
// This is a kind of long macro but it lets us decide what to
// do on certain kinds of errors. For instance, if we know
// we are going to hit something once, we might set it to
// HVC_WARN. Or if we know we will hit it 1000 times, but don't
// want to take the code out completely (especially if we're doing
// it on the fly), we can set it to HVC_IGNORE
//
#define VF_ASSERT(condition, code, message) \
{ \ static ULONG enable = (ULONG) -1; \ if (enable == (ULONG) -1) \ enable = ViPenalties[code]; \ if (!(condition) && enable) \ { \ DbgPrint("* * * * * * * * HAL Verifier Detected Violation * * * * * * * *\n");\ DbgPrint("* *\n"); \ DbgPrint("* * VF: "); \ DbgPrint message; \ DbgPrint("\n"); \ DbgPrint("* *\n"); \ DbgPrint("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");\ \ VfAssert(condition, code, &enable); \ } \ }
//
// Old favorite:
//
// Control macro (used like a for loop) which iterates over all entries in
// a standard doubly linked list. Head is the list head and the entries
// are of type Type. A member called ListEntry is assumed to be the
// LIST_ENTRY structure linking the entries together. Current contains a
// pointer to each entry in turn.
//
#define FOR_ALL_IN_LIST(Type, Head, Current) \
for((Current) = CONTAINING_RECORD((Head)->Flink, Type, ListEntry); \ (Head) != &(Current)->ListEntry; \ (Current) = CONTAINING_RECORD((Current)->ListEntry.Flink, \ Type, \ ListEntry) \ )
#ifndef MIN
#define MIN(a,b) ( ( (ULONG) (a)<(ULONG) (b))?(a):(b) )
#endif
#define NOP
#define VF_INITIALIZE_LOCKED_LIST(LockedList) \
KeInitializeSpinLock(&(LockedList)->SpinLock); \ InitializeListHead(&(LockedList)->ListEntry);
#define VF_LOCK_LIST(ListToLock, OldIrql) \
KeAcquireSpinLock(&(ListToLock)->SpinLock, &OldIrql)
#define VF_UNLOCK_LIST(ListToUnlock, OldIrql) \
KeReleaseSpinLock(&(ListToUnlock)->SpinLock, OldIrql)
#define VF_IS_LOCKED_LIST_EMPTY(LockedList) \
IsListEmpty( &(LockedList)->ListEntry )
#define VF_ADD_TO_LOCKED_LIST(LockedList, AddMe) \
ExInterlockedInsertHeadList( \ &(LockedList)->ListEntry, \ &(AddMe)->ListEntry, \ &(LockedList)->SpinLock )
#define VF_REMOVE_FROM_LOCKED_LIST(LockedList, RemoveMe) \
{ \ KIRQL OldIrql; \ VF_LOCK_LIST((LockedList), OldIrql); \ RemoveEntryList(&(RemoveMe)->ListEntry); \ VF_UNLOCK_LIST((LockedList), OldIrql); \ }
#define VF_REMOVE_FROM_LOCKED_LIST_DONT_LOCK(LockedList, RemoveMe) \
RemoveEntryList(&(RemoveMe)->ListEntry);
//
// This is a bit of a hack so that reference counting for adapters will work.
// If the device uses a dma channel, the HAL wants to keep it around.
// There is a bit of funky logic that goes on to determine whether
// a device uses an adapter channel so I've included it here, free of
// charge.
//
#define VF_DOES_DEVICE_USE_DMA_CHANNEL(deviceDescription) \
( \ ( (deviceDescription)->InterfaceType == Isa && \ (deviceDescription)->DmaChannel < 8 ) || \ ! (deviceDescription)->Master )
#define VF_DOES_DEVICE_REQUIRE_CONTIGUOUS_BUFFERS(deviceDescription) \
( !(deviceDescription)->Master || ! (deviceDescription)->ScatterGather )
#define DMA_OFFSET(DmaOperationsField) \
FIELD_OFFSET(DMA_OPERATIONS, DmaOperationsField)
#define DMA_INDEX(DmaOperations, Offset) \
(PVOID) \ *( (PVOID *) \ ( ( (PUCHAR) (DmaOperations) ) + \ (Offset) ) )
#define SIGN_MAP_REGISTER_FILE(MapRegisterFile) \
(MapRegisterFile)->Signature = MRF_SIGNATURE;
#define VALIDATE_MAP_REGISTER_FILE_SIGNATURE(MapRegisterFile ) \
((MapRegisterFile) && (MapRegisterFile)->Signature == MRF_SIGNATURE )
//
// System dependent way to get the caller's address
//
#if defined(_X86_)
#define GET_CALLING_ADDRESS(CallingAddress) \
{ \ PVOID callersCaller; \ RtlGetCallersAddress(&CallingAddress, &callersCaller); \ } #else // ! defined(_X86_) //
#define GET_CALLING_ADDRESS(CallingAddress) \
CallingAddress = (PVOID)_ReturnAddress(); #endif // ! defined(_X86_)
//
// From a map register file, map register number and the corresponding system address,
// return the corresponding mapped address in system space.
//
#define MAP_REGISTER_SYSTEM_ADDRESS(MapRegisterFile, DriverCurrentSa, MapRegisterNumber) \
(PUCHAR) (MapRegisterFile)->MapRegisterBuffer + \ ( (MapRegisterNumber) << PAGE_SHIFT ) + \ BYTE_OFFSET(DriverCurrentSa)
//
// From a map register file's OriginalBuffer, map register number and system address
// returns the address in the original buffer. Used to do a 3-way merge between
// the driver's buffer, verifier's buffer (passed to the hardware) and the original
// buffer
//
#define ORIGINAL_BUFFER_SYSTEM_ADDRESS(MapRegisterFile, DriverCurrentSa, MapRegisterNumber) \
(PUCHAR) (MapRegisterFile)->OriginalBuffer + \ ( (MapRegisterNumber) << PAGE_SHIFT ) + \ BYTE_OFFSET(DriverCurrentSa)
//
// From a map register file, map register number and the corresponding system address,
// return the corresponding mapped address as an index into the map register file's
// MDL (i.e virtual address).
//
#define MAP_REGISTER_VIRTUAL_ADDRESS(MapRegisterFile, DriverCurrentSa, MapRegisterNumber) \
(PUCHAR) MmGetMdlVirtualAddress((MapRegisterFile)->MapRegisterMdl) + \ ( (MapRegisterNumber) << PAGE_SHIFT ) + \ BYTE_OFFSET(DriverCurrentSa)
/////////////////////////////////////////////////////////////////////
//////////////////////////// Hal verifier inline function definitions
/////////////////////////////////////////////////////////////////////
//
// Since so many people don't raise the irql when they put the dma adapter,
// just warn them.
//
__inline VOID VF_ASSERT_SPECIAL_IRQL(IN KIRQL Irql) {
KIRQL currentIrql = KeGetCurrentIrql(); VF_ASSERT( currentIrql == Irql, HV_BAD_IRQL_JUST_WARN, ("**** Bad IRQL -- needed %x, got %x ****", (ULONG) Irql, (ULONG) currentIrql) ); } // VF_ASSERT_IRQL //
__inline VOID VF_ASSERT_IRQL(IN KIRQL Irql) { KIRQL currentIrql = KeGetCurrentIrql(); VF_ASSERT( currentIrql == Irql, HV_BAD_IRQL, ("**** Bad IRQL -- needed %x, got %x ****", (ULONG) Irql, (ULONG) currentIrql) ); } // VF_ASSERT_IRQL //
__inline VOID VF_ASSERT_MAX_IRQL(IN KIRQL MaxIrql) { KIRQL currentIrql = KeGetCurrentIrql(); VF_ASSERT( currentIrql <= MaxIrql, HV_BAD_IRQL, ("**** Bad IRQL -- needed %x or less, got %x ****", (ULONG) MaxIrql, (ULONG) currentIrql) ); }
// =========================================
// Inlined functions to help with accounting
// =========================================
__inline VOID ADD_MAP_REGISTERS( IN PADAPTER_INFORMATION AdapterInformation, IN ULONG NumberOfMapRegisters, IN BOOLEAN ScatterGather ) { ULONG activeMapRegisters = InterlockedExchangeAdd( &AdapterInformation->ActiveMapRegisters, NumberOfMapRegisters ) + NumberOfMapRegisters; InterlockedExchangeAdd((PLONG)(&AdapterInformation->AllocatedMapRegisters), NumberOfMapRegisters); VF_ASSERT( NumberOfMapRegisters <= AdapterInformation->MaximumMapRegisters, HV_TOO_MANY_MAP_REGISTERS, ( "Allocating too many map registers at a time: %x (max %x)", NumberOfMapRegisters, AdapterInformation->MaximumMapRegisters ) ); if (! ScatterGather ) { VF_ASSERT( activeMapRegisters <= AdapterInformation->MaximumMapRegisters, HV_OUT_OF_MAP_REGISTERS, ( "Allocated too many map registers : %x (max %x)", activeMapRegisters, AdapterInformation->MaximumMapRegisters ) ); }
} // ADD_MAP_REGISTERS //
__inline VOID SUBTRACT_MAP_REGISTERS( IN PADAPTER_INFORMATION AdapterInformation, IN ULONG NumberOfMapRegisters ) { LONG activeMapRegisters = InterlockedExchangeAdd( &AdapterInformation->ActiveMapRegisters, -((LONG) NumberOfMapRegisters) ) - NumberOfMapRegisters; VF_ASSERT( activeMapRegisters >= 0, HV_FREED_TOO_MANY_MAP_REGISTERS, ( "Freed too many map registers: %x", activeMapRegisters ) ); InterlockedExchange((PLONG)(&AdapterInformation->MappedTransferWithoutFlushing), 0);
} // SUBTRACT_MAP_REGISTERS //
__inline VOID INCREMENT_COMMON_BUFFERS( IN PADAPTER_INFORMATION AdapterInformation ) { InterlockedIncrement((PLONG)(&AdapterInformation->AllocatedCommonBuffers) );
} // INCREMENT_COMMON_BUFFERS //
__inline VOID DECREMENT_COMMON_BUFFERS( IN PADAPTER_INFORMATION AdapterInformation ) { ULONG commonBuffersFreed = (ULONG) InterlockedIncrement( (PLONG)(&AdapterInformation->FreedCommonBuffers) ); VF_ASSERT( commonBuffersFreed <= AdapterInformation->AllocatedCommonBuffers, HV_FREED_TOO_MANY_COMMON_BUFFERS, ("Freed too many common buffers") ); } // DECREMENT_COMMON_BUFFERS //
__inline VOID INCREASE_MAPPED_TRANSFER_BYTE_COUNT( IN PADAPTER_INFORMATION AdapterInformation, IN ULONG Length ) { ULONG mappedTransferCount; ULONG maxMappedTransfer;
maxMappedTransfer = AdapterInformation->ActiveMapRegisters << PAGE_SHIFT;
mappedTransferCount = InterlockedExchangeAdd( (PLONG)(&AdapterInformation->MappedTransferWithoutFlushing), (LONG) Length ) + Length;
VF_ASSERT( mappedTransferCount <= maxMappedTransfer, HV_DID_NOT_FLUSH_ADAPTER_BUFFERS, ("Driver did not flush adapter buffers -- bytes mapped: %x (%x max)", mappedTransferCount, maxMappedTransfer )); } // INCREASE_MAPPED_TRANSFER_BYTE_COUNT //
__inline VOID DECREASE_MAPPED_TRANSFER_BYTE_COUNT( IN PADAPTER_INFORMATION AdapterInformation, IN ULONG Length ) { UNREFERENCED_PARAMETER (Length);
InterlockedExchange( (PLONG)(&AdapterInformation->MappedTransferWithoutFlushing), 0);
} // DECREASE_MAPPED_TRANSFER_BYTE_COUNT //
__inline VOID INCREMENT_ADAPTER_CHANNELS( IN PADAPTER_INFORMATION AdapterInformation ) {
ULONG allocatedAdapterChannels = (ULONG) InterlockedIncrement( (PLONG)(&AdapterInformation->AllocatedAdapterChannels) );
VF_ASSERT( allocatedAdapterChannels == AdapterInformation->FreedAdapterChannels + 1, HV_TOO_MANY_ADAPTER_CHANNELS, ( "Driver has allocated too many simultaneous adapter channels" )); } // INCREMENT_ADAPTER_CHANNELS //
__inline VOID DECREMENT_ADAPTER_CHANNELS( IN PADAPTER_INFORMATION AdapterInformation ) { ULONG adapterChannelsFreed = (ULONG) InterlockedIncrement( (PLONG)(&AdapterInformation->FreedAdapterChannels) ); VF_ASSERT( adapterChannelsFreed == AdapterInformation->AllocatedAdapterChannels, HV_FREED_TOO_MANY_ADAPTER_CHANNELS, ( "Driver has freed too many simultaneous adapter channels" )); } // DECREMENT_ADAPTER_CHANNELS //
_inline VOID INCREMENT_SCATTER_GATHER_LISTS( IN PADAPTER_INFORMATION AdapterInformation ) { InterlockedIncrement( (PLONG)(&AdapterInformation->AllocatedScatterGatherLists) ); InterlockedIncrement( &AdapterInformation->ActiveScatterGatherLists);
} // INCREMENT_SCATTER_GATHER_LISTS //
__inline VOID DECREMENT_SCATTER_GATHER_LISTS ( IN PADAPTER_INFORMATION AdapterInformation ) { LONG activeScatterGatherLists = InterlockedDecrement( &AdapterInformation->ActiveScatterGatherLists );
VF_ASSERT( activeScatterGatherLists >= 0, HV_FREED_TOO_MANY_SCATTER_GATHER_LISTS, ( "Driver has freed too many scatter gather lists %x allocated, %x freed", AdapterInformation->AllocatedScatterGatherLists, AdapterInformation->AllocatedScatterGatherLists - activeScatterGatherLists) );
} // DECREMENT_SCATTER_GATHER_LISTS //
__inline VOID VERIFY_BUFFER_LOCKED( IN PMDL Mdl ) { VF_ASSERT( MmAreMdlPagesLocked(Mdl), HV_DMA_BUFFER_NOT_LOCKED, ( "DMA Pages Not Locked! MDL %p for DMA not locked", Mdl) );
} // VERIFY_BUFFER_LOCKED //
__inline PHAL_VERIFIER_BUFFER VF_FIND_BUFFER ( IN PHAL_VERIFIER_LOCKED_LIST LockedList, IN PVOID AdvertisedStartAddress ) { PHAL_VERIFIER_BUFFER verifierBuffer; KIRQL OldIrql;
VF_LOCK_LIST(LockedList, OldIrql); FOR_ALL_IN_LIST(HAL_VERIFIER_BUFFER, &LockedList->ListEntry, verifierBuffer ) {
if ((PUCHAR) verifierBuffer->RealStartAddress + verifierBuffer->PrePadBytes == AdvertisedStartAddress) { VF_UNLOCK_LIST(LockedList, OldIrql); return verifierBuffer; } } VF_UNLOCK_LIST(LockedList, OldIrql); return NULL; } // VF_FIND_BUFFER //
__inline PADAPTER_INFORMATION VF_FIND_DEVICE_INFORMATION( IN PDEVICE_OBJECT DeviceObject ) { PADAPTER_INFORMATION adapterInformation; KIRQL OldIrql;
VF_LOCK_LIST(&ViAdapterList, OldIrql); FOR_ALL_IN_LIST(ADAPTER_INFORMATION, &ViAdapterList.ListEntry, adapterInformation) {
if (adapterInformation->DeviceObject == DeviceObject) { VF_UNLOCK_LIST(&ViAdapterList, OldIrql); return adapterInformation; } }
VF_UNLOCK_LIST(&ViAdapterList, OldIrql); return NULL; } // VF_FIND_DEVICE_INFORMATION //
__inline PADAPTER_INFORMATION VF_FIND_INACTIVE_ADAPTER( IN PDEVICE_OBJECT DeviceObject ) { PADAPTER_INFORMATION adapterInformation; KIRQL OldIrql;
VF_LOCK_LIST(&ViAdapterList, OldIrql); FOR_ALL_IN_LIST(ADAPTER_INFORMATION, &ViAdapterList.ListEntry, adapterInformation) {
if (adapterInformation->DeviceObject == DeviceObject && (adapterInformation->Inactive == TRUE || adapterInformation->DeferredRemove == TRUE)) { VF_UNLOCK_LIST(&ViAdapterList, OldIrql); return adapterInformation; } }
VF_UNLOCK_LIST(&ViAdapterList, OldIrql); return NULL; } // VF_FIND_INACTIVE_ADAPTER //
__inline VOID VF_MARK_FOR_DEFERRED_REMOVE( IN PDEVICE_OBJECT DeviceObject ) { PADAPTER_INFORMATION adapterInformation; KIRQL OldIrql;
VF_LOCK_LIST(&ViAdapterList, OldIrql); FOR_ALL_IN_LIST(ADAPTER_INFORMATION, &ViAdapterList.ListEntry, adapterInformation) {
if (adapterInformation->DeviceObject == DeviceObject) { adapterInformation->DeferredRemove = TRUE; } }
VF_UNLOCK_LIST(&ViAdapterList, OldIrql); return ; } // VF_MARK_FOR_DEFERRED_REMOVE //
__inline VOID VF_ASSERT_MAP_REGISTERS_CAN_BE_FREED( IN PADAPTER_INFORMATION AdapterInformation, IN PMAP_REGISTER_FILE MapRegisterFile ) { UNREFERENCED_PARAMETER (AdapterInformation);
VF_ASSERT( MapRegisterFile->NumberOfRegistersMapped, HV_CANNOT_FREE_MAP_REGISTERS, ( "Cannot free map registers -- %x registers still mapped", MapRegisterFile->NumberOfMapRegisters) ); } // VF_ASSERT_MAP_REGISTERS_CAN_BE_FREED
|