reactos/reactos/hal/halx86/adapter.c
Casper Hornstrup 36402e5aa4 Module wide .cvsignore for:
*.sys, *.exe, *.dll, *.a, *.o, *.coff

Seperated the HALs from ntoskrnl.exe

Added template HAL

svn path=/trunk/; revision=2186
2001-08-21 20:18:27 +00:00

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