mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 11:43:04 +00:00

*.sys, *.exe, *.dll, *.a, *.o, *.coff Seperated the HALs from ntoskrnl.exe Added template HAL svn path=/trunk/; revision=2186
154 lines
4.7 KiB
C
154 lines
4.7 KiB
C
/* $Id: adapter.c,v 1.1 2001/08/21 20:18:26 chorns Exp $
|
|
*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: hal/x86/adapter.c (from ntoskrnl/io/adapter.c)
|
|
* PURPOSE: DMA handling
|
|
* PROGRAMMER: David Welch (welch@mcmail.com)
|
|
* UPDATE HISTORY:
|
|
* Created 22/05/98
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include <ddk/ntddk.h>
|
|
#include <ddk/iotypes.h>
|
|
#include <internal/debug.h>
|
|
#include <hal.h>
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
/* NOTE: IoAllocateAdapterChannel in NTOSKRNL.EXE */
|
|
|
|
NTSTATUS STDCALL
|
|
HalAllocateAdapterChannel(PADAPTER_OBJECT AdapterObject,
|
|
PDEVICE_OBJECT DeviceObject,
|
|
ULONG NumberOfMapRegisters,
|
|
PDRIVER_CONTROL ExecutionRoutine,
|
|
PVOID Context )
|
|
{
|
|
KIRQL OldIrql;
|
|
PVOID Buffer;
|
|
int ret;
|
|
LARGE_INTEGER MaxAddress;
|
|
|
|
MaxAddress.QuadPart = 0x1000000;
|
|
Buffer = MmAllocateContiguousAlignedMemory( NumberOfMapRegisters * PAGESIZE,
|
|
MaxAddress,
|
|
0x10000 );
|
|
if( !Buffer )
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
KeAcquireSpinLock( &AdapterObject->SpinLock, &OldIrql );
|
|
if( AdapterObject->Inuse )
|
|
{
|
|
// someone is already using it, we need to wait
|
|
// create a wait block, and add it to the chain
|
|
UNIMPLEMENTED;
|
|
}
|
|
else {
|
|
AdapterObject->Inuse = TRUE;
|
|
KeReleaseSpinLock( &AdapterObject->SpinLock, OldIrql );
|
|
ret = ExecutionRoutine( DeviceObject,
|
|
NULL,
|
|
Buffer,
|
|
Context );
|
|
KeAcquireSpinLock( &AdapterObject->SpinLock, &OldIrql );
|
|
if( ret == DeallocateObject )
|
|
{
|
|
MmFreeContiguousMemory( Buffer );
|
|
AdapterObject->Inuse = FALSE;
|
|
}
|
|
else AdapterObject->Buffer = Buffer;
|
|
}
|
|
KeReleaseSpinLock( &AdapterObject->SpinLock, OldIrql );
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
BOOLEAN STDCALL
|
|
IoFlushAdapterBuffers (PADAPTER_OBJECT AdapterObject,
|
|
PMDL Mdl,
|
|
PVOID MapRegisterBase,
|
|
PVOID CurrentVa,
|
|
ULONG Length,
|
|
BOOLEAN WriteToDevice)
|
|
{
|
|
// if this was a read from device, copy data back to caller buffer, otherwise, do nothing
|
|
if( !WriteToDevice )
|
|
memcpy( (PVOID)((DWORD)MmGetSystemAddressForMdl( Mdl ) + (DWORD)CurrentVa - (DWORD)MmGetMdlVirtualAddress( Mdl )), MapRegisterBase, Length );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID STDCALL
|
|
IoFreeAdapterChannel (PADAPTER_OBJECT AdapterObject)
|
|
{
|
|
KIRQL OldIrql;
|
|
|
|
KeAcquireSpinLock( &AdapterObject->SpinLock, &OldIrql );
|
|
if( AdapterObject->Inuse == FALSE )
|
|
{
|
|
DbgPrint( "Attempting to IoFreeAdapterChannel on a channel not in use\n" );
|
|
KeBugCheck(0);
|
|
}
|
|
AdapterObject->Inuse = FALSE;
|
|
if( AdapterObject->Buffer )
|
|
{
|
|
MmFreeContiguousMemory( AdapterObject->Buffer );
|
|
AdapterObject->Buffer = 0;
|
|
}
|
|
KeReleaseSpinLock( &AdapterObject->SpinLock, OldIrql );
|
|
}
|
|
|
|
|
|
VOID STDCALL
|
|
IoFreeMapRegisters (PADAPTER_OBJECT AdapterObject,
|
|
PVOID MapRegisterBase,
|
|
ULONG NumberOfMapRegisters)
|
|
{
|
|
UNIMPLEMENTED;
|
|
}
|
|
|
|
|
|
PHYSICAL_ADDRESS STDCALL
|
|
IoMapTransfer (PADAPTER_OBJECT AdapterObject,
|
|
PMDL Mdl,
|
|
PVOID MapRegisterBase,
|
|
PVOID CurrentVa,
|
|
PULONG Length,
|
|
BOOLEAN WriteToDevice)
|
|
{
|
|
PHYSICAL_ADDRESS Address;
|
|
// program up the dma controller, and return
|
|
// if it is a write to the device, copy the caller buffer to the low buffer
|
|
if( WriteToDevice )
|
|
memcpy( MapRegisterBase,
|
|
MmGetSystemAddressForMdl( Mdl ) + ( (DWORD)CurrentVa - (DWORD)MmGetMdlVirtualAddress( Mdl ) ),
|
|
*Length );
|
|
Address = MmGetPhysicalAddress( MapRegisterBase );
|
|
// port 0xA is the dma mask register, or a 0x10 on to the channel number to mask it
|
|
WRITE_PORT_UCHAR( (PVOID)0x0A, AdapterObject->Channel | 0x10 );
|
|
// write zero to the reset register
|
|
WRITE_PORT_UCHAR( (PVOID)0x0C, 0 );
|
|
// mode register, or channel with 0x4 for write memory, 0x8 for read memory, 0x10 for non auto initialize
|
|
WRITE_PORT_UCHAR( (PVOID)0x0B, AdapterObject->Channel | ( WriteToDevice ? 0x8 : 0x4 ) );
|
|
// set the 64k page register for the channel
|
|
WRITE_PORT_UCHAR( AdapterObject->PagePort, (UCHAR)(((ULONG)Address.QuadPart)>>16) );
|
|
// low, then high address byte, which is always 0 for us, because we have a 64k alligned address
|
|
WRITE_PORT_UCHAR( AdapterObject->OffsetPort, 0 );
|
|
WRITE_PORT_UCHAR( AdapterObject->OffsetPort, 0 );
|
|
// count is 1 less than length, low then high
|
|
WRITE_PORT_UCHAR( AdapterObject->CountPort, (UCHAR)(*Length - 1) );
|
|
WRITE_PORT_UCHAR( AdapterObject->CountPort, (UCHAR)((*Length - 1)>>8) );
|
|
// unmask the channel to let it rip
|
|
WRITE_PORT_UCHAR( (PVOID)0x0A, AdapterObject->Channel );
|
|
Address.QuadPart = (DWORD)MapRegisterBase;
|
|
return Address;
|
|
}
|
|
|
|
|
|
/* EOF */
|
|
|
|
|
|
|
|
|