summaryrefslogtreecommitdiff
path: root/general/HalExtensionSample/HalExtSampleDma
diff options
context:
space:
mode:
Diffstat (limited to 'general/HalExtensionSample/HalExtSampleDma')
-rw-r--r--general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.c1253
-rw-r--r--general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.def2
-rw-r--r--general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.rc10
-rw-r--r--general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.vcxproj126
-rw-r--r--general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.vcxproj.Filters30
-rw-r--r--general/HalExtensionSample/HalExtSampleDma/HalExtSampleDmaReadme.txt139
6 files changed, 1560 insertions, 0 deletions
diff --git a/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.c b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.c
new file mode 100644
index 00000000..3aade318
--- /dev/null
+++ b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.c
@@ -0,0 +1,1253 @@
+/*++
+
+Copyright (c) 2011 Microsoft Corporation
+
+Module Name:
+
+ HalExtSampleDma.c
+
+Abstract:
+
+ This file implements a HAL Extension Module for the fictitious chDMA
+ controller.
+
+Author:
+
+ Cody Hartwig (chartwig) 9-Jun-2011
+
+--*/
+
+//
+// --------------------------------------------------------------------Includes
+//
+
+#include <nthalext.h>
+
+//
+// ---------------------------------------------------------------- Definitions
+//
+
+//
+// Disable warnings of features used by the standard headers
+//
+// Disable warning C4214: nonstandard extension used : bit field types other than int
+// Disable warning C4201: nonstandard extension used : nameless struct/union
+// Disable warning C4115: named type definition in parentheses
+// Disable warning C4127: conditional expression is constant
+// Disable warning C4200: zero-sized array in struct/union
+//
+
+#pragma warning(disable:4214 4201 4115 4127 4200)
+
+//
+// Define register set size.
+//
+
+#define CH_DMA_REGISTER_SIZE (0x210)
+
+//
+// Define maximums.
+//
+
+#define CH_DMA_MAX_REQUEST_LINES (32)
+#define CH_DMA_MAX_CHANNELS (32)
+
+#define CONFIGURE_ADD_REQ_CONFIG (0x80000000)
+
+//
+// Define register offsets.
+//
+
+#define CH_DMA_CONTROL (0x00)
+#define CH_DMA_STATUS (0x04)
+#define CH_DMA_INTERRUPT_MASK (0x08)
+
+#define CH_DMA_CHAN_CONTROL (0x00)
+#define CH_DMA_CHAN_MEM_PTR (0x04)
+#define CH_DMA_CHAN_DEV_PTR (0x08)
+#define CH_DMA_CHAN_STATUS (0x1c)
+
+//
+// Define device-side bus widths.
+//
+
+#define CH_DMA_WIDTH_8_BIT (0)
+#define CH_DMA_WIDTH_16_BIT (1)
+#define CH_DMA_WIDTH_32_BIT (2)
+
+//
+// Define transfer burst sizes.
+//
+
+#define CH_DMA_BURST_1_WORD (0)
+#define CH_DMA_BURST_2_WORD (1)
+#define CH_DMA_BURST_4_WORD (2)
+#define CH_DMA_BURST_8_WORD (3)
+
+//
+// Define transfer directions.
+//
+
+#define CH_DMA_DEVICE_WRITE (0)
+#define CH_DMA_DEVICE_READ (1)
+
+//
+// ------------------------------------------------------ Data Type Definitions
+//
+
+#pragma pack(push, 1)
+
+//
+// Register Definitions.
+//
+
+typedef struct _CH_DMA_CONTROL_REGISTER {
+ union {
+ struct {
+ ULONG ControllerEnable:1;
+ ULONG Reserved:31;
+ };
+ ULONG AsUlong;
+ };
+} CH_DMA_CONTROL_REGISTER, *PCH_DMA_CONTROL_REGISTER;
+
+typedef struct _CH_DMA_CHAN_CONTROL_REGISTER {
+ union {
+ struct {
+ ULONG ChannelEnable:1;
+ ULONG InterruptEnable:1;
+ ULONG DeviceWidth:2;
+ ULONG BurstSize:2;
+ ULONG FlowControl:1;
+ ULONG Loop:1;
+ ULONG RequestLine:5;
+ ULONG ReadFromDevice:1;
+ ULONG Reserved:2;
+ ULONG Length:16;
+ };
+ ULONG AsUlong;
+ };
+} CH_DMA_CHAN_CONTROL_REGISTER, *PCH_DMA_CHAN_CONTROL_REGISTER;
+
+typedef struct _CH_DMA_CHAN_STATUS_REGISTER {
+ union {
+ struct {
+ ULONG Busy:1;
+ ULONG Reserved:15;
+ ULONG BytesTransferred:16;
+ };
+ ULONG AsUlong;
+ };
+} CH_DMA_CHAN_STATUS_REGISTER, *PCH_DMA_CHAN_STATUS_REGISTER;
+
+//
+// CSRT resource descriptor types for chDMA.
+//
+
+typedef struct _CH_DMA_ADD_REQ_LINE_CONFIG {
+ ULONG RequestLine;
+ CH_DMA_CHAN_CONTROL_REGISTER Ctrl;
+} CH_DMA_ADD_REQ_LINE_CONFIG, *PCH_DMA_ADD_REQ_LINE_CONFIG;
+
+typedef struct _RD_DMA_CONTROLLER {
+ CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
+ ULONGLONG BasePhysicalAddress;
+ ULONG ChannelCount;
+ ULONG MinimumRequestLine;
+ ULONG MaximumRequestLine;
+ ULONG InterruptGsi;
+ BOOLEAN CacheCoherent;
+ ULONG ReqLineConfigCount;
+ CH_DMA_ADD_REQ_LINE_CONFIG ReqLineConfigs[ANYSIZE_ARRAY];
+} RD_DMA_CONTROLLER, *PRD_DMA_CONTROLLER;
+
+//
+// Resource description matching chDMA controller described in chdmaReadme.txt:
+//
+// CH_DMA_CHAN_CONTROL_REGISTER UartControl;
+// UartControl.AsUlong = 0;
+// UartControl.DeviceWidth = CH_DMA_WIDTH_8_BIT;
+// UartControl.BurstSize = CH_DMA_BURST_1_WORD;
+// UartControl.FlowControl = 1;
+//
+// CH_DMA_ADD_REQ_LINE_CONFIG UartConfig = {
+// 0x15,
+// UartControl
+// };
+//
+// RD_DMA_CONTROLLER DmaDesc = {
+// Header,
+// 0x70001000,
+// 32,
+// 0,
+// 31,
+// 0x27,
+// FALSE,
+// 1,
+// { UartConfig }
+// };
+//
+
+typedef struct _RD_DMA_CHANNEL {
+ CSRT_RESOURCE_DESCRIPTOR_HEADER Header;
+ ULONG ChannelNumber;
+} RD_DMA_CHANNEL, *PRD_DMA_CHANNEL;
+
+//
+// Resource description matching chDMA channel described in chdmaReadme.txt:
+//
+// RD_DMA_CHANNEL DmaDesc = {
+// Header,
+// 0
+// };
+//
+
+#pragma pack(pop)
+
+//
+// Extension Request line to configuration mapping.
+//
+
+typedef struct _CH_REQ_LINE_CONFIG {
+ BOOLEAN Valid;
+ CH_DMA_CHAN_CONTROL_REGISTER Ctrl;
+} CH_REQ_LINE_CONFIG, *PCH_REQ_LINE_CONFIG;
+
+typedef struct _CH_REQ_LINE_CONFIG_TABLE {
+ CH_REQ_LINE_CONFIG Entries[CH_DMA_MAX_REQUEST_LINES];
+} CH_DMA_REQ_LINE_CONFIG_TABLE, *PCH_DMA_REQ_LINE_CONFIG_TABLE;
+
+//
+// Define extension internal data for the controller and channel.
+//
+
+typedef struct _CH_DMA_CHANNEL {
+ BOOLEAN Active;
+ BOOLEAN AutoInit;
+} CH_DMA_CHANNEL, *PCH_DMA_CHANNEL;
+
+typedef struct _CH_DMA_CONTROLLER {
+
+ //
+ // Virtual and physical base addresses of the controller.
+ //
+
+ PULONG ControllerBaseVa;
+ PHYSICAL_ADDRESS ControllerBasePa;
+
+ ULONG ChannelCount;
+ ULONG MinimumRequestLine;
+ ULONG MaximumRequestLine;
+
+ //
+ // Individual channel extension status.
+ //
+
+ CH_DMA_CHANNEL Channels[CH_DMA_MAX_CHANNELS];
+
+ //
+ // Request line to configuration mapping.
+ //
+
+ CH_DMA_REQ_LINE_CONFIG_TABLE ReqConfig;
+} CH_DMA_CONTROLLER, *PCH_DMA_CONTROLLER;
+
+//
+// ----------------------------------------------------------------- Prototypes
+//
+
+VOID
+ChInitializeController (
+ __in PVOID ControllerContext
+ );
+
+BOOLEAN
+ChValidateRequestLineBinding (
+ __in PVOID ControllerContext,
+ __in PDMA_REQUEST_LINE_BINDING_DESCRIPTION BindingDescription
+ );
+
+ULONG
+ChQueryMaxFragments (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber,
+ __in ULONG MaxFragmentsRequested
+ );
+
+VOID
+ChProgramChannel (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber,
+ __in ULONG RequestLine,
+ __in PDMA_SCATTER_GATHER_LIST MemoryAddresses,
+ __in PHYSICAL_ADDRESS DeviceAddress,
+ __in BOOLEAN WriteToDevice,
+ __in BOOLEAN LoopTransfer
+ );
+
+BOOLEAN
+ChCancelTransfer (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber
+ );
+
+NTSTATUS
+ChConfigureChannel (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber,
+ __in ULONG FunctionNumber,
+ __in PVOID Context
+ );
+
+VOID
+ChFlushChannel (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber
+ );
+
+_Success_(return != FALSE)
+BOOLEAN
+ChHandleInterrupt (
+ __in PVOID ControllerContext,
+ __out PULONG ChannelNumber,
+ __out PDMA_INTERRUPT_TYPE InterruptType
+ );
+
+ULONG
+ChReadDmaCounter (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber
+ );
+
+//
+// -------------------------------------------------------------------- Globals
+//
+
+DMA_FUNCTION_TABLE ChFunctionTable =
+{
+ ChInitializeController,
+ ChValidateRequestLineBinding,
+ ChQueryMaxFragments,
+ ChProgramChannel,
+ ChConfigureChannel,
+ ChFlushChannel,
+ ChHandleInterrupt,
+ ChReadDmaCounter,
+ NULL, /* ReportCommonBuffer */
+ ChCancelTransfer
+};
+
+//
+// ------------------------------------------------------------------- Routines
+//
+
+VOID
+WriteRegister (
+ __in PCH_DMA_CONTROLLER Controller,
+ __in ULONG RegisterOffset,
+ __in ULONG Value
+ )
+
+{
+
+ PULONG Address;
+
+ Address = Controller->ControllerBaseVa;
+
+ //
+ // Add register offset. Register offset is in bytes. Pointer addition is
+ // in ULONGs.
+ //
+
+ Address += (RegisterOffset / 4);
+
+ WRITE_REGISTER_ULONG(Address, Value);
+}
+
+ULONG
+ReadRegister (
+ __in PCH_DMA_CONTROLLER Controller,
+ __in ULONG RegisterOffset
+ )
+
+{
+
+ PULONG Address;
+
+ Address = Controller->ControllerBaseVa;
+
+ //
+ // Add register offset. Register offset is in bytes. Pointer addition is
+ // in ULONGs.
+ //
+
+ Address += (RegisterOffset / 4);
+
+ return READ_REGISTER_ULONG(Address);
+}
+
+VOID
+WriteChannelRegister (
+ __in PCH_DMA_CONTROLLER Controller,
+ __in ULONG ChannelNumber,
+ __in ULONG RegisterOffset,
+ __in ULONG Value
+ )
+
+{
+ PULONG Address;
+
+ Address = Controller->ControllerBaseVa;
+
+ //
+ // Add channel base offset.
+ // Register offset is in bytes. Pointer addition is in ULONGs.
+ //
+
+ Address += (0x10 / 4);
+
+ //
+ // Add channel number offset.
+ //
+
+ Address += ((0x10 * ChannelNumber) / 4);
+
+ //
+ // Add channel register offset.
+ //
+
+ Address += (RegisterOffset / 4);
+
+ WRITE_REGISTER_ULONG(Address, Value);
+}
+
+ULONG
+ReadChannelRegister (
+ __in PCH_DMA_CONTROLLER Controller,
+ __in ULONG ChannelNumber,
+ __in ULONG RegisterOffset
+ )
+
+{
+
+ PULONG Address;
+
+ Address = Controller->ControllerBaseVa;
+
+ //
+ // Add channel base offset.
+ // Register offset is in bytes. Pointer addition is in ULONGs.
+ //
+
+ Address += (0x10 / 4);
+
+ //
+ // Add channel number offset.
+ //
+
+ Address += ((0x10 * ChannelNumber) / 4);
+
+ //
+ // Add channel register offset.
+ //
+
+ Address += (RegisterOffset / 4);
+
+ return READ_REGISTER_ULONG(Address);
+}
+
+VOID
+ChInitializeController (
+ __in PVOID ControllerContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine provides an opportunity for DMA controllers to initialize.
+
+Arguments:
+
+ ControllerContext - Supplies a pointer to the controller's internel data.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ CH_DMA_CONTROL_REGISTER CtrlRegister;
+ PCH_DMA_CONTROLLER Controller;
+ ULONG Index;
+ ULONG InterruptMask;
+
+ Controller = (PCH_DMA_CONTROLLER)ControllerContext;
+
+ //
+ // Map the controller base iff this is the first call to init (and it is
+ // therefore not already mapped.)
+ //
+
+ if (Controller->ControllerBaseVa == NULL) {
+ Controller->ControllerBaseVa =
+ (PULONG) HalMapIoSpace(Controller->ControllerBasePa,
+ PAGE_SIZE,
+ MmNonCached);
+
+ NT_ASSERT(Controller->ControllerBaseVa != NULL);
+ }
+
+ if (Controller->ControllerBaseVa == NULL) {
+ return;
+ }
+
+ //
+ // Initialize each channel.
+ //
+
+ for (Index = 0; Index < Controller->ChannelCount; Index += 1) {
+ WriteChannelRegister(Controller, Index, CH_DMA_CHAN_CONTROL, 0);
+ Controller->Channels[Index].Active = FALSE;
+ Controller->Channels[Index].AutoInit = FALSE;
+ }
+
+ //
+ // Enable the DMA controller.
+ //
+
+ CtrlRegister.AsUlong = 0;
+ CtrlRegister.ControllerEnable = 1;
+ WriteRegister(Controller, CH_DMA_CONTROL, CtrlRegister.AsUlong);
+
+ //
+ // Enable all interrupts.
+ //
+
+ InterruptMask = (1UL << Controller->ChannelCount) - 1;
+ WriteRegister(Controller, CH_DMA_INTERRUPT_MASK, InterruptMask);
+
+ return;
+}
+
+BOOLEAN
+ChValidateRequestLineBinding (
+ __in PVOID ControllerContext,
+ __in PDMA_REQUEST_LINE_BINDING_DESCRIPTION BindingDescription
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries a DMA controller extension to test the validity of a
+ request line binding.
+
+Arguments:
+
+ ControllerContext - Supplies a pointer to the controller's internal data.
+
+ DeviceDescription - Supplies a pointer to the request information.
+
+Return Value:
+
+ TRUE if the request line binding is valid and supported by the controller.
+
+ FALSE if the binding is invalid.
+
+Environment:
+
+ PASSIVE_LEVEL.
+
+--*/
+
+{
+
+ PCH_DMA_CONTROLLER Controller;
+
+ Controller = (PCH_DMA_CONTROLLER)ControllerContext;
+ if (BindingDescription->ChannelNumber > Controller->ChannelCount) {
+ return FALSE;
+ }
+
+ if ((BindingDescription->RequestLine > Controller->MaximumRequestLine) ||
+ (BindingDescription->RequestLine < Controller->MinimumRequestLine)) {
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+ULONG
+ChQueryMaxFragments (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber,
+ __in ULONG MaxFragmentsRequested
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the DMA extension to determine the number of
+ scatter gather fragments that the next transfer can support.
+
+Arguments:
+
+ ControllerContext - Supplies a pointer to the controller's internal data.
+
+ ChannelNumber - Supplies the number of the channel to program.
+
+ MaxFragmentsRequested - Supplies a hint to the maximum fragments useful to
+ this transfer.
+
+Return Value:
+
+ Number of fragments the next transfer on this channel can support.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(ControllerContext);
+ UNREFERENCED_PARAMETER(ChannelNumber);
+ UNREFERENCED_PARAMETER(MaxFragmentsRequested);
+
+ return 1;
+}
+
+VOID
+ChProgramChannel (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber,
+ __in ULONG RequestLine,
+ __in PDMA_SCATTER_GATHER_LIST MemoryAddresses,
+ __in PHYSICAL_ADDRESS DeviceAddress,
+ __in BOOLEAN WriteToDevice,
+ __in BOOLEAN LoopTransfer
+ )
+
+/*++
+
+Routine Description:
+
+ This routine programs a DMA controller channel for a specific transfer.
+
+Arguments:
+
+ ControllerContext - Supplies a pointer to the controller's internal data.
+
+ ChannelNumber - Supplies the number of the channel to program.
+
+ RequestLine - Supplies the request line number to program. This request
+ line number is system-unique (as provided to the HAL during
+ registration) and must be translated by the extension.
+
+ MemoryAddress - Supplies the address to be programmed into the memory
+ side of the channel configuration.
+
+ DeviceAddress - Supplies the address to be programmed into the device
+ side of the channel configuration.
+
+ WriteToDevice - Supplies the direction of the transfer.
+
+ LoopTransfer - Supplies whether AutoInitialize has been set in the
+ adapter making this request.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ CH_DMA_CHAN_CONTROL_REGISTER Ctrl;
+ PCH_DMA_CONTROLLER Controller;
+ ULONG DevPtr;
+ ULONG MemPtr;
+
+ Controller = (PCH_DMA_CONTROLLER)ControllerContext;
+ Controller->Channels[ChannelNumber].Active = TRUE;
+
+ //
+ // If this request line exists in the request line config table, use
+ // those values. Otherwise, use the reset values.
+ //
+
+ Ctrl.AsUlong = 0;
+ if (Controller->ReqConfig.Entries[RequestLine].Valid != 0) {
+ Ctrl.AsUlong = Controller->ReqConfig.Entries[RequestLine].Ctrl.AsUlong;
+ }
+
+ Ctrl.ChannelEnable = 1;
+ Ctrl.InterruptEnable = 1;
+ Ctrl.Loop = (LoopTransfer == FALSE) ? 0 : 1;
+ Ctrl.ReadFromDevice = (WriteToDevice == FALSE) ? 1 : 0;
+
+ //
+ // Request lines numbers reported by BIOS may be offset to make them
+ // globally unique. Request lines on the controller are based at 0.
+ //
+
+ Ctrl.RequestLine = RequestLine - Controller->MinimumRequestLine;
+ Ctrl.Length = MemoryAddresses->Elements[0].Length;
+
+ DevPtr = DeviceAddress.LowPart;
+ MemPtr = MemoryAddresses->Elements[0].Address.LowPart;
+
+ WriteChannelRegister(Controller,
+ ChannelNumber,
+ CH_DMA_CHAN_MEM_PTR,
+ MemPtr);
+
+ WriteChannelRegister(Controller,
+ ChannelNumber,
+ CH_DMA_CHAN_DEV_PTR,
+ DevPtr);
+
+ //
+ // Channel control is written last as it will enable the channel.
+ //
+
+ WriteChannelRegister(Controller,
+ ChannelNumber,
+ CH_DMA_CHAN_CONTROL,
+ Ctrl.AsUlong);
+}
+
+BOOLEAN
+ChCancelTransfer (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine must disable the selected channel. The channel must not be
+ capable of interrupting for this transfer after being cleared in this way.
+
+Arguments:
+
+ ControllerContext - Supplies a pointer to the controller's internal data.
+
+ ChannelNumber - Supplies the channel number.
+
+Return Value:
+
+ FALSE if the channel is already idle or if the channel is already asserting
+ an interrupt. TRUE is the channel is active and no interrupt is asserted.
+
+--*/
+
+{
+
+ PCH_DMA_CONTROLLER Controller;
+ ULONG StatusRegister;
+
+ Controller = (PCH_DMA_CONTROLLER)ControllerContext;
+
+ //
+ // If the channel is not active (because the interrupt already fired or
+ // because the channel was never programmed, return immediately.
+ //
+
+ if (Controller->Channels[ChannelNumber].Active == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // Disable the channel.
+ //
+
+ WriteChannelRegister(Controller, ChannelNumber, CH_DMA_CHAN_CONTROL, 0);
+
+ //
+ // If an interrupt is already pending on the channel, do nothing. The
+ // normal interrupt path will complete it. If an interrupt is not pending
+ // then this was successfully cancelled. In that case, mark the channel
+ // inactive and return TRUE.
+ //
+
+ StatusRegister = ReadRegister(Controller, CH_DMA_STATUS);
+ if ((StatusRegister & (1UL << ChannelNumber)) != 0) {
+ return FALSE;
+
+ } else {
+ Controller->Channels[ChannelNumber].Active = FALSE;
+ return TRUE;
+ }
+}
+
+NTSTATUS
+AddReqLineConfig (
+ __in PCH_DMA_CONTROLLER Controller,
+ __in PCH_DMA_ADD_REQ_LINE_CONFIG Config
+ )
+
+/*++
+
+Routine Description:
+
+ This routine updates the request line configuration table in the
+ extension's internal data for this controller.
+
+Arguments:
+
+ Controller - Supplies a pointer to the internal data for the controller.
+
+ Config - Supplies a pointer to the configuration to modify.
+
+Return Value:
+
+ STATUS_INVALID_PARAMETER if the request line is invalid.
+ Else, STATUS_SUCCESS.
+
+--*/
+
+{
+
+ ULONG RequestLine;
+
+ RequestLine = Config->RequestLine;
+ if ((RequestLine < Controller->MinimumRequestLine) ||
+ (RequestLine > Controller->MaximumRequestLine)) {
+
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ Controller->ReqConfig.Entries[RequestLine].Ctrl.AsUlong =
+ Config->Ctrl.AsUlong;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+ChConfigureChannel (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber,
+ __in ULONG FunctionNumber,
+ __in PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine configures the channel for a DMA extension specific operation.
+
+Arguments:
+
+ ControllerContext - Supplies a pointer to the controller's internal data.
+
+ ChannelNumber - Supplies the channel to configure.
+
+ FunctionNumber - Supplies the ID of the operation to perform.
+
+ Context - Supplies parameters for this operation.
+
+Return Value:
+
+ NTSTATUS code.
+
+--*/
+
+{
+
+ PCH_DMA_CONTROLLER Controller;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ Controller = (PCH_DMA_CONTROLLER)ControllerContext;
+ switch (FunctionNumber) {
+ case CONFIGURE_ADD_REQ_CONFIG:
+ Status = AddReqLineConfig(Controller,
+ (PCH_DMA_ADD_REQ_LINE_CONFIG)Context);
+
+ break;
+ default:
+ Status = STATUS_NOT_IMPLEMENTED;
+ }
+
+ return Status;
+}
+
+VOID
+ChFlushChannel (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes a previous transfer from a channel and returns the
+ channel to a state ready for the next ProgramChannel call.
+
+Arguments:
+
+ ControllerContext - Supplies a pointer to the controller's internal data.
+
+ ChannelNumber - Supplies the channel to flush.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PCH_DMA_CONTROLLER Controller;
+
+ Controller = (PCH_DMA_CONTROLLER)ControllerContext;
+ WriteChannelRegister(Controller, ChannelNumber, CH_DMA_CHAN_CONTROL, 0);
+}
+
+_Success_(return != FALSE)
+BOOLEAN
+ChHandleInterrupt (
+ __in PVOID ControllerContext,
+ __out PULONG ChannelNumber,
+ __out PDMA_INTERRUPT_TYPE InterruptType
+ )
+
+/*++
+
+Routine Description:
+
+ This routine probes a controller for interrupts, clears any interrupts
+ found, fills in channel and interrupt type information. This routine
+ will be called repeatedly until FALSE is returned.
+
+Arguments:
+
+ ControllerContext - Supplies a pointer to the controller's internal data.
+
+ ChannelNumber - Supplies a placeholder for the extension to fill in which
+ channel is interrupting.
+
+ InterruptType - Supplies a placeholder for the extension to fill in the
+ interrupt type.
+
+Return Value:
+
+ TRUE if an interrupt was found on this controller.
+
+ FALSE otherwise.
+
+--*/
+
+{
+
+ PCH_DMA_CONTROLLER Controller;
+ ULONG Index;
+ ULONG StatusRegister;
+
+ Controller = (PCH_DMA_CONTROLLER)ControllerContext;
+ StatusRegister = ReadRegister(Controller, CH_DMA_STATUS);
+ for (Index = 0; Index < Controller->ChannelCount; Index += 1) {
+ if ((StatusRegister & (1UL << Index)) != 0) {
+ *ChannelNumber = Index;
+ *InterruptType = InterruptTypeCompletion;
+ WriteRegister(Controller, CH_DMA_STATUS, (1UL << Index));
+
+ //
+ // If the channel is not marked as active, then this interrupt
+ // is spurious. Probably this is the result of a transfer being
+ // cancelled.
+ //
+
+ if (Controller->Channels[Index].Active == FALSE) {
+ continue;
+ }
+
+ //
+ // If the channel is not in autoinitialize mode, is it inactive now.
+ // If the channel is in autoinitialize, then it will remain active
+ // until it receives a cancel.
+ //
+
+ if (Controller->Channels[Index].AutoInit == FALSE) {
+ Controller->Channels[Index].Active = FALSE;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+ULONG ChReadDmaCounter (
+ __in PVOID ControllerContext,
+ __in ULONG ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine determines how many bytes remain to be transferred on the
+ given channel. If the current transfer is set to loop, this routine
+ will return the number of bytes remaining in the current iteration.
+
+Arguments:
+
+ ControllerContext - Supplies a pointer to the controller's internal data.
+
+ ChannelNumber - Supplies the channel number.
+
+Return Value:
+
+ Returns the number of bytes remaining to be transferred on the given
+ channel.
+
+--*/
+
+{
+
+ PCH_DMA_CONTROLLER Controller;
+ CH_DMA_CHAN_CONTROL_REGISTER Ctrl;
+ CH_DMA_CHAN_STATUS_REGISTER StatusReg;
+
+ Controller = (PCH_DMA_CONTROLLER)ControllerContext;
+ Ctrl.AsUlong = ReadChannelRegister(Controller,
+ ChannelNumber,
+ CH_DMA_CHAN_CONTROL);
+
+ StatusReg.AsUlong = ReadChannelRegister(Controller,
+ ChannelNumber,
+ CH_DMA_CHAN_STATUS);
+
+ return (Ctrl.Length - StatusReg.BytesTransferred);
+}
+
+NTSTATUS
+RegisterDmaController (
+ __in ULONG Handle,
+ __in PCSRT_RESOURCE_GROUP_HEADER ResourceGroup,
+ __in PCSRT_RESOURCE_DESCRIPTOR_HEADER ResourceDescriptor,
+ __out PULONG ControllerId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine takes a DMA resource descriptor with subtype controller.
+ The controller is then registered with the HAL.
+
+Arguments:
+
+ Handle - Supplies handle passed to extension.
+
+ ResourceGroup - Supplies resource group containing this descriptor.
+
+ ResourceDescrpitor - Supplies the resource descriptor.
+
+ ControllerId - Supplies a placeholder for the controller ID returned from
+ the HAL after registration.
+
+Return Value:
+
+ NTSTATUS Value.
+
+--*/
+
+{
+
+ PCH_REQ_LINE_CONFIG ConfigEntry;
+ PCH_REQ_LINE_CONFIG ConfigTableDst;
+ PCH_DMA_ADD_REQ_LINE_CONFIG ConfigTableSrc;
+ CH_DMA_CONTROLLER Controller;
+ PRD_DMA_CONTROLLER DmaDesc;
+ DMA_INITIALIZATION_BLOCK DmaInitBlock;
+ ULONG Index;
+ ULONG RequestLine;
+ NTSTATUS Status;
+
+ RtlZeroMemory(&Controller, sizeof(CH_DMA_CONTROLLER));
+
+ DmaDesc = (PRD_DMA_CONTROLLER)ResourceDescriptor;
+ Controller.ControllerBasePa.QuadPart = DmaDesc->BasePhysicalAddress;
+ Controller.ChannelCount = DmaDesc->ChannelCount;
+ Controller.MinimumRequestLine = DmaDesc->MinimumRequestLine;
+ Controller.MaximumRequestLine = DmaDesc->MaximumRequestLine;
+
+ //
+ // Build request line configuration mapping table.
+ //
+
+ ConfigTableDst = &Controller.ReqConfig.Entries[0];
+ ConfigTableSrc = &DmaDesc->ReqLineConfigs[0];
+
+ //
+ // Verify the supplied configuration description will fit within
+ // the build maximum.
+ //
+
+ if (DmaDesc->ReqLineConfigCount >= CH_DMA_MAX_REQUEST_LINES) {
+ Status = STATUS_INVALID_PARAMETER_1;
+ goto Exit;
+ }
+
+ for (Index = 0; Index < DmaDesc->ReqLineConfigCount; Index += 1) {
+
+ RequestLine = ConfigTableSrc[Index].RequestLine;
+
+ //
+ // Keep PreFast happy that we're assigning within memory bounds
+ //
+
+ if (RequestLine >= CH_DMA_MAX_REQUEST_LINES) {
+ Status = STATUS_INVALID_PARAMETER_2;
+ goto Exit;
+ }
+
+ ConfigEntry = &ConfigTableDst[RequestLine];
+ ConfigEntry->Ctrl.AsUlong = ConfigTableSrc[Index].Ctrl.AsUlong;
+ ConfigEntry->Valid = TRUE;
+ }
+
+ INITIALIZE_DMA_HEADER(&DmaInitBlock);
+ DmaInitBlock.ChannelCount = Controller.ChannelCount;
+ DmaInitBlock.MinimumTransferUnit = 1;
+ DmaInitBlock.MinimumRequestLine = Controller.MinimumRequestLine;
+ DmaInitBlock.MaximumRequestLine = Controller.MaximumRequestLine;
+ DmaInitBlock.CacheCoherent = DmaDesc->CacheCoherent;
+ DmaInitBlock.GeneratesInterrupt = TRUE;
+ DmaInitBlock.InternalData = (PVOID)&Controller;
+ DmaInitBlock.InternalDataSize = sizeof(CH_DMA_CONTROLLER);
+ DmaInitBlock.DmaAddressWidth = 32;
+ DmaInitBlock.Gsi = DmaDesc->InterruptGsi;
+ DmaInitBlock.InterruptPolarity = InterruptActiveHigh;
+ DmaInitBlock.InterruptMode = LevelSensitive;
+ DmaInitBlock.Operations = &ChFunctionTable;
+
+ //
+ // Register physical address space with the HAL.
+ //
+
+ HalRegisterPermanentAddressUsage(Controller.ControllerBasePa,
+ CH_DMA_REGISTER_SIZE);
+
+ //
+ // Register controller.
+ //
+
+ Status = RegisterResourceDescriptor(Handle,
+ ResourceGroup,
+ ResourceDescriptor,
+ &DmaInitBlock);
+
+ *ControllerId = DmaInitBlock.ControllerId;
+
+Exit:
+ return Status;
+
+}
+
+NTSTATUS
+RegisterDmaChannel (
+ __in ULONG Handle,
+ __in PCSRT_RESOURCE_GROUP_HEADER ResourceGroup,
+ __in PCSRT_RESOURCE_DESCRIPTOR_HEADER ResourceDescriptor,
+ __in ULONG ControllerId
+ )
+
+/*++
+
+Routine Description:
+
+ This routine takes a DMA resource descriptor with subtype channel.
+ The channel is then registered with the HAL.
+
+Arguments:
+
+ Handle - Supplies handle passed to extension.
+
+ ResourceGroup - Supplies resource group containing this descriptor.
+
+ ResourceDescrpitor - Supplies the resource descriptor.
+
+ ControllerId - Supplies the controller ID this channel is registered with.
+
+Return Value:
+
+ NTSTATUS Value.
+
+--*/
+
+{
+
+ DMA_CHANNEL_INITIALIZATION_BLOCK DmaChannelInitBlock;
+ PRD_DMA_CHANNEL DmaDesc;
+
+ NT_ASSERT(ControllerId != 0);
+
+ DmaDesc = (PRD_DMA_CHANNEL)ResourceDescriptor;
+ INITIALIZE_DMA_CHANNEL_HEADER(&DmaChannelInitBlock);
+ DmaChannelInitBlock.ControllerId = ControllerId;
+ DmaChannelInitBlock.GeneratesInterrupt = FALSE;
+ DmaChannelInitBlock.ChannelNumber = DmaDesc->ChannelNumber;
+ DmaChannelInitBlock.CommonBufferLength = 0;
+
+ return RegisterResourceDescriptor(Handle,
+ ResourceGroup,
+ ResourceDescriptor,
+ &DmaChannelInitBlock);
+}
+
+NTSTATUS
+AddResourceGroup (
+ __in ULONG Handle,
+ __in PCSRT_RESOURCE_GROUP_HEADER ResourceGroup
+ )
+
+{
+
+ ULONG ControllerId;
+ PCSRT_RESOURCE_DESCRIPTOR_HEADER ResourceDescriptor;
+
+ ResourceDescriptor = NULL;
+ ControllerId = 0;
+ for (;;) {
+ ResourceDescriptor =
+ GetNextResourceDescriptor(Handle,
+ ResourceGroup,
+ ResourceDescriptor,
+ CSRT_RD_TYPE_DMA,
+ CSRT_RD_SUBTYPE_ANY,
+ CSRT_RD_UID_ANY);
+
+ if (ResourceDescriptor == NULL) {
+ break;
+ }
+
+ if (ResourceDescriptor->Subtype == CSRT_RD_SUBTYPE_DMA_CONTROLLER) {
+ RegisterDmaController(Handle,
+ ResourceGroup,
+ ResourceDescriptor,
+ &ControllerId);
+
+ } else if (ResourceDescriptor->Subtype == CSRT_RD_SUBTYPE_DMA_CHANNEL) {
+ RegisterDmaChannel(Handle,
+ ResourceGroup,
+ ResourceDescriptor,
+ ControllerId);
+ } else {
+
+ NT_ASSERT(FALSE);
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
diff --git a/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.def b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.def
new file mode 100644
index 00000000..22ecba00
--- /dev/null
+++ b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.def
@@ -0,0 +1,2 @@
+LIBRARY HalExtSampleDma
+
diff --git a/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.rc b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.rc
new file mode 100644
index 00000000..534afafb
--- /dev/null
+++ b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.rc
@@ -0,0 +1,10 @@
+#include "verrsrc.h"
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "HAL Extension Sample - DMA"
+#define VER_INTERNALNAME_STR "HalExtSampleDma.DLL"
+#define VER_ORIGINALFILENAME_STR "HalExtSampleDma.DLL"
+
+#include <common.ver>
diff --git a/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.vcxproj b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.vcxproj
new file mode 100644
index 00000000..4d7b340c
--- /dev/null
+++ b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.vcxproj
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Arm">
+ <Configuration>Debug</Configuration>
+ <Platform>Arm</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Arm">
+ <Configuration>Release</Configuration>
+ <Platform>Arm</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{7568DCFB-C421-478A-A809-21EF6EC243BE}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Arm</Platform>
+ <SampleGuid>{03525FA0-7E40-493E-AAB7-D8D73FACBC51}</SampleGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Arm'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>False</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>True</UseDebugLibraries>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ <DriverType />
+ <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Arm'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" />
+ </ImportGroup>
+ <ItemGroup Label="WrappedTaskItems" />
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Arm'">
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">HalExtensionInit@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">HalExtensionInit</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'">
+ <Link>
+ <EntryPointSymbol Condition="'$(Platform)'=='win32'">HalExtensionInit@12</EntryPointSymbol>
+ <EntryPointSymbol Condition="'$(Platform)'!='win32'">HalExtensionInit</EntryPointSymbol>
+ </Link>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Arm'">
+ <TargetName>HalExtSampleDma</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'">
+ <TargetName>HalExtSampleDma</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Arm'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalOptions>%(AdditionalOptions) /J</AdditionalOptions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);halextlib.lib;libcntpr.lib;bufferoverflowfastfailk.lib</AdditionalDependencies>
+ <AdditionalOptions>%(AdditionalOptions) -merge:PAGECONST=PAGE -merge:INITCONST=INIT /LARGEADDRESSAWARE</AdditionalOptions>
+ <ModuleDefinitionFile>HalExtSampleDma.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'">
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalOptions>%(AdditionalOptions) /J</AdditionalOptions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ </ClCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);halextlib.lib;libcntpr.lib;bufferoverflowfastfailk.lib</AdditionalDependencies>
+ <AdditionalOptions>%(AdditionalOptions) -merge:PAGECONST=PAGE -merge:INITCONST=INIT /LARGEADDRESSAWARE</AdditionalOptions>
+ <ModuleDefinitionFile>HalExtSampleDma.def</ModuleDefinitionFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="HalExtSampleDma.c" />
+ <ResourceCompile Include="HalExtSampleDma.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inf)" Include="*.inf" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Exclude="@(None)" Include="*.txt;*.htm;*.html" />
+ <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" />
+ <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project> \ No newline at end of file
diff --git a/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.vcxproj.Filters b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.vcxproj.Filters
new file mode 100644
index 00000000..0e78975f
--- /dev/null
+++ b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.vcxproj.Filters
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{C49AD628-A169-4113-A58C-7869B002B124}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{4066A1BF-4F9E-4F43-B6C3-3DEEDE4A553C}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{CD82A108-349C-4687-A02C-C816B6A47307}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="HalExtSampleDma.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <None Include="HalExtSampleDma.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="HalExtSampleDma.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDmaReadme.txt b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDmaReadme.txt
new file mode 100644
index 00000000..05e44648
--- /dev/null
+++ b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDmaReadme.txt
@@ -0,0 +1,139 @@
+Copyright (c) 2011 Microsoft Corporation
+
+Author: Cody Hartwig (chartwig) 9-Jun-2011
+
+------
+
+This document describes the chDMA controller. chDMA is a 32-channel,
+32-request line DMA controller for which a sample HAL extension has been
+implemented. This document also describes a sample peripheral device and the
+configuration required for use with the DMA controller.
+
+General Controller Information
+==============================
+
+Base Physical Address 0x70001000
+GSI 0x27
+Number of Channels 32
+Number of Request Lines 32
+Cache Coherent No
+Supports ReadDmaCounter Yes
+
+
+Register Layout
+===============
+
+CH_DMA_CONTROL (Offset: 0x00, RW, Reset: 0x00000000)
+--------------
+
+This register sets controller-wide settings such as controller enable.
+
+Bit Function
+31 Controller Enable: 1-enable, 0-disable
+30-0 Reserved
+
+CH_DMA_STATUS (Offset: 0x04, RW1C, Reset: 0x00000000)
+-------------
+
+This register describes which channels are currently asserting an interrupt.
+Interrupts are cleared by writing 1 to the appropriate bit.
+
+Bit Function
+31 Channel 31 interrupt status
+30 Channel 30 interrupt status
+..
+0 Channel 0 interrupt status
+
+CH_DMA_INTERRUPT_MASK (Offset: 0x08, RW, Reset: 0x00000000)
+---------------------
+
+A channel interrupt is unmasked by writing 1 to the corresponding bit in this
+register.
+
+Bit Function
+31 Channel 31 interrupt mask
+30 Channel 30 interrupt mask
+..
+0 Channel 0 interrupt mask
+
+CH_DMA_CHANNEL_i_CONTROL (Offset: 0x10 + (i * 0x10), RW, Reset:0x00000000)
+------------------------
+
+This register controls per channel operation of the controller. A transfer
+may begin once the enable bit is set. When the enable bit is cleared, the
+current burst is finished and the transfer will stop.
+
+Bit Function
+31 Enable
+30 Interrupt on completion
+29-28 Device Width:
+ 0b00 - 8-bit
+ 0b01 - 16-bit
+ 0b10 - 32-bit
+ 0b11 - Reserved
+27-26 Burst Size:
+ 0b00 - 1 Word
+ 0b01 - 2 Word
+ 0b10 - 4 Word
+ 0b11 - 8 Word
+25 Flow Control: 1-enable, 0-disable
+24 Loop: 1-repeat transfer, 0-transfer once
+23-19 Request line trigger
+18 Transfer Direction: 1-device to mem, 0-mem to device
+17-16 Reserved
+15-0 Transfer Length
+
+CH_DMA_CHANNEL_i_MEM_PTR (Offset: 0x14 + (i * 0x10), RW, Reset: 0x00000000)
+------------------------
+
+This register sets the memory-side address of the transfer.
+
+Bit Function
+31-0 Memory-side address
+
+CH_DMA_CHANNEL_i_DEV_PTR (Offset: 0x18 + (i * 0x10), RW, Reset: 0x00000000)
+------------------------
+
+This register sets the device-side address of the transfer.
+
+Bit Function
+31-0 Device-side address
+
+CH_DMA_CHANNEL_i_STATUS (Offset: 0x1c + (i * 0x10), RO, Reset: 0x00000000)
+-----------------------
+
+This register reports transfer status.
+
+Bit Function
+31 Channel Busy
+30-16 Reserved
+15-0 Bytes Transferred
+
+
+
+Programming Model
+=================
+Normal operation of the DMA controller is achieved by the following steps:
+
+1. Enable the controller by writing 0x80000000 to the CH_DMA_CONTROL register.
+2. Unmask channel 0's interrupt by or'ing 0x1 with the CH_DMA_INTERRUPT_MASK
+ register
+3. Program the memory-side transfer address into the CH_DMA_CHANNEL_0_MEM_PTR
+ register.
+4. Program the device-side transfer address into the CH_DMA_CHANNEL_0_DEV_PTR
+ register.
+5. Program the CH_DMA_CHANNEL_0_CONTROL register. This enables the channel.
+
+
+Peripheral Information
+======================
+
+For the purposes of this sample, the chDMA controller is connected to a single
+UAART. This UART requires the following DMA controller configuration to
+work properly:
+
+Parameter Value
+Bus Width 8 bits
+Burst Size 1 Word
+Request Line 0x15
+Flow Control Enabled