diff options
Diffstat (limited to 'general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.c')
| -rw-r--r-- | general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.c | 1253 |
1 files changed, 0 insertions, 1253 deletions
diff --git a/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.c b/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.c deleted file mode 100644 index 3aade318..00000000 --- a/general/HalExtensionSample/HalExtSampleDma/HalExtSampleDma.c +++ /dev/null @@ -1,1253 +0,0 @@ -/*++ - -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; -} |
