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:
Filip Navara 2005-08-22 08:39:42 +00:00
parent 1fb85e029e
commit a0b8ef87a8
8 changed files with 2239 additions and 1484 deletions

View file

@ -211,10 +211,7 @@ HalFlushCommonBuffer(
ULONG Unknown2,
ULONG Unknown3,
ULONG Unknown4,
ULONG Unknown5,
ULONG Unknown6,
ULONG Unknown7,
ULONG Unknown8)
ULONG Unknown5)
{
UNIMPLEMENTED;

View file

@ -20,7 +20,7 @@ HalDisableSystemInterrupt@8
HalDisplayString@4
HalEnableSystemInterrupt@12
HalEndSystemInterrupt@8
HalFlushCommonBuffer@32
HalFlushCommonBuffer@20
HalFreeCommonBuffer@24
HalGetAdapter@8
HalGetBusData@20

View file

@ -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

View file

@ -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>

View 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"

View 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 */

View file

@ -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();