mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
Complete reimplementation of HAL DMA routines.
The key changes are * Proper support for bus-master device adapters. * Real implementation of map registers. * Basic support for emulating scatter/gather DMA on devices that don't support it in hardware. * Support for transfers that aren't page aligned. * Proper detection and support of EISA DMA controllers. * Fixed prototype for HalFlushCommonBuffer. svn path=/trunk/; revision=17470
This commit is contained in:
parent
1fb85e029e
commit
a0b8ef87a8
8 changed files with 2239 additions and 1484 deletions
|
@ -211,10 +211,7 @@ HalFlushCommonBuffer(
|
|||
ULONG Unknown2,
|
||||
ULONG Unknown3,
|
||||
ULONG Unknown4,
|
||||
ULONG Unknown5,
|
||||
ULONG Unknown6,
|
||||
ULONG Unknown7,
|
||||
ULONG Unknown8)
|
||||
ULONG Unknown5)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ HalDisableSystemInterrupt@8
|
|||
HalDisplayString@4
|
||||
HalEnableSystemInterrupt@12
|
||||
HalEndSystemInterrupt@8
|
||||
HalFlushCommonBuffer@32
|
||||
HalFlushCommonBuffer@20
|
||||
HalFreeCommonBuffer@24
|
||||
HalGetAdapter@8
|
||||
HalGetBusData@20
|
||||
|
|
|
@ -1,717 +0,0 @@
|
|||
/* $Id$
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: hal/x86/adapter.c (from ntoskrnl/io/adapter.c)
|
||||
* PURPOSE: DMA handling
|
||||
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
||||
* Vizzini (vizzini@plasmic.com)
|
||||
* UPDATE HISTORY:
|
||||
* Created 22/05/98
|
||||
* 18-Oct-2003 Vizzini DMA support modifications
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <hal.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/* NOTE: IoAllocateAdapterChannel in NTOSKRNL.EXE */
|
||||
|
||||
|
||||
NTSTATUS STDCALL
|
||||
HalAllocateAdapterChannel(
|
||||
PADAPTER_OBJECT AdapterObject,
|
||||
PWAIT_CONTEXT_BLOCK WaitContextBlock,
|
||||
ULONG NumberOfMapRegisters,
|
||||
PDRIVER_CONTROL ExecutionRoutine)
|
||||
/*
|
||||
* FUNCTION: Sets up an ADAPTER_OBJECT with map registers
|
||||
* ARGUMENTS:
|
||||
* - AdapterObject: pointer to an ADAPTER_OBJECT to set up
|
||||
* - WaitContextBlock: Context block to be used with ExecutionRoutine
|
||||
* - NumberOfMapRegisters: number of map registers requested
|
||||
* - ExecutionRoutine: callback to call when map registers are allocated
|
||||
* RETURNS:
|
||||
* STATUS_INSUFFICIENT_RESOURCES if map registers cannot be allocated
|
||||
* STATUS_SUCCESS in all other cases, including if the callbacak had
|
||||
* to be queued for later delivery
|
||||
* NOTES:
|
||||
* - the ADAPTER_OBJECT struct is undocumented; please make copious
|
||||
* notes in hal.h if anything is changed or improved since there is
|
||||
* no other documentation for this data structure
|
||||
* BUGS:
|
||||
* - it's possible that some of this code is in the wrong place
|
||||
* - there are many unhandled cases
|
||||
*/
|
||||
{
|
||||
LARGE_INTEGER MinAddress;
|
||||
LARGE_INTEGER MaxAddress;
|
||||
LARGE_INTEGER BoundryAddressMultiple;
|
||||
IO_ALLOCATION_ACTION Retval;
|
||||
|
||||
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||
|
||||
/*
|
||||
FIXME: return STATUS_INSUFFICIENT_RESOURCES if the NumberOfMapRegisters
|
||||
requested is larger than the value returned by IoGetDmaAdapter.
|
||||
*/
|
||||
|
||||
/* set up the wait context block in case we can't run right away */
|
||||
WaitContextBlock->DeviceRoutine = ExecutionRoutine;
|
||||
WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
|
||||
|
||||
/* returns true if queued, else returns false and sets the queue to busy */
|
||||
if(KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue, &WaitContextBlock->WaitQueueEntry))
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
/* why 64K alignment? */
|
||||
/*
|
||||
* X86 lacks map registers, so for now, we allocate a contiguous
|
||||
* block of physical memory <16MB and copy all DMA buffers into
|
||||
* that. This can be optimized.
|
||||
*
|
||||
* FIXME: We propably shouldn't allocate the memory here for common
|
||||
* buffer transfers. See a comment in IoMapTransfer about common buffer
|
||||
* support.
|
||||
*/
|
||||
|
||||
MinAddress.QuadPart = 0;
|
||||
BoundryAddressMultiple.QuadPart = 0;
|
||||
if ((AdapterObject->Dma64BitAddresses) && (AdapterObject->MasterDevice))
|
||||
{
|
||||
MaxAddress.QuadPart = 0xFFFFFFFFFFFFFFFFLL; /* 64Bit: >4GB address range */
|
||||
}
|
||||
else if ((AdapterObject->Dma32BitAddresses) && (AdapterObject->MasterDevice))
|
||||
{
|
||||
MaxAddress.QuadPart = 0xFFFFFFFF; /* 32Bit: 4GB address range */
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxAddress.QuadPart = 0x00FFFFFF; /* 24Bit: 16MB address range */
|
||||
if (AdapterObject->Width16Bits)
|
||||
{
|
||||
BoundryAddressMultiple.QuadPart = 0x20000; /* 128k boundary */
|
||||
}
|
||||
else
|
||||
{
|
||||
BoundryAddressMultiple.QuadPart = 0x10000; /* 64k boundary */
|
||||
}
|
||||
}
|
||||
AdapterObject->MapRegisterBase = MmAllocateContiguousMemorySpecifyCache(
|
||||
NumberOfMapRegisters * PAGE_SIZE,
|
||||
MinAddress,
|
||||
MaxAddress,
|
||||
BoundryAddressMultiple,
|
||||
MmCached);
|
||||
|
||||
if(!AdapterObject->MapRegisterBase)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
AdapterObject->CommittedMapRegisters = NumberOfMapRegisters;
|
||||
|
||||
/* call the client's AdapterControl callback with its map registers and context */
|
||||
Retval = ExecutionRoutine(WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp,
|
||||
AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext);
|
||||
|
||||
/*
|
||||
* KeepObject: don't free any resources; the ADAPTER_OBJECT is still in use
|
||||
* and the caller will call IoFreeAdapterChannel later
|
||||
*
|
||||
* DeallocateObject: Deallocate the map registers and release the ADAPTER_OBJECT
|
||||
* so someone else can use it
|
||||
*
|
||||
* DeallocateObjectKeepRegisters: release the ADAPTER_OBJECT but hang on to
|
||||
* the map registers. The client will later call IoFreeMapRegisters.
|
||||
*
|
||||
* NOTE - IoFreeAdapterChannel runs the queue, so it must be called
|
||||
* unless the adapter object is not to be freed.
|
||||
*/
|
||||
if( Retval == DeallocateObject )
|
||||
IoFreeAdapterChannel(AdapterObject);
|
||||
else if(Retval == DeallocateObjectKeepRegisters)
|
||||
{
|
||||
/* don't free the allocated map registers - this is what IoFreeAdapterChannel checks */
|
||||
AdapterObject->CommittedMapRegisters = 0;
|
||||
IoFreeAdapterChannel(AdapterObject);
|
||||
}
|
||||
|
||||
/*
|
||||
* if we don't call IoFreeAdapterChannel, the next device won't get de-queued,
|
||||
* which is what we want.
|
||||
*/
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
HalpGrowMapBuffers(
|
||||
IN PADAPTER_OBJECT AdapterObject,
|
||||
IN ULONG SizeOfMapBuffers)
|
||||
/*
|
||||
* FUNCTION: Allocate initial, or additional, map buffers for IO adapters.
|
||||
* ARGUMENTS:
|
||||
* AdapterObject: DMA adapter to allocate buffers for.
|
||||
* SizeOfMapBuffers: Size of the map buffers to allocate
|
||||
* NOTES:
|
||||
* - Needs to be tested...
|
||||
*/
|
||||
{
|
||||
//ULONG PagesToAllocate = BYTES_TO_PAGES(SizeOfMapBuffers);
|
||||
|
||||
/* TODO: Allocation */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PADAPTER_OBJECT STDCALL
|
||||
HalpAllocateAdapterEx(
|
||||
ULONG NumberOfMapRegisters,
|
||||
BOOLEAN IsMaster,
|
||||
BOOLEAN Dma32BitAddresses)
|
||||
/*
|
||||
* FUNCTION: Allocates an ADAPTER_OBJECT, optionally creates the Master Adapter.
|
||||
* ARGUMENTS:
|
||||
* - NumberOfMapRegisters: Number of map registers to allocate
|
||||
* - IsMaster: Wether this is a Master Device or not
|
||||
* - Dma32BitAddresses: Wether 32-bit Addresses are supported
|
||||
* RETURNS:
|
||||
* - Pointer to Adapter Object, or NULL if failure.
|
||||
* BUGS:
|
||||
* - Some stuff is unhandled/incomplete
|
||||
*/
|
||||
{
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
ULONG ObjectSize;
|
||||
ULONG BitmapSize;
|
||||
NTSTATUS Status;
|
||||
ULONG AllowedMapRegisters = 64;
|
||||
PADAPTER_OBJECT AdapterObject;
|
||||
HANDLE Handle;
|
||||
|
||||
/* Allocate the Master Adapter if we haven't already
|
||||
but make sure we're not asked to do it now, and also check if we need it */
|
||||
if ((MasterAdapter == NULL) && (!IsMaster) && (NumberOfMapRegisters)) {
|
||||
|
||||
/* Allocate and Save */
|
||||
DPRINT("Allocating the Master Adapter Object\n");
|
||||
MasterAdapter = HalpAllocateAdapterEx(NumberOfMapRegisters,
|
||||
TRUE,
|
||||
Dma32BitAddresses);
|
||||
|
||||
/* Cancel on Failure */
|
||||
DPRINT("Checking if Master Adapter was allocated properly\n");
|
||||
if (!MasterAdapter) return NULL;
|
||||
}
|
||||
|
||||
/* Initialize the Object Attributes for the Adapter Object */
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
NULL,
|
||||
OBJ_PERMANENT,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Check if this is the Master Adapter, in which case we need to allocate the bitmap */
|
||||
if (IsMaster) {
|
||||
/* Size due to the Bitmap + Bytes in the Bitmap Buffer (8 bytes, 64 bits)*/
|
||||
BitmapSize = sizeof(RTL_BITMAP) + (AllowedMapRegisters + 7) / 8;
|
||||
|
||||
/* We will put the Bitmap Buffer after the Adapter Object for simplicity */
|
||||
ObjectSize = sizeof(ADAPTER_OBJECT) + BitmapSize;
|
||||
} else {
|
||||
ObjectSize = sizeof(ADAPTER_OBJECT);
|
||||
}
|
||||
|
||||
/* Create and Allocate the Object */
|
||||
DPRINT("Creating the Object\n");
|
||||
Status = ObCreateObject(KernelMode,
|
||||
IoAdapterObjectType,
|
||||
&ObjectAttributes,
|
||||
KernelMode,
|
||||
NULL,
|
||||
ObjectSize,
|
||||
0,
|
||||
0,
|
||||
(PVOID)&AdapterObject);
|
||||
|
||||
if (!NT_SUCCESS(Status)) return NULL;
|
||||
|
||||
/* Add a Reference */
|
||||
DPRINT("Referencing the Object\n");
|
||||
Status = ObReferenceObjectByPointer(AdapterObject,
|
||||
FILE_READ_DATA | FILE_WRITE_DATA,
|
||||
IoAdapterObjectType,
|
||||
KernelMode);
|
||||
|
||||
if (!NT_SUCCESS(Status)) return NULL;
|
||||
|
||||
/* It's a Valid Object, so now we can play with the memory */
|
||||
RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
|
||||
|
||||
/* Insert it into the Object Table */
|
||||
DPRINT("Inserting the Object\n");
|
||||
Status = ObInsertObject(AdapterObject,
|
||||
NULL,
|
||||
FILE_READ_DATA | FILE_WRITE_DATA,
|
||||
0,
|
||||
NULL,
|
||||
&Handle);
|
||||
|
||||
if (!NT_SUCCESS(Status)) return NULL;
|
||||
|
||||
/* We don't want the handle */
|
||||
NtClose(Handle);
|
||||
|
||||
/* Set up the Adapter Object fields */
|
||||
AdapterObject->MapRegistersPerChannel = 1;
|
||||
|
||||
/* Set the Master if needed (master only needed if we use Map Registers) */
|
||||
if (NumberOfMapRegisters) AdapterObject->MasterAdapter = MasterAdapter;
|
||||
|
||||
/* Initalize the Channel Wait queue, which every adapter has */
|
||||
DPRINT("Initializing the Device Queue of the Object\n");
|
||||
KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
|
||||
|
||||
/* Initialize the SpinLock, Queue and Bitmap, which are kept in the Master Adapter only */
|
||||
if (IsMaster) {
|
||||
|
||||
DPRINT("Initializing the Master Adapter Stuff\n");
|
||||
KeInitializeSpinLock(&AdapterObject->SpinLock);
|
||||
InitializeListHead(&AdapterObject->AdapterQueue);
|
||||
|
||||
/* As said previously, we put them here for simplicity */
|
||||
AdapterObject->MapRegisters = (PVOID)(AdapterObject + 1);
|
||||
|
||||
/* Set up Bitmap */
|
||||
RtlInitializeBitMap(AdapterObject->MapRegisters,
|
||||
(PULONG)(AdapterObject->MapRegisters + 1),
|
||||
AllowedMapRegisters);
|
||||
|
||||
/* Reset the Bitmap */
|
||||
RtlSetAllBits(AdapterObject->MapRegisters);
|
||||
AdapterObject->NumberOfMapRegisters = 0;
|
||||
AdapterObject->CommittedMapRegisters = 0;
|
||||
|
||||
/* Allocate Memory for the Map Registers */
|
||||
AdapterObject->MapRegisterBase = ExAllocatePool(NonPagedPool,
|
||||
AllowedMapRegisters * sizeof(DWORD));
|
||||
|
||||
/* Clear them */
|
||||
RtlZeroMemory(AdapterObject->MapRegisterBase, AllowedMapRegisters * sizeof(DWORD));
|
||||
|
||||
/* Allocate the contigous memory */
|
||||
DPRINT("Allocating Buffers\n");
|
||||
HalpGrowMapBuffers(AdapterObject, 0x1000000);
|
||||
}
|
||||
|
||||
DPRINT("Adapter Object allocated\n");
|
||||
return AdapterObject;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN STDCALL
|
||||
IoFlushAdapterBuffers (
|
||||
PADAPTER_OBJECT AdapterObject,
|
||||
PMDL Mdl,
|
||||
PVOID MapRegisterBase,
|
||||
PVOID CurrentVa,
|
||||
ULONG Length,
|
||||
BOOLEAN WriteToDevice)
|
||||
/*
|
||||
* FUNCTION: flush any data remaining in the dma controller's memory into the host memory
|
||||
* ARGUMENTS:
|
||||
* AdapterObject: the adapter object to flush
|
||||
* Mdl: original MDL to flush data into
|
||||
* MapRegisterBase: map register base that was just used by IoMapTransfer, etc
|
||||
* CurrentVa: offset into Mdl to be flushed into, same as was passed to IoMapTransfer
|
||||
* Length: length of the buffer to be flushed into
|
||||
* WriteToDevice: True if it's a write, False if it's a read
|
||||
* RETURNS:
|
||||
* TRUE in all cases
|
||||
* NOTES:
|
||||
* - This copies data from the map register-backed buffer to the user's target buffer.
|
||||
* Data is not in the user buffer until this is called.
|
||||
* - This is only meaningful on a read operation. Return immediately for a write.
|
||||
*/
|
||||
{
|
||||
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
||||
|
||||
/* this can happen if the card supports scatter/gather */
|
||||
if(!MapRegisterBase)
|
||||
return TRUE;
|
||||
|
||||
/* mask out (disable) the dma channel */
|
||||
if (AdapterObject->AdapterNumber == 1) {
|
||||
|
||||
/* Set this for Ease */
|
||||
PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
|
||||
|
||||
/* Set Channel */
|
||||
WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_SETMASK);
|
||||
} else {
|
||||
/* Set this for Ease */
|
||||
PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
|
||||
|
||||
/* Set Channel */
|
||||
WRITE_PORT_UCHAR(&DmaControl2->SingleMask, (AdapterObject->ChannelNumber - 4) | DMA_SETMASK);
|
||||
}
|
||||
|
||||
if(WriteToDevice)
|
||||
return TRUE;
|
||||
|
||||
memcpy(
|
||||
(PVOID)((DWORD)MmGetSystemAddressForMdl( Mdl ) + (DWORD)CurrentVa - (DWORD)MmGetMdlVirtualAddress( Mdl )),
|
||||
MapRegisterBase, Length );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
VOID STDCALL
|
||||
IoFreeAdapterChannel (PADAPTER_OBJECT AdapterObject)
|
||||
/*
|
||||
* FUNCTION: frees DMA resources allocated by IoAllocateAdapterChannel
|
||||
* ARGUMENTS:
|
||||
* AdapterObject: Adapter object with resources to free
|
||||
* NOTES:
|
||||
* - This function releases the DMA adapter and optionally the map registers
|
||||
* - After releasing the adapter, it checks the adapter's queue and runs
|
||||
* each queued device object in series until the queue is empty
|
||||
* - This is the only way the device queue is emptied.
|
||||
*/
|
||||
{
|
||||
LARGE_INTEGER MaxAddress;
|
||||
LARGE_INTEGER MinAddress;
|
||||
LARGE_INTEGER BoundryAddressMultiple;
|
||||
PWAIT_CONTEXT_BLOCK WaitContextBlock;
|
||||
IO_ALLOCATION_ACTION Retval;
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* To keep map registers, call here with the following set to 0 */
|
||||
if(AdapterObject->CommittedMapRegisters)
|
||||
IoFreeMapRegisters(AdapterObject, AdapterObject->MapRegisterBase, AdapterObject->CommittedMapRegisters);
|
||||
|
||||
if(!(WaitContextBlock = (PWAIT_CONTEXT_BLOCK)KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue)))
|
||||
break;
|
||||
|
||||
/*
|
||||
* the following should really be done elsewhere since this
|
||||
* function really can't return an error code. FIXME.
|
||||
*/
|
||||
|
||||
MinAddress.QuadPart = 0;
|
||||
BoundryAddressMultiple.QuadPart = 0;
|
||||
if ((AdapterObject->Dma64BitAddresses) && (AdapterObject->MasterDevice))
|
||||
{
|
||||
MaxAddress.QuadPart = 0xFFFFFFFFFFFFFFFFLL; /* 64Bit: >4GB address range */
|
||||
}
|
||||
else if ((AdapterObject->Dma32BitAddresses) && (AdapterObject->MasterDevice))
|
||||
{
|
||||
MaxAddress.QuadPart = 0xFFFFFFFF; /* 32Bit: 4GB address range */
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxAddress.QuadPart = 0x00FFFFFF; /* 24Bit: 16MB address range */
|
||||
if (AdapterObject->Width16Bits)
|
||||
{
|
||||
BoundryAddressMultiple.QuadPart = 0x20000; /* 128k boundary */
|
||||
}
|
||||
else
|
||||
{
|
||||
BoundryAddressMultiple.QuadPart = 0x10000; /* 64k boundary */
|
||||
}
|
||||
}
|
||||
|
||||
AdapterObject->MapRegisterBase = MmAllocateContiguousMemorySpecifyCache(
|
||||
WaitContextBlock->NumberOfMapRegisters * PAGE_SIZE,
|
||||
MinAddress,
|
||||
MaxAddress,
|
||||
BoundryAddressMultiple,
|
||||
MmCached);
|
||||
|
||||
if(!AdapterObject->MapRegisterBase)
|
||||
return;
|
||||
|
||||
/* call the adapter control routine */
|
||||
Retval = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp,
|
||||
AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext);
|
||||
|
||||
if(Retval == KeepObject)
|
||||
{
|
||||
/* we're done until the caller manually calls IoFreeAdapterChannel */
|
||||
break;
|
||||
}
|
||||
else if(Retval == DeallocateObjectKeepRegisters)
|
||||
{
|
||||
/* hide the map registers so they aren't deallocated next time around */
|
||||
AdapterObject->CommittedMapRegisters = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID STDCALL
|
||||
IoFreeMapRegisters (
|
||||
IN PADAPTER_OBJECT AdapterObject,
|
||||
IN PVOID MapRegisterBase,
|
||||
IN ULONG NumberOfMapRegisters)
|
||||
/*
|
||||
* FUNCTION: free map registers reserved by the system for a DMA
|
||||
* ARGUMENTS:
|
||||
* AdapterObject: dma adapter to free map registers on
|
||||
* MapRegisterBase: hadle to map registers to free
|
||||
* NumberOfRegisters: number of map registers to be freed
|
||||
* NOTES:
|
||||
* - XXX real windows has a funky interdependence between IoFreeMapRegisters
|
||||
* and IoFreeAdapterChannel
|
||||
* BUGS:
|
||||
* - needs to be improved to use a real map register implementation
|
||||
*/
|
||||
{
|
||||
if( AdapterObject->CommittedMapRegisters )
|
||||
{
|
||||
MmFreeContiguousMemory(AdapterObject->MapRegisterBase);
|
||||
AdapterObject->MapRegisterBase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PHYSICAL_ADDRESS STDCALL
|
||||
IoMapTransfer (
|
||||
IN PADAPTER_OBJECT AdapterObject,
|
||||
IN PMDL Mdl,
|
||||
IN PVOID MapRegisterBase,
|
||||
IN PVOID CurrentVa,
|
||||
IN OUT PULONG Length,
|
||||
IN BOOLEAN WriteToDevice)
|
||||
/*
|
||||
* FUNCTION: map a dma for transfer and do the dma if it's a slave
|
||||
* ARGUMENTS:
|
||||
* AdapterObject: adapter object to do the dma on. busmaster may pass NULL.
|
||||
* Mdl: locked-down user buffer to DMA in to or out of
|
||||
* MapRegisterBase: handle to map registers to use for this dma. allways NULL
|
||||
* when doing s/g.
|
||||
* CurrentVa: index into Mdl to transfer into/out of
|
||||
* Length: length of transfer in/out. Only modified on out when doing s/g.
|
||||
* WriteToDevice: TRUE if it's an output dma, FALSE otherwise
|
||||
* RETURNS:
|
||||
* If a busmaster: A logical address that can be used to program a dma controller
|
||||
* Otherwise: nothing meaningful
|
||||
* NOTES:
|
||||
* - This function does a copyover to contiguous memory <16MB
|
||||
* - If it's a slave transfer, this function actually performs it.
|
||||
* BUGS:
|
||||
* - If the controller supports scatter/gather, the copyover should not happen
|
||||
*/
|
||||
{
|
||||
PHYSICAL_ADDRESS Address;
|
||||
KIRQL OldIrql;
|
||||
ULONG LengthShift = 0;
|
||||
|
||||
Address.QuadPart = 0;
|
||||
|
||||
/* Isa System (slave) DMA? */
|
||||
if (MapRegisterBase && !AdapterObject->MasterDevice)
|
||||
{
|
||||
KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
|
||||
|
||||
/*
|
||||
* FIXME: Handle case when doing common-buffer System DMA. In this case,
|
||||
* the buffer described by MDL is already phys. contiguous and below
|
||||
* 16 mega. Driver makes a one-shot call to IoMapTransfer during init.
|
||||
* to program controller with the common-buffer.
|
||||
*
|
||||
* UPDATE: Common buffer support is in place, but it's not done in a
|
||||
* clean way. We use the buffer passed by the MDL in case that the
|
||||
* adapter object is marked as auto initialize. I'm not sure if this
|
||||
* is correct and if not, how to do it properly. Note that it's also
|
||||
* possible to allocate the common buffer with different adapter object
|
||||
* and IoMapTransfer must still work in this case. Eventually this should
|
||||
* be cleaned up somehow or at least this comment modified to reflect
|
||||
* the reality.
|
||||
* -- Filip Navara, 19/07/2004
|
||||
*/
|
||||
|
||||
/* if it is a write to the device, copy the caller buffer to the low buffer */
|
||||
if (WriteToDevice && !AdapterObject->AdapterMode.AutoInitialize)
|
||||
{
|
||||
memcpy(MapRegisterBase,
|
||||
(char*)MmGetSystemAddressForMdl(Mdl) + ((ULONG)CurrentVa - (ULONG)MmGetMdlVirtualAddress(Mdl)),
|
||||
*Length );
|
||||
}
|
||||
|
||||
/* Writer Adapter Mode, transfer type */
|
||||
AdapterObject->AdapterMode.TransferType = (WriteToDevice ? WRITE_TRANSFER : READ_TRANSFER);
|
||||
|
||||
/* program up the dma controller, and return */
|
||||
if (!AdapterObject->AdapterMode.AutoInitialize) {
|
||||
Address = MmGetPhysicalAddress( MapRegisterBase );
|
||||
} else {
|
||||
Address = MmGetPhysicalAddress( CurrentVa );
|
||||
}
|
||||
|
||||
/* 16-bit DMA has a shifted length */
|
||||
if (AdapterObject->Width16Bits) {
|
||||
LengthShift = 1;
|
||||
}
|
||||
|
||||
/* Make the Transfer */
|
||||
if (AdapterObject->AdapterNumber == 1) {
|
||||
|
||||
PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa; /* For Writing Less Code */
|
||||
|
||||
/* Mask the Channel */
|
||||
WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_SETMASK);
|
||||
|
||||
/* Reset Register */
|
||||
WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
|
||||
|
||||
/* Set the Mode */
|
||||
WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterObject->AdapterModeByte);
|
||||
|
||||
/* Set the Page Register */
|
||||
WRITE_PORT_UCHAR(AdapterObject->PagePort, (UCHAR)(Address.u.LowPart >> 16));
|
||||
|
||||
/* Set the Offset Register (apparently always 0 for us if I trust the previous comment) */
|
||||
WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0);
|
||||
WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0);
|
||||
|
||||
/* Set the Length */
|
||||
WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
|
||||
(UCHAR)((*Length >> LengthShift) - 1));
|
||||
WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
|
||||
(UCHAR)(((*Length >> LengthShift) - 1) >> 8));
|
||||
|
||||
/* Unmask the Channel */
|
||||
WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
|
||||
} else {
|
||||
PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa; /* For Writing Less Code */
|
||||
|
||||
/* Mask the Channel */
|
||||
WRITE_PORT_UCHAR(&DmaControl2->SingleMask, AdapterObject->ChannelNumber | DMA_SETMASK);
|
||||
|
||||
/* Reset Register */
|
||||
WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
|
||||
|
||||
/* Set the Mode */
|
||||
WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterObject->AdapterModeByte);
|
||||
|
||||
/* Set the Page Register */
|
||||
WRITE_PORT_UCHAR(AdapterObject->PagePort, (UCHAR)(Address.u.LowPart >> 16));
|
||||
|
||||
/* Set the Offset Register (apparently always 0 for us if I trust the previous comment) */
|
||||
WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0);
|
||||
WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress, 0);
|
||||
|
||||
/* Set the Length */
|
||||
WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
|
||||
(UCHAR)((*Length >> LengthShift) - 1));
|
||||
WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
|
||||
(UCHAR)(((*Length >> LengthShift) - 1) >> 8));
|
||||
|
||||
/* Unmask the Channel */
|
||||
WRITE_PORT_UCHAR(&DmaControl2->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
|
||||
}
|
||||
|
||||
/* Release Spinlock */
|
||||
KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
|
||||
|
||||
/*
|
||||
NOTE: Return value should be ignored when doing System DMA.
|
||||
Maybe return some more obvious invalid address here (thou returning
|
||||
MapRegisterBase is also wrong;-)to catch invalid use?
|
||||
*/
|
||||
Address.QuadPart = (ULONG)MapRegisterBase;
|
||||
return Address;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Busmaster with s/g support?
|
||||
NOTE: old docs allowed busmasters to pass a NULL Adapter. In this case, MapRegisterBase
|
||||
being NULL is used to detect a s/g busmaster.
|
||||
*/
|
||||
if ((!AdapterObject && !MapRegisterBase) ||
|
||||
(AdapterObject && AdapterObject->MasterDevice && AdapterObject->ScatterGather))
|
||||
{
|
||||
/*
|
||||
Just return the passed VA's corresponding phys. address.
|
||||
Update length to the number of phys. contiguous bytes found.
|
||||
*/
|
||||
|
||||
PULONG MdlPages;
|
||||
ULONG MdlPageIndex, PhysContiguousLen;
|
||||
ULONG PhysAddress;
|
||||
|
||||
MdlPages = (PULONG)(Mdl + 1);
|
||||
|
||||
/* Get VA's corresponding mdl phys. page index */
|
||||
MdlPageIndex = ((ULONG)CurrentVa - (ULONG)Mdl->StartVa) / PAGE_SIZE;
|
||||
|
||||
/* Get phys. page containing the VA */
|
||||
PhysAddress = MdlPages[MdlPageIndex];
|
||||
|
||||
PhysContiguousLen = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
|
||||
|
||||
/* VA to map may span several contiguous phys. pages (unlikely) */
|
||||
while (PhysContiguousLen < *Length &&
|
||||
MdlPages[MdlPageIndex++] + PAGE_SIZE == MdlPages[MdlPageIndex])
|
||||
{
|
||||
/*
|
||||
Note that allways adding PAGE_SIZE may make PhysContiguousLen greater
|
||||
than Length if buffer doesn't end on page boundary. Take this
|
||||
into consideration below.
|
||||
*/
|
||||
PhysContiguousLen += PAGE_SIZE;
|
||||
}
|
||||
|
||||
if (PhysContiguousLen < *Length)
|
||||
{
|
||||
*Length = PhysContiguousLen;
|
||||
}
|
||||
|
||||
//add offset to phys. page address
|
||||
Address.QuadPart = PhysAddress + BYTE_OFFSET(CurrentVa);
|
||||
return Address;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Busmaster without s/g support?
|
||||
NOTE: old docs allowed busmasters to pass a NULL Adapter. In this case, MapRegisterBase
|
||||
not being NULL is used to detect a non s/g busmaster.
|
||||
*/
|
||||
if ((!AdapterObject && MapRegisterBase) ||
|
||||
(AdapterObject && AdapterObject->MasterDevice && !AdapterObject->ScatterGather))
|
||||
{
|
||||
/*
|
||||
NOTE: Busmasters doing common-buffer DMA shouldn't call IoMapTransfer, but I don't
|
||||
know if it's illegal... Maybe figure out what to do in this case...
|
||||
*/
|
||||
|
||||
if( WriteToDevice )
|
||||
{
|
||||
memcpy(MapRegisterBase,
|
||||
(char*)MmGetSystemAddressForMdl(Mdl) + ((ULONG)CurrentVa - (ULONG)MmGetMdlVirtualAddress(Mdl)),
|
||||
*Length );
|
||||
}
|
||||
|
||||
return MmGetPhysicalAddress(MapRegisterBase);
|
||||
}
|
||||
|
||||
DPRINT("IoMapTransfer: Unsupported operation\n");
|
||||
KEBUGCHECK(0);
|
||||
return Address;
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,6 @@
|
|||
<define name="_DISABLE_TIDENTS" />
|
||||
<define name="__USE_W32API" />
|
||||
<define name="_NTHAL_" />
|
||||
<file>adapter.c</file>
|
||||
<file>beep.c</file>
|
||||
<file>bus.c</file>
|
||||
<file>dma.c</file>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "apic.h"
|
||||
#include "bus.h"
|
||||
#include "halirq.h"
|
||||
#include "haldma.h"
|
||||
#include "halp.h"
|
||||
#include "mps.h"
|
||||
#include "ioapic.h"
|
||||
|
|
389
reactos/hal/halx86/include/haldma.h
Normal file
389
reactos/hal/halx86/include/haldma.h
Normal file
|
@ -0,0 +1,389 @@
|
|||
#ifndef HALDMA_H
|
||||
#define HALDMA_H
|
||||
|
||||
/*
|
||||
* DMA Page Register Structure
|
||||
* 080 DMA RESERVED
|
||||
* 081 DMA Page Register (channel 2)
|
||||
* 082 DMA Page Register (channel 3)
|
||||
* 083 DMA Page Register (channel 1)
|
||||
* 084 DMA RESERVED
|
||||
* 085 DMA RESERVED
|
||||
* 086 DMA RESERVED
|
||||
* 087 DMA Page Register (channel 0)
|
||||
* 088 DMA RESERVED
|
||||
* 089 PS/2-DMA Page Register (channel 6)
|
||||
* 08A PS/2-DMA Page Register (channel 7)
|
||||
* 08B PS/2-DMA Page Register (channel 5)
|
||||
* 08C PS/2-DMA RESERVED
|
||||
* 08D PS/2-DMA RESERVED
|
||||
* 08E PS/2-DMA RESERVED
|
||||
* 08F PS/2-DMA Page Register (channel 4)
|
||||
*/
|
||||
|
||||
typedef struct _DMA_PAGE
|
||||
{
|
||||
UCHAR Reserved1;
|
||||
UCHAR Channel2;
|
||||
UCHAR Channel3;
|
||||
UCHAR Channel1;
|
||||
UCHAR Reserved2[3];
|
||||
UCHAR Channel0;
|
||||
UCHAR Reserved3;
|
||||
UCHAR Channel6;
|
||||
UCHAR Channel7;
|
||||
UCHAR Channel5;
|
||||
UCHAR Reserved4[3];
|
||||
UCHAR Channel4;
|
||||
} DMA_PAGE, *PDMA_PAGE;
|
||||
|
||||
/*
|
||||
* DMA Channel Mask Register Structure
|
||||
*
|
||||
* MSB LSB
|
||||
* x x x x x x x x
|
||||
* ------------------- - -----
|
||||
* | | | 00 - Select channel 0 mask bit
|
||||
* | | \---- 01 - Select channel 1 mask bit
|
||||
* | | 10 - Select channel 2 mask bit
|
||||
* | | 11 - Select channel 3 mask bit
|
||||
* | |
|
||||
* | \---------- 0 - Clear mask bit
|
||||
* | 1 - Set mask bit
|
||||
* |
|
||||
* \----------------------- xx - Reserved
|
||||
*/
|
||||
|
||||
typedef struct _DMA_CHANNEL_MASK
|
||||
{
|
||||
UCHAR Channel: 2;
|
||||
UCHAR SetMask: 1;
|
||||
UCHAR Reserved: 5;
|
||||
} DMA_CHANNEL_MASK, *PDMA_CHANNEL_MASK;
|
||||
|
||||
/*
|
||||
* DMA Mask Register Structure
|
||||
*
|
||||
* MSB LSB
|
||||
* x x x x x x x x
|
||||
* \---/ - - ----- -----
|
||||
* | | | | | 00 - Channel 0 select
|
||||
* | | | | \---- 01 - Channel 1 select
|
||||
* | | | | 10 - Channel 2 select
|
||||
* | | | | 11 - Channel 3 select
|
||||
* | | | |
|
||||
* | | | | 00 - Verify transfer
|
||||
* | | | \------------ 01 - Write transfer
|
||||
* | | | 10 - Read transfer
|
||||
* | | |
|
||||
* | | \-------------------- 0 - Autoinitialized
|
||||
* | | 1 - Non-autoinitialized
|
||||
* | |
|
||||
* | \------------------------ 0 - Address increment select
|
||||
* |
|
||||
* | 00 - Demand mode
|
||||
* \------------------------------ 01 - Single mode
|
||||
* 10 - Block mode
|
||||
* 11 - Cascade mode
|
||||
*/
|
||||
|
||||
typedef union _DMA_MODE
|
||||
{
|
||||
struct
|
||||
{
|
||||
UCHAR Channel: 2;
|
||||
UCHAR TransferType: 2;
|
||||
UCHAR AutoInitialize: 1;
|
||||
UCHAR AddressDecrement: 1;
|
||||
UCHAR RequestMode: 2;
|
||||
};
|
||||
UCHAR Byte;
|
||||
} DMA_MODE, *PDMA_MODE;
|
||||
|
||||
/*
|
||||
* DMA Extended Mode Register Structure
|
||||
*
|
||||
* MSB LSB
|
||||
* x x x x x x x x
|
||||
* - - ----- ----- -----
|
||||
* | | | | | 00 - Channel 0 select
|
||||
* | | | | \---- 01 - Channel 1 select
|
||||
* | | | | 10 - Channel 2 select
|
||||
* | | | | 11 - Channel 3 select
|
||||
* | | | |
|
||||
* | | | | 00 - 8-bit I/O, by bytes
|
||||
* | | | \------------ 01 - 16-bit I/O, by words, address shifted
|
||||
* | | | 10 - 32-bit I/O, by bytes
|
||||
* | | | 11 - 16-bit I/O, by bytes
|
||||
* | | |
|
||||
* | | \---------------------- 00 - Compatible
|
||||
* | | 01 - Type A
|
||||
* | | 10 - Type B
|
||||
* | | 11 - Burst
|
||||
* | |
|
||||
* | \---------------------------- 0 - Terminal Count is Output
|
||||
* |
|
||||
* \---------------------------------0 - Disable Stop Register
|
||||
* 1 - Enable Stop Register
|
||||
*/
|
||||
|
||||
typedef union _DMA_EXTENDED_MODE
|
||||
{
|
||||
struct
|
||||
{
|
||||
UCHAR ChannelNumber: 2;
|
||||
UCHAR TransferSize: 2;
|
||||
UCHAR TimingMode: 2;
|
||||
UCHAR TerminalCountIsOutput: 1;
|
||||
UCHAR EnableStopRegister: 1;
|
||||
};
|
||||
UCHAR Byte;
|
||||
} DMA_EXTENDED_MODE, *PDMA_EXTENDED_MODE;
|
||||
|
||||
/* DMA Extended Mode Register Transfer Sizes */
|
||||
#define B_8BITS 0
|
||||
#define W_16BITS 1
|
||||
#define B_32BITS 2
|
||||
#define B_16BITS 3
|
||||
|
||||
/* DMA Extended Mode Register Timing */
|
||||
#define COMPATIBLE_TIMING 0
|
||||
#define TYPE_A_TIMING 1
|
||||
#define TYPE_B_TIMING 2
|
||||
#define BURST_TIMING 3
|
||||
|
||||
/* Channel Stop Registers for each Channel */
|
||||
typedef struct _DMA_CHANNEL_STOP
|
||||
{
|
||||
UCHAR ChannelLow;
|
||||
UCHAR ChannelMid;
|
||||
UCHAR ChannelHigh;
|
||||
UCHAR Reserved;
|
||||
} DMA_CHANNEL_STOP, *PDMA_CHANNEL_STOP;
|
||||
|
||||
/* Transfer Types */
|
||||
#define VERIFY_TRANSFER 0x00
|
||||
#define READ_TRANSFER 0x01
|
||||
#define WRITE_TRANSFER 0x02
|
||||
|
||||
/* Request Modes */
|
||||
#define DEMAND_REQUEST_MODE 0x00
|
||||
#define SINGLE_REQUEST_MODE 0x01
|
||||
#define BLOCK_REQUEST_MODE 0x02
|
||||
#define CASCADE_REQUEST_MODE 0x03
|
||||
|
||||
#define DMA_SETMASK 4
|
||||
#define DMA_CLEARMASK 0
|
||||
#define DMA_READ 4
|
||||
#define DMA_WRITE 8
|
||||
#define DMA_SINGLE_TRANSFER 0x40
|
||||
#define DMA_AUTO_INIT 0x10
|
||||
|
||||
typedef struct _DMA1_ADDRESS_COUNT
|
||||
{
|
||||
UCHAR DmaBaseAddress;
|
||||
UCHAR DmaBaseCount;
|
||||
} DMA1_ADDRESS_COUNT, *PDMA1_ADDRESS_COUNT;
|
||||
|
||||
typedef struct _DMA2_ADDRESS_COUNT
|
||||
{
|
||||
UCHAR DmaBaseAddress;
|
||||
UCHAR Reserved1;
|
||||
UCHAR DmaBaseCount;
|
||||
UCHAR Reserved2;
|
||||
} DMA2_ADDRESS_COUNT, *PDMA2_ADDRESS_COUNT;
|
||||
|
||||
typedef struct _DMA1_CONTROL
|
||||
{
|
||||
DMA1_ADDRESS_COUNT DmaAddressCount[4];
|
||||
UCHAR DmaStatus;
|
||||
UCHAR DmaRequest;
|
||||
UCHAR SingleMask;
|
||||
UCHAR Mode;
|
||||
UCHAR ClearBytePointer;
|
||||
UCHAR MasterClear;
|
||||
UCHAR ClearMask;
|
||||
UCHAR AllMask;
|
||||
} DMA1_CONTROL, *PDMA1_CONTROL;
|
||||
|
||||
typedef struct _DMA2_CONTROL
|
||||
{
|
||||
DMA2_ADDRESS_COUNT DmaAddressCount[4];
|
||||
UCHAR DmaStatus;
|
||||
UCHAR Reserved1;
|
||||
UCHAR DmaRequest;
|
||||
UCHAR Reserved2;
|
||||
UCHAR SingleMask;
|
||||
UCHAR Reserved3;
|
||||
UCHAR Mode;
|
||||
UCHAR Reserved4;
|
||||
UCHAR ClearBytePointer;
|
||||
UCHAR Reserved5;
|
||||
UCHAR MasterClear;
|
||||
UCHAR Reserved6;
|
||||
UCHAR ClearMask;
|
||||
UCHAR Reserved7;
|
||||
UCHAR AllMask;
|
||||
UCHAR Reserved8;
|
||||
} DMA2_CONTROL, *PDMA2_CONTROL;
|
||||
|
||||
/* This structure defines the I/O Map of the 82537 controller. */
|
||||
typedef struct _EISA_CONTROL
|
||||
{
|
||||
/* DMA Controller 1 */
|
||||
DMA1_CONTROL DmaController1; /* 00h-0Fh */
|
||||
UCHAR Reserved1[16]; /* 0Fh-1Fh */
|
||||
|
||||
/* Interrupt Controller 1 (PIC) */
|
||||
UCHAR Pic1Operation; /* 20h */
|
||||
UCHAR Pic1Interrupt; /* 21h */
|
||||
UCHAR Reserved2[30]; /* 22h-3Fh */
|
||||
|
||||
/* Timer */
|
||||
UCHAR TimerCounter; /* 40h */
|
||||
UCHAR TimerMemoryRefresh; /* 41h */
|
||||
UCHAR Speaker; /* 42h */
|
||||
UCHAR TimerOperation; /* 43h */
|
||||
UCHAR TimerMisc; /* 44h */
|
||||
UCHAR Reserved3[2]; /* 45-46h */
|
||||
UCHAR TimerCounterControl; /* 47h */
|
||||
UCHAR TimerFailSafeCounter; /* 48h */
|
||||
UCHAR Reserved4; /* 49h */
|
||||
UCHAR TimerCounter2; /* 4Ah */
|
||||
UCHAR TimerOperation2; /* 4Bh */
|
||||
UCHAR Reserved5[20]; /* 4Ch-5Fh */
|
||||
|
||||
/* NMI / Keyboard / RTC */
|
||||
UCHAR Keyboard; /* 60h */
|
||||
UCHAR NmiStatus; /* 61h */
|
||||
UCHAR Reserved6[14]; /* 62h-6Fh */
|
||||
UCHAR NmiEnable; /* 70h */
|
||||
UCHAR Reserved7[15]; /* 71h-7Fh */
|
||||
|
||||
/* DMA Page Registers Controller 1 */
|
||||
DMA_PAGE DmaController1Pages; /* 80h-8Fh */
|
||||
UCHAR Reserved8[16]; /* 90h-9Fh */
|
||||
|
||||
/* Interrupt Controller 2 (PIC) */
|
||||
UCHAR Pic2Operation; /* 0A0h */
|
||||
UCHAR Pic2Interrupt; /* 0A1h */
|
||||
UCHAR Reserved9[30]; /* 0A2h-0BFh */
|
||||
|
||||
/* DMA Controller 2 */
|
||||
DMA1_CONTROL DmaController2; /* 0C0h-0CFh */
|
||||
|
||||
/* System Reserved Ports */
|
||||
UCHAR SystemReserved[816]; /* 0D0h-3FFh */
|
||||
|
||||
/* Extended DMA Registers, Controller 1 */
|
||||
UCHAR DmaHighByteCount1[8]; /* 400h-407h */
|
||||
UCHAR Reserved10[2]; /* 408h-409h */
|
||||
UCHAR DmaChainMode1; /* 40Ah */
|
||||
UCHAR DmaExtendedMode1; /* 40Bh */
|
||||
UCHAR DmaBufferControl; /* 40Ch */
|
||||
UCHAR Reserved11[84]; /* 40Dh-460h */
|
||||
UCHAR ExtendedNmiControl; /* 461h */
|
||||
UCHAR NmiCommand; /* 462h */
|
||||
UCHAR Reserved12; /* 463h */
|
||||
UCHAR BusMaster; /* 464h */
|
||||
UCHAR Reserved13[27]; /* 465h-47Fh */
|
||||
|
||||
/* DMA Page Registers Controller 2 */
|
||||
DMA_PAGE DmaController2Pages; /* 480h-48Fh */
|
||||
UCHAR Reserved14[48]; /* 490h-4BFh */
|
||||
|
||||
/* Extended DMA Registers, Controller 2 */
|
||||
UCHAR DmaHighByteCount2[16]; /* 4C0h-4CFh */
|
||||
|
||||
/* Edge/Level Control Registers */
|
||||
UCHAR Pic1EdgeLevel; /* 4D0h */
|
||||
UCHAR Pic2EdgeLevel; /* 4D1h */
|
||||
UCHAR Reserved15[2]; /* 4D2h-4D3h */
|
||||
|
||||
/* Extended DMA Registers, Controller 2 */
|
||||
UCHAR DmaChainMode2; /* 4D4h */
|
||||
UCHAR Reserved16; /* 4D5h */
|
||||
UCHAR DmaExtendedMode2; /* 4D6h */
|
||||
UCHAR Reserved17[9]; /* 4D7h-4DFh */
|
||||
|
||||
/* DMA Stop Registers */
|
||||
DMA_CHANNEL_STOP DmaChannelStop[8]; /* 4E0h-4FFh */
|
||||
} EISA_CONTROL, *PEISA_CONTROL;
|
||||
|
||||
typedef struct _MAP_REGISTER_ENTRY
|
||||
{
|
||||
PVOID VirtualAddress;
|
||||
PHYSICAL_ADDRESS PhysicalAddress;
|
||||
ULONG Counter;
|
||||
} MAP_REGISTER_ENTRY, *PMAP_REGISTER_ENTRY;
|
||||
|
||||
struct _ADAPTER_OBJECT {
|
||||
/*
|
||||
* New style DMA object definition. The fact that it is at the beginning
|
||||
* of the ADAPTER_OBJECT structure allows us to easily implement the
|
||||
* fallback implementation of IoGetDmaAdapter.
|
||||
*/
|
||||
DMA_ADAPTER DmaHeader;
|
||||
|
||||
/*
|
||||
* For normal adapter objects pointer to master adapter that takes care
|
||||
* of channel allocation. For master adapter set to NULL.
|
||||
*/
|
||||
struct _ADAPTER_OBJECT *MasterAdapter;
|
||||
|
||||
ULONG MapRegistersPerChannel;
|
||||
PVOID AdapterBaseVa;
|
||||
PMAP_REGISTER_ENTRY MapRegisterBase;
|
||||
|
||||
ULONG NumberOfMapRegisters;
|
||||
ULONG CommittedMapRegisters;
|
||||
|
||||
PWAIT_CONTEXT_BLOCK CurrentWcb;
|
||||
KDEVICE_QUEUE ChannelWaitQueue;
|
||||
PKDEVICE_QUEUE RegisterWaitQueue;
|
||||
LIST_ENTRY AdapterQueue;
|
||||
KSPIN_LOCK SpinLock;
|
||||
PRTL_BITMAP MapRegisters;
|
||||
PUCHAR PagePort;
|
||||
UCHAR ChannelNumber;
|
||||
UCHAR AdapterNumber;
|
||||
USHORT DmaPortAddress;
|
||||
DMA_MODE AdapterMode;
|
||||
BOOLEAN NeedsMapRegisters;
|
||||
BOOLEAN MasterDevice;
|
||||
BOOLEAN Width16Bits;
|
||||
BOOLEAN ScatterGather;
|
||||
BOOLEAN IgnoreCount;
|
||||
BOOLEAN Dma32BitAddresses;
|
||||
BOOLEAN Dma64BitAddresses;
|
||||
LIST_ENTRY AdapterList;
|
||||
} ADAPTER_OBJECT;
|
||||
|
||||
typedef struct _GROW_WORK_ITEM {
|
||||
WORK_QUEUE_ITEM WorkQueueItem;
|
||||
PADAPTER_OBJECT AdapterObject;
|
||||
ULONG NumberOfMapRegisters;
|
||||
} GROW_WORK_ITEM, *PGROW_WORK_ITEM;
|
||||
|
||||
#define MAP_BASE_SW_SG 1
|
||||
|
||||
PADAPTER_OBJECT STDCALL
|
||||
HalpDmaAllocateMasterAdapter(VOID);
|
||||
|
||||
VOID STDCALL
|
||||
HalPutDmaAdapter(
|
||||
PADAPTER_OBJECT AdapterObject);
|
||||
|
||||
ULONG STDCALL
|
||||
HalpDmaGetDmaAlignment(
|
||||
PADAPTER_OBJECT AdapterObject);
|
||||
|
||||
NTSTATUS STDCALL
|
||||
IoAllocateAdapterChannel(
|
||||
IN PADAPTER_OBJECT AdapterObject,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN ULONG NumberOfMapRegisters,
|
||||
IN PDRIVER_CONTROL ExecutionRoutine,
|
||||
IN PVOID Context);
|
||||
|
||||
#endif /* HALDMA_H */
|
|
@ -40,358 +40,6 @@ PVOID HalpMapPhysMemory(ULONG PhysAddr, ULONG Size);
|
|||
/* Non-generic initialization */
|
||||
VOID HalpInitPhase0 (PLOADER_PARAMETER_BLOCK LoaderBlock);
|
||||
|
||||
/* DMA Page Register Structure
|
||||
080 DMA RESERVED
|
||||
081 DMA Page Register (channel 2)
|
||||
082 DMA Page Register (channel 3)
|
||||
083 DMA Page Register (channel 1)
|
||||
084 DMA RESERVED
|
||||
085 DMA RESERVED
|
||||
086 DMA RESERVED
|
||||
087 DMA Page Register (channel 0)
|
||||
088 DMA RESERVED
|
||||
089 PS/2-DMA Page Register (channel 6)
|
||||
08A PS/2-DMA Page Register (channel 7)
|
||||
08B PS/2-DMA Page Register (channel 5)
|
||||
08C PS/2-DMA RESERVED
|
||||
08D PS/2-DMA RESERVED
|
||||
08E PS/2-DMA RESERVED
|
||||
08F PS/2-DMA Page Register (channel 4)
|
||||
*/
|
||||
typedef struct _DMA_PAGE{
|
||||
UCHAR Reserved1;
|
||||
UCHAR Channel2;
|
||||
UCHAR Channel3;
|
||||
UCHAR Channel1;
|
||||
UCHAR Reserved2[3];
|
||||
UCHAR Channel0;
|
||||
UCHAR Reserved3;
|
||||
UCHAR Channel6;
|
||||
UCHAR Channel7;
|
||||
UCHAR Channel5;
|
||||
UCHAR Reserved4[3];
|
||||
UCHAR Channel4;
|
||||
} DMA_PAGE, *PDMA_PAGE;
|
||||
|
||||
/* DMA Channel Mask Register Structure
|
||||
|
||||
MSB LSB
|
||||
x x x x x x x x
|
||||
------------------- - -----
|
||||
| | | 00 - Select channel 0 mask bit
|
||||
| | \---- 01 - Select channel 1 mask bit
|
||||
| | 10 - Select channel 2 mask bit
|
||||
| | 11 - Select channel 3 mask bit
|
||||
| |
|
||||
| \---------- 0 - Clear mask bit
|
||||
| 1 - Set mask bit
|
||||
|
|
||||
\----------------------- xx - Reserved
|
||||
*/
|
||||
typedef struct _DMA_CHANNEL_MASK {
|
||||
UCHAR Channel : 2;
|
||||
UCHAR SetMask : 1;
|
||||
UCHAR Reserved : 5;
|
||||
} DMA_CHANNEL_MASK, *PDMA_CHANNEL_MASK;
|
||||
|
||||
/* DMA Mask Register Structure
|
||||
|
||||
MSB LSB
|
||||
x x x x x x x x
|
||||
\---/ - - ----- -----
|
||||
| | | | | 00 - Channel 0 select
|
||||
| | | | \---- 01 - Channel 1 select
|
||||
| | | | 10 - Channel 2 select
|
||||
| | | | 11 - Channel 3 select
|
||||
| | | |
|
||||
| | | | 00 - Verify transfer
|
||||
| | | \------------ 01 - Write transfer
|
||||
| | | 10 - Read transfer
|
||||
| | |
|
||||
| | \-------------------- 0 - Autoinitialized
|
||||
| | 1 - Non-autoinitialized
|
||||
| |
|
||||
| \------------------------ 0 - Address increment select
|
||||
|
|
||||
| 00 - Demand mode
|
||||
\------------------------------ 01 - Single mode
|
||||
10 - Block mode
|
||||
11 - Cascade mode
|
||||
*/
|
||||
typedef struct _DMA_MODE {
|
||||
UCHAR Channel : 2;
|
||||
UCHAR TransferType : 2;
|
||||
UCHAR AutoInitialize : 1;
|
||||
UCHAR AddressDecrement : 1;
|
||||
UCHAR RequestMode : 2;
|
||||
} DMA_MODE, *PDMA_MODE;
|
||||
|
||||
|
||||
/* DMA Extended Mode Register Structure
|
||||
|
||||
MSB LSB
|
||||
x x x x x x x x
|
||||
- - ----- ----- -----
|
||||
| | | | | 00 - Channel 0 select
|
||||
| | | | \---- 01 - Channel 1 select
|
||||
| | | | 10 - Channel 2 select
|
||||
| | | | 11 - Channel 3 select
|
||||
| | | |
|
||||
| | | | 00 - 8-bit I/O, by bytes
|
||||
| | | \------------ 01 - 16-bit I/O, by words, address shifted
|
||||
| | | 10 - 32-bit I/O, by bytes
|
||||
| | | 11 - 16-bit I/O, by bytes
|
||||
| | |
|
||||
| | \---------------------- 00 - Compatible
|
||||
| | 01 - Type A
|
||||
| | 10 - Type B
|
||||
| | 11 - Burst
|
||||
| |
|
||||
| \---------------------------- 0 - Terminal Count is Output
|
||||
|
|
||||
\---------------------------------0 - Disable Stop Register
|
||||
1 - Enable Stop Register
|
||||
*/
|
||||
typedef struct _DMA_EXTENDED_MODE {
|
||||
UCHAR ChannelNumber : 2;
|
||||
UCHAR TransferSize : 2;
|
||||
UCHAR TimingMode : 2;
|
||||
UCHAR TerminalCountIsOutput : 1;
|
||||
UCHAR EnableStopRegister : 1;
|
||||
}DMA_EXTENDED_MODE, *PDMA_EXTENDED_MODE;
|
||||
|
||||
/* DMA Extended Mode Register Transfer Sizes */
|
||||
#define B_8BITS 0
|
||||
#define W_16BITS 1
|
||||
#define B_32BITS 2
|
||||
#define B_16BITS 3
|
||||
|
||||
/* DMA Extended Mode Register Timing */
|
||||
#define COMPATIBLE_TIMING 0
|
||||
#define TYPE_A_TIMING 1
|
||||
#define TYPE_B_TIMING 2
|
||||
#define BURST_TIMING 3
|
||||
|
||||
/* Channel Stop Registers for each Channel */
|
||||
typedef struct _DMA_CHANNEL_STOP {
|
||||
UCHAR ChannelLow;
|
||||
UCHAR ChannelMid;
|
||||
UCHAR ChannelHigh;
|
||||
UCHAR Reserved;
|
||||
} DMA_CHANNEL_STOP, *PDMA_CHANNEL_STOP;
|
||||
|
||||
/* Transfer Types */
|
||||
#define VERIFY_TRANSFER 0x00
|
||||
#define READ_TRANSFER 0x01
|
||||
#define WRITE_TRANSFER 0x02
|
||||
|
||||
/* Request Modes */
|
||||
#define DEMAND_REQUEST_MODE 0x00
|
||||
#define SINGLE_REQUEST_MODE 0x01
|
||||
#define BLOCK_REQUEST_MODE 0x02
|
||||
#define CASCADE_REQUEST_MODE 0x03
|
||||
|
||||
#define DMA_SETMASK 4
|
||||
#define DMA_CLEARMASK 0
|
||||
#define DMA_READ 4
|
||||
#define DMA_WRITE 8
|
||||
#define DMA_SINGLE_TRANSFER 0x40
|
||||
#define DMA_AUTO_INIT 0x10
|
||||
|
||||
typedef struct _DMA1_ADDRESS_COUNT {
|
||||
UCHAR DmaBaseAddress;
|
||||
UCHAR DmaBaseCount;
|
||||
} DMA1_ADDRESS_COUNT, *PDMA1_ADDRESS_COUNT;
|
||||
|
||||
typedef struct _DMA2_ADDRESS_COUNT {
|
||||
UCHAR DmaBaseAddress;
|
||||
UCHAR Reserved1;
|
||||
UCHAR DmaBaseCount;
|
||||
UCHAR Reserved2;
|
||||
} DMA2_ADDRESS_COUNT, *PDMA2_ADDRESS_COUNT;
|
||||
|
||||
typedef struct _DMA1_CONTROL {
|
||||
DMA1_ADDRESS_COUNT DmaAddressCount[4];
|
||||
UCHAR DmaStatus;
|
||||
UCHAR DmaRequest;
|
||||
UCHAR SingleMask;
|
||||
UCHAR Mode;
|
||||
UCHAR ClearBytePointer;
|
||||
UCHAR MasterClear;
|
||||
UCHAR ClearMask;
|
||||
UCHAR AllMask;
|
||||
} DMA1_CONTROL, *PDMA1_CONTROL;
|
||||
|
||||
typedef struct _DMA2_CONTROL {
|
||||
DMA2_ADDRESS_COUNT DmaAddressCount[4];
|
||||
UCHAR DmaStatus;
|
||||
UCHAR Reserved1;
|
||||
UCHAR DmaRequest;
|
||||
UCHAR Reserved2;
|
||||
UCHAR SingleMask;
|
||||
UCHAR Reserved3;
|
||||
UCHAR Mode;
|
||||
UCHAR Reserved4;
|
||||
UCHAR ClearBytePointer;
|
||||
UCHAR Reserved5;
|
||||
UCHAR MasterClear;
|
||||
UCHAR Reserved6;
|
||||
UCHAR ClearMask;
|
||||
UCHAR Reserved7;
|
||||
UCHAR AllMask;
|
||||
UCHAR Reserved8;
|
||||
} DMA2_CONTROL, *PDMA2_CONTROL;
|
||||
|
||||
/* This Structure Defines the I/O Map of the 82537 Controller
|
||||
I've only defined the registers which are likely to be useful to us */
|
||||
typedef struct _EISA_CONTROL {
|
||||
/* DMA Controller 1 */
|
||||
DMA1_CONTROL DmaController1; /* 00h-0Fh */
|
||||
UCHAR Reserved1[16]; /* 0Fh-1Fh */
|
||||
|
||||
/* Interrupt Controller 1 (PIC) */
|
||||
UCHAR Pic1Operation; /* 20h */
|
||||
UCHAR Pic1Interrupt; /* 21h */
|
||||
UCHAR Reserved2[30]; /* 22h-3Fh */
|
||||
|
||||
/* Timer */
|
||||
UCHAR TimerCounter; /* 40h */
|
||||
UCHAR TimerMemoryRefresh; /* 41h */
|
||||
UCHAR Speaker; /* 42h */
|
||||
UCHAR TimerOperation; /* 43h */
|
||||
UCHAR TimerMisc; /* 44h */
|
||||
UCHAR Reserved3[2]; /* 45-46h */
|
||||
UCHAR TimerCounterControl; /* 47h */
|
||||
UCHAR TimerFailSafeCounter; /* 48h */
|
||||
UCHAR Reserved4; /* 49h */
|
||||
UCHAR TimerCounter2; /* 4Ah */
|
||||
UCHAR TimerOperation2; /* 4Bh */
|
||||
UCHAR Reserved5[20]; /* 4Ch-5Fh */
|
||||
|
||||
/* NMI / Keyboard / RTC */
|
||||
UCHAR Keyboard; /* 60h */
|
||||
UCHAR NmiStatus; /* 61h */
|
||||
UCHAR Reserved6[14]; /* 62h-6Fh */
|
||||
UCHAR NmiEnable; /* 70h */
|
||||
UCHAR Reserved7[15]; /* 71h-7Fh */
|
||||
|
||||
/* DMA Page Registers Controller 1 */
|
||||
DMA_PAGE DmaController1Pages; /* 80h-8Fh */
|
||||
UCHAR Reserved8[16]; /* 90h-9Fh */
|
||||
|
||||
/* Interrupt Controller 2 (PIC) */
|
||||
UCHAR Pic2Operation; /* 0A0h */
|
||||
UCHAR Pic2Interrupt; /* 0A1h */
|
||||
UCHAR Reserved9[30]; /* 0A2h-0BFh */
|
||||
|
||||
/* DMA Controller 2 */
|
||||
DMA1_CONTROL DmaController2; /* 0C0h-0CFh */
|
||||
|
||||
/* System Reserved Ports */
|
||||
UCHAR SystemReserved[816]; /* 0D0h-3FFh */
|
||||
|
||||
/* Extended DMA Registers, Controller 1 */
|
||||
UCHAR DmaHighByteCount1[8]; /* 400h-407h */
|
||||
UCHAR Reserved10[2]; /* 408h-409h */
|
||||
UCHAR DmaChainMode1; /* 40Ah */
|
||||
UCHAR DmaExtendedMode1; /* 40Bh */
|
||||
UCHAR DmaBufferControl; /* 40Ch */
|
||||
UCHAR Reserved11[84]; /* 40Dh-460h */
|
||||
UCHAR ExtendedNmiControl; /* 461h */
|
||||
UCHAR NmiCommand; /* 462h */
|
||||
UCHAR Reserved12; /* 463h */
|
||||
UCHAR BusMaster; /* 464h */
|
||||
UCHAR Reserved13[27]; /* 465h-47Fh */
|
||||
|
||||
/* DMA Page Registers Controller 2 */
|
||||
DMA_PAGE DmaController2Pages; /* 480h-48Fh */
|
||||
UCHAR Reserved14[48]; /* 490h-4BFh */
|
||||
|
||||
/* Extended DMA Registers, Controller 2 */
|
||||
UCHAR DmaHighByteCount2[16]; /* 4C0h-4CFh */
|
||||
|
||||
/* Edge/Level Control Registers */
|
||||
UCHAR Pic1EdgeLevel; /* 4D0h */
|
||||
UCHAR Pic2EdgeLevel; /* 4D1h */
|
||||
UCHAR Reserved15[2]; /* 4D2h-4D3h */
|
||||
|
||||
/* Extended DMA Registers, Controller 2 */
|
||||
UCHAR DmaChainMode2; /* 4D4h */
|
||||
UCHAR Reserved16; /* 4D5h */
|
||||
UCHAR DmaExtendedMode2; /* 4D6h */
|
||||
UCHAR Reserved17[9]; /* 4D7h-4DFh */
|
||||
|
||||
/* DMA Stop Registers */
|
||||
DMA_CHANNEL_STOP DmaChannelStop[8]; /* 4E0h-4FFh */
|
||||
} EISA_CONTROL, *PEISA_CONTROL;
|
||||
|
||||
extern ULONG HalpEisaDma;
|
||||
extern PADAPTER_OBJECT MasterAdapter;
|
||||
|
||||
ULONG HalpEisaDma;
|
||||
PADAPTER_OBJECT MasterAdapter;
|
||||
|
||||
/*
|
||||
* ADAPTER_OBJECT - Track a busmaster DMA adapter and its associated resources
|
||||
*
|
||||
* NOTES:
|
||||
* - I've updated this to the Windows Object Defintion.
|
||||
*/
|
||||
struct _ADAPTER_OBJECT {
|
||||
DMA_ADAPTER DmaHeader;
|
||||
struct _ADAPTER_OBJECT *MasterAdapter;
|
||||
ULONG MapRegistersPerChannel;
|
||||
PVOID AdapterBaseVa;
|
||||
PVOID MapRegisterBase;
|
||||
ULONG NumberOfMapRegisters;
|
||||
ULONG CommittedMapRegisters;
|
||||
PWAIT_CONTEXT_BLOCK CurrentWcb;
|
||||
KDEVICE_QUEUE ChannelWaitQueue;
|
||||
PKDEVICE_QUEUE RegisterWaitQueue;
|
||||
LIST_ENTRY AdapterQueue;
|
||||
ULONG SpinLock;
|
||||
PRTL_BITMAP MapRegisters;
|
||||
PUCHAR PagePort;
|
||||
UCHAR ChannelNumber;
|
||||
UCHAR AdapterNumber;
|
||||
USHORT DmaPortAddress;
|
||||
union {
|
||||
DMA_MODE AdapterMode;
|
||||
UCHAR AdapterModeByte;
|
||||
};
|
||||
BOOLEAN NeedsMapRegisters;
|
||||
BOOLEAN MasterDevice;
|
||||
UCHAR Width16Bits;
|
||||
UCHAR ScatterGather;
|
||||
UCHAR IgnoreCount;
|
||||
UCHAR Dma32BitAddresses;
|
||||
UCHAR Dma64BitAddresses;
|
||||
BOOLEAN LegacyAdapter;
|
||||
LIST_ENTRY AdapterList;
|
||||
} ADAPTER_OBJECT;
|
||||
|
||||
/*
|
||||
struct _ADAPTER_OBJECT {
|
||||
INTERFACE_TYPE InterfaceType;
|
||||
BOOLEAN Master;
|
||||
int Channel;
|
||||
PVOID PagePort;
|
||||
PVOID CountPort;
|
||||
PVOID OffsetPort;
|
||||
KSPIN_LOCK SpinLock;
|
||||
PVOID Buffer;
|
||||
BOOLEAN Inuse;
|
||||
ULONG AvailableMapRegisters;
|
||||
PVOID MapRegisterBase;
|
||||
ULONG AllocatedMapRegisters;
|
||||
PWAIT_CONTEXT_BLOCK WaitContextBlock;
|
||||
KDEVICE_QUEUE DeviceQueue;
|
||||
BOOLEAN ScatterGather;
|
||||
BOOLEAN DemandMode;
|
||||
BOOLEAN AutoInitialize;
|
||||
};
|
||||
*/
|
||||
|
||||
/* sysinfo.c */
|
||||
NTSTATUS STDCALL
|
||||
HalpQuerySystemInformation(IN HAL_QUERY_INFORMATION_CLASS InformationClass,
|
||||
|
@ -399,7 +47,6 @@ HalpQuerySystemInformation(IN HAL_QUERY_INFORMATION_CLASS InformationClass,
|
|||
IN OUT PVOID Buffer,
|
||||
OUT PULONG ReturnedLength);
|
||||
|
||||
|
||||
/* Non-standard functions */
|
||||
VOID STDCALL
|
||||
HalReleaseDisplayOwnership();
|
||||
|
|
Loading…
Reference in a new issue