// Public nt-lite DMA declarations. #pragma once #include #include #include struct DEVICE_OBJECT; struct PROCESS; typedef struct IO_DMA_ADAPTER IO_DMA_ADAPTER; typedef struct IO_DMA_BUFFER IO_DMA_BUFFER; typedef struct IO_DMA_MAPPING IO_DMA_MAPPING; typedef struct MM_PINNED_MEMORY MM_PINNED_MEMORY; typedef enum IO_DMA_DIRECTION { IoDmaToDevice = 1, IoDmaFromDevice, IoDmaBidirectional } IO_DMA_DIRECTION; // Fails a streaming mapping instead of allocating a bounce buffer. #define IO_DMA_MAP_NO_BOUNCE 0x00000001u // Describes immutable constraints shared by one device adapter. Address, // alignment, and boundary limits apply to common buffers. Segment limits apply // to streaming mappings. Zero selects the unconstrained default for each field. typedef struct IO_DMA_REQUIREMENTS { uint64_t MaximumDeviceAddress; size_t Alignment; size_t Boundary; size_t MaximumSegmentLength; uint32_t MaximumSegments; } IO_DMA_REQUIREMENTS; // Describes one device-visible span in a streaming mapping. typedef struct IO_DMA_SEGMENT { uint64_t DeviceAddress; size_t Length; } IO_DMA_SEGMENT; // Reports cumulative activity and live ownership for validation. typedef struct IO_DMA_STATS { uint64_t AdaptersCreated; uint64_t AdaptersDestroyed; uint64_t AdaptersInUse; uint64_t CommonBuffersAllocated; uint64_t CommonBuffersFreed; uint64_t CommonBuffersInUse; uint64_t CommonBufferBytesInUse; uint64_t PinnedKernelRanges; uint64_t PinnedUserRanges; uint64_t PinnedRangesReleased; uint64_t PinnedRangesInUse; uint64_t PinnedPagesInUse; uint64_t StreamingMappings; uint64_t StreamingMappingsUnmapped; uint64_t StreamingMappingsInUse; uint64_t DirectMappings; uint64_t BounceMappings; uint64_t BounceBytesCopiedToDevice; uint64_t BounceBytesCopiedToCpu; uint64_t FailedAllocations; uint64_t FailedMappings; } IO_DMA_STATS; // Driver-visible DMA services. Device addresses are intentionally distinct // from physical addresses even while the first implementation maps them one to // one on x86-64. typedef struct NTL_DDK_DMA { // Returns the one adapter and requirement set owned by a device object. KSTATUS (*GetAdapter)(struct DEVICE_OBJECT* device, const IO_DMA_REQUIREMENTS* requirements, IO_DMA_ADAPTER** outAdapter); // Releases one caller-owned adapter reference. void (*PutAdapter)(IO_DMA_ADAPTER* adapter); // Allocates coherent memory with stable CPU and base device addresses. The // caller must quiesce every device reference before releasing the buffer. KSTATUS (*AllocateCommonBuffer)(IO_DMA_ADAPTER* adapter, size_t size, size_t alignment, IO_DMA_BUFFER** outBuffer); // Releases a coherent common buffer. void (*FreeCommonBuffer)(IO_DMA_BUFFER* buffer); // Returns the stable CPU address of a common buffer. void* (*GetCommonBufferAddress)(const IO_DMA_BUFFER* buffer); // Returns the stable device address of a common buffer. uint64_t (*GetCommonBufferDeviceAddress)(const IO_DMA_BUFFER* buffer); // Returns the caller-requested size of a common buffer. size_t (*GetCommonBufferSize)(const IO_DMA_BUFFER* buffer); // Stabilizes a kernel range for one or more streaming mappings. Pinning // preserves the pages, but does not transfer ownership to a device. KSTATUS (*PinKernelMemory)(void* address, size_t size, IO_DMA_DIRECTION direction, MM_PINNED_MEMORY** outMemory); // Stabilizes a process-owned user range for one or more mappings. The // descriptor retains the process and range until the final unpin. KSTATUS (*PinUserMemory)(struct PROCESS* process, void* address, size_t size, IO_DMA_DIRECTION direction, MM_PINNED_MEMORY** outMemory); // Releases one pinned-memory reference after all mappings leave. void (*UnpinMemory)(MM_PINNED_MEMORY* memory); // Maps a pinned subrange and creates a constrained segment list. A new // mapping begins CPU-owned and requires external operation serialization. KSTATUS (*MapPinnedMemory)(IO_DMA_ADAPTER* adapter, MM_PINNED_MEMORY* memory, size_t offset, size_t length, IO_DMA_DIRECTION direction, uint32_t flags, IO_DMA_MAPPING** outMapping); // Releases a mapping and performs a final receive-side bounce copy only // when ownership was transferred to the device and not returned to the CPU. void (*UnmapMemory)(IO_DMA_MAPPING* mapping); // Transfers mapping ownership from the CPU to the device. Streaming DMA // must not begin before this operation succeeds. KSTATUS (*SynchronizeForDevice)(IO_DMA_MAPPING* mapping); // Transfers mapping ownership from the device to the CPU. CPU readers must // not consume receive data before this operation succeeds. KSTATUS (*SynchronizeForCpu)(IO_DMA_MAPPING* mapping); // Returns the immutable segment count owned by a mapping. uint32_t (*GetSegmentCount)(const IO_DMA_MAPPING* mapping); // Returns the immutable segment array owned by a mapping. const IO_DMA_SEGMENT* (*GetSegments)(const IO_DMA_MAPPING* mapping); // Copies current DMA counters into caller-owned storage. void (*QueryStats)(IO_DMA_STATS* outStats); } NTL_DDK_DMA;