mirror of
https://github.com/reactos/reactos.git
synced 2024-10-01 23:14:53 +00:00
- Implementation of HalReadDmaCounter.
- Cleaned up implementation of HalGetAdapter. Moved the initialization stuff from there to HalpInitDma that is called by HalInitSystem. - Let HalAllocateCommonBuffer allocated 64K aligned memory. - Change IoMapTransfer to support auto initialize and single transfer mode, 16-bit DMA and common buffers. - Stop DMA transfer in IoFlushAdapterBuffers. svn path=/trunk/; revision=10254
This commit is contained in:
parent
ec5f846d4c
commit
6e64d6266e
|
@ -1,4 +1,4 @@
|
|||
/* $Id: adapter.c,v 1.10 2003/12/31 05:33:03 jfilby Exp $
|
||||
/* $Id: adapter.c,v 1.11 2004/07/22 18:49:18 navaraf Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -66,7 +66,7 @@ HalAllocateAdapterChannel(
|
|||
WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
|
||||
|
||||
/* returns true if queued, else returns false and sets the queue to busy */
|
||||
if(KeInsertDeviceQueue(&AdapterObject->DeviceQueue, (PKDEVICE_QUEUE_ENTRY)WaitContextBlock))
|
||||
if(KeInsertDeviceQueue(&AdapterObject->DeviceQueue, &WaitContextBlock->WaitQueueEntry))
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
/* 24-bit max address due to 16-bit dma controllers */
|
||||
|
@ -79,6 +79,10 @@ HalAllocateAdapterChannel(
|
|||
* 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.
|
||||
*/
|
||||
AdapterObject->MapRegisterBase = MmAllocateContiguousAlignedMemory(
|
||||
NumberOfMapRegisters * PAGE_SIZE,
|
||||
|
@ -159,6 +163,12 @@ IoFlushAdapterBuffers (
|
|||
if(!MapRegisterBase)
|
||||
return TRUE;
|
||||
|
||||
/* mask out (disable) the dma channel */
|
||||
if (AdapterObject->Channel < 4)
|
||||
WRITE_PORT_UCHAR( (PVOID)0x0A, (UCHAR)(AdapterObject->Channel | 0x4) );
|
||||
else
|
||||
WRITE_PORT_UCHAR( (PVOID)0xD4, (UCHAR)((AdapterObject->Channel - 4) | 0x4) );
|
||||
|
||||
if(WriteToDevice)
|
||||
return TRUE;
|
||||
|
||||
|
@ -166,19 +176,6 @@ IoFlushAdapterBuffers (
|
|||
(PVOID)((DWORD)MmGetSystemAddressForMdl( Mdl ) + (DWORD)CurrentVa - (DWORD)MmGetMdlVirtualAddress( Mdl )),
|
||||
MapRegisterBase, Length );
|
||||
|
||||
/*
|
||||
FIXME: mask off (disable) channel if doing System DMA?
|
||||
|
||||
From linux:
|
||||
|
||||
if (dmanr<=3)
|
||||
dma_outb(dmanr | 4, DMA1_MASK_REG 0x0A) ;
|
||||
else
|
||||
dma_outb((dmanr & 3) | 4, DMA2_MASK_REG 0x0A);
|
||||
|
||||
*/
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -305,6 +302,10 @@ IoMapTransfer (
|
|||
*/
|
||||
{
|
||||
PHYSICAL_ADDRESS Address;
|
||||
PVOID MaskReg, ClearReg, ModeReg;
|
||||
UCHAR ModeMask, LengthShift;
|
||||
KIRQL OldIrql;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
Address.QuadPart = 0ULL;
|
||||
#else
|
||||
|
@ -321,38 +322,76 @@ IoMapTransfer (
|
|||
assert(AdapterObject->Channel != 4);
|
||||
#endif
|
||||
|
||||
KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
|
||||
|
||||
/*
|
||||
FIXME: Handle case when doing common-buffer System DMA. In this case, the buffer described
|
||||
by MDL is allready phys. contiguous and below 16 mega. Driver makes a one-shot call to
|
||||
IoMapTransfer during init. to program controller with the common-buffer.
|
||||
* 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 )
|
||||
if( WriteToDevice && !AdapterObject->AutoInitialize )
|
||||
{
|
||||
memcpy(MapRegisterBase,
|
||||
(char*)MmGetSystemAddressForMdl(Mdl) + ((ULONG)CurrentVa - (ULONG)MmGetMdlVirtualAddress(Mdl)),
|
||||
*Length );
|
||||
}
|
||||
|
||||
// 16-bit DMA
|
||||
if( AdapterObject->Channel >= 4 )
|
||||
{
|
||||
MaskReg = (PVOID)0xD4; ClearReg = (PVOID)0xD8; ModeReg = (PVOID)0xD6;
|
||||
LengthShift = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaskReg = (PVOID)0x0A; ClearReg = (PVOID)0x0C; ModeReg = (PVOID)0x0B;
|
||||
LengthShift = 0;
|
||||
}
|
||||
|
||||
// calculate the mask we will later set to the mode register
|
||||
ModeMask = (AdapterObject->Channel & 3) | ( WriteToDevice ? 0x8 : 0x4 );
|
||||
// FIXME: if not demand mode, which mode to use? 0x40 for single mode
|
||||
if (!AdapterObject->DemandMode)
|
||||
ModeMask |= 0x40;
|
||||
if (AdapterObject->AutoInitialize)
|
||||
ModeMask |= 0x10;
|
||||
|
||||
// program up the dma controller, and return
|
||||
if (!AdapterObject->AutoInitialize)
|
||||
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, (UCHAR)(AdapterObject->Channel | 0x10));
|
||||
else
|
||||
Address = MmGetPhysicalAddress( CurrentVa );
|
||||
// disable and select the channel number
|
||||
WRITE_PORT_UCHAR( MaskReg, (UCHAR)((AdapterObject->Channel & 3) | 0x4) );
|
||||
// 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, (UCHAR)(AdapterObject->Channel | ( WriteToDevice ? 0x8 : 0x4 )) );
|
||||
WRITE_PORT_UCHAR( ClearReg, 0 );
|
||||
// mode register, or channel with 0x4 for write memory, 0x8 for read memory, 0x10 for auto initialize
|
||||
WRITE_PORT_UCHAR( ModeReg, ModeMask);
|
||||
// set the 64k page register for the channel
|
||||
WRITE_PORT_UCHAR( AdapterObject->PagePort, (UCHAR)(((ULONG)Address.QuadPart)>>16) );
|
||||
WRITE_PORT_UCHAR( AdapterObject->PagePort, (UCHAR)(Address.u.LowPart >> 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) );
|
||||
WRITE_PORT_UCHAR( AdapterObject->CountPort, (UCHAR)((*Length >> LengthShift) - 1) );
|
||||
WRITE_PORT_UCHAR( AdapterObject->CountPort, (UCHAR)(((*Length >> LengthShift) - 1)>>8) );
|
||||
// unmask the channel to let it rip
|
||||
WRITE_PORT_UCHAR( (PVOID)0x0A, (UCHAR)AdapterObject->Channel );
|
||||
WRITE_PORT_UCHAR( MaskReg, AdapterObject->Channel & 3 );
|
||||
|
||||
KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
|
||||
|
||||
/*
|
||||
NOTE: Return value should be ignored when doing System DMA.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: dma.c,v 1.8 2003/10/23 09:03:51 vizzini Exp $
|
||||
/* $Id: dma.c,v 1.9 2004/07/22 18:49:18 navaraf Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -18,21 +18,38 @@
|
|||
|
||||
/* XXX This initialization is out of date - ADAPTER_OBJECT has changed */
|
||||
/* NOTE: The following initializations have to be kept in synch with ADAPTER_OBJECT in hal.h */
|
||||
/* FIXME: we need the 16-bit dma channels */
|
||||
ADAPTER_OBJECT IsaSlaveAdapterObjects[] = {
|
||||
{ Isa, FALSE, 0, (PVOID)0x87, (PVOID)0x1, (PVOID)0x0, 0, NULL },
|
||||
{ Isa, FALSE, 1, (PVOID)0x83, (PVOID)0x3, (PVOID)0x2, 0, NULL },
|
||||
{ Isa, FALSE, 2, (PVOID)0x81, (PVOID)0x5, (PVOID)0x4, 0, NULL },
|
||||
{ Isa, FALSE, 3, (PVOID)0x82, (PVOID)0x7, (PVOID)0x6, 0, NULL } };
|
||||
{ Isa, FALSE, 3, (PVOID)0x82, (PVOID)0x7, (PVOID)0x6, 0, NULL },
|
||||
/* 16-bit DMA */
|
||||
{ Isa, FALSE, 4, (PVOID)0x8F, (PVOID)0xC2, (PVOID)0xC0, 0, NULL },
|
||||
{ Isa, FALSE, 5, (PVOID)0x8B, (PVOID)0xC6, (PVOID)0xC4, 0, NULL },
|
||||
{ Isa, FALSE, 6, (PVOID)0x89, (PVOID)0xCA, (PVOID)0xC8, 0, NULL },
|
||||
{ Isa, FALSE, 7, (PVOID)0x8A, (PVOID)0xCE, (PVOID)0xCC, 0, NULL } };
|
||||
|
||||
ADAPTER_OBJECT PciBusMasterAdapterObjects[] = {
|
||||
{ PCIBus, TRUE, 0, (PVOID)0, (PVOID)0, (PVOID)0x0, 0, NULL } };
|
||||
|
||||
/* Global flag to tell whether or not the adapter's device queue should be initialized (first call only) */
|
||||
BOOLEAN AdaptersInitialized = FALSE;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
HalpInitDma (VOID)
|
||||
{
|
||||
ULONG Index;
|
||||
|
||||
KeInitializeDeviceQueue(&PciBusMasterAdapterObjects[0].DeviceQueue);
|
||||
KeInitializeSpinLock(&PciBusMasterAdapterObjects[0].SpinLock);
|
||||
PciBusMasterAdapterObjects[0].Inuse = FALSE;
|
||||
for (Index = 0; Index < 8; Index++)
|
||||
{
|
||||
KeInitializeDeviceQueue(&IsaSlaveAdapterObjects[Index].DeviceQueue);
|
||||
KeInitializeSpinLock(&IsaSlaveAdapterObjects[Index].SpinLock);
|
||||
IsaSlaveAdapterObjects[Index].Inuse = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
PVOID STDCALL
|
||||
HalAllocateCommonBuffer (PADAPTER_OBJECT AdapterObject,
|
||||
ULONG Length,
|
||||
|
@ -52,11 +69,15 @@ HalAllocateCommonBuffer (PADAPTER_OBJECT AdapterObject,
|
|||
* NULL on failure
|
||||
* NOTES:
|
||||
* CacheEnabled is ignored - it's all cache-disabled (like in NT)
|
||||
* UPDATE: It's not ignored now. If that's wrong just modify the
|
||||
* CacheEnabled comparsion below.
|
||||
*/
|
||||
{
|
||||
PHYSICAL_ADDRESS HighestAddress;
|
||||
PHYSICAL_ADDRESS LowestAddress, HighestAddress, BoundryAddressMultiple;
|
||||
PVOID BaseAddress;
|
||||
|
||||
LowestAddress.QuadPart = 0;
|
||||
BoundryAddressMultiple.QuadPart = 0;
|
||||
HighestAddress.u.HighPart = 0;
|
||||
if (AdapterObject->InterfaceType == Isa ||
|
||||
(AdapterObject->InterfaceType == MicroChannel && AdapterObject->Master == FALSE))
|
||||
|
@ -68,7 +89,13 @@ HalAllocateCommonBuffer (PADAPTER_OBJECT AdapterObject,
|
|||
HighestAddress.u.LowPart = 0xFFFFFFFF; /* 32Bit: 4GB address range */
|
||||
}
|
||||
|
||||
BaseAddress = MmAllocateContiguousMemory(Length, HighestAddress);
|
||||
BaseAddress = MmAllocateContiguousAlignedMemory(
|
||||
Length,
|
||||
LowestAddress,
|
||||
HighestAddress,
|
||||
BoundryAddressMultiple,
|
||||
CacheEnabled ? MmCached : MmNonCached,
|
||||
0x10000 );
|
||||
if (!BaseAddress)
|
||||
return 0;
|
||||
|
||||
|
@ -114,56 +141,80 @@ HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription,
|
|||
* RETURNS: The allocated adapter object on success
|
||||
* NULL on failure
|
||||
* TODO:
|
||||
* Figure out what to do with the commented-out cases
|
||||
* Honour all the fields in DeviceDescription structure.
|
||||
*/
|
||||
{
|
||||
/* TODO: find a better home for this */
|
||||
if(!AdaptersInitialized)
|
||||
{
|
||||
KeInitializeDeviceQueue(&PciBusMasterAdapterObjects[0].DeviceQueue);
|
||||
KeInitializeDeviceQueue(&IsaSlaveAdapterObjects[0].DeviceQueue);
|
||||
KeInitializeDeviceQueue(&IsaSlaveAdapterObjects[1].DeviceQueue);
|
||||
KeInitializeDeviceQueue(&IsaSlaveAdapterObjects[2].DeviceQueue);
|
||||
KeInitializeDeviceQueue(&IsaSlaveAdapterObjects[3].DeviceQueue);
|
||||
AdaptersInitialized = TRUE;
|
||||
}
|
||||
PADAPTER_OBJECT AdapterObject;
|
||||
|
||||
/* Validate parameters in device description, and return a pointer to
|
||||
the adapter object for the requested dma channel */
|
||||
if( DeviceDescription->Version != DEVICE_DESCRIPTION_VERSION )
|
||||
return NULL;
|
||||
|
||||
if (DeviceDescription->InterfaceType == PCIBus)
|
||||
switch (DeviceDescription->InterfaceType)
|
||||
{
|
||||
case PCIBus:
|
||||
if (DeviceDescription->Master == FALSE)
|
||||
return NULL;
|
||||
|
||||
return &PciBusMasterAdapterObjects[0];
|
||||
}
|
||||
|
||||
/*
|
||||
if( DeviceDescription->Master )
|
||||
case Isa:
|
||||
/* There are only 8 DMA channels on ISA. */
|
||||
if (DeviceDescription->DmaChannel >= 8)
|
||||
return NULL;
|
||||
if( DeviceDescription->ScatterGather )
|
||||
/* Channels 1-4 are for 8-bit transfers... */
|
||||
if (DeviceDescription->DmaWidth != Width8Bits &&
|
||||
DeviceDescription->DmaChannel < 4)
|
||||
return NULL;
|
||||
if( DeviceDescription->AutoInitialize )
|
||||
/* ...and the rest is for 16-bit transfers. */
|
||||
if (DeviceDescription->DmaWidth != Width16Bits &&
|
||||
DeviceDescription->DmaChannel >= 4)
|
||||
return NULL;
|
||||
if( DeviceDescription->Dma32BitAddresses )
|
||||
AdapterObject = &IsaSlaveAdapterObjects[DeviceDescription->DmaChannel];
|
||||
AdapterObject->Master = DeviceDescription->Master;
|
||||
AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
|
||||
AdapterObject->AutoInitialize = DeviceDescription->AutoInitialize;
|
||||
AdapterObject->DemandMode = DeviceDescription->DemandMode;
|
||||
AdapterObject->Buffer = 0;
|
||||
/* FIXME: Is this correct? */
|
||||
*NumberOfMapRegisters = 16;
|
||||
return AdapterObject;
|
||||
|
||||
default:
|
||||
/* Unsupported bus. */
|
||||
return NULL;
|
||||
if( DeviceDescription->InterfaceType != Isa )
|
||||
return NULL;
|
||||
*/
|
||||
/* if( DeviceDescription->DmaWidth != Width8Bits )
|
||||
return NULL;*/
|
||||
*NumberOfMapRegisters = 0x10;
|
||||
IsaSlaveAdapterObjects[DeviceDescription->DmaChannel].Buffer = 0;
|
||||
return &IsaSlaveAdapterObjects[DeviceDescription->DmaChannel];
|
||||
}
|
||||
}
|
||||
|
||||
ULONG STDCALL
|
||||
HalReadDmaCounter (PADAPTER_OBJECT AdapterObject)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
KIRQL OldIrql;
|
||||
ULONG Count;
|
||||
|
||||
if (AdapterObject && AdapterObject->InterfaceType == Isa && !AdapterObject->Master)
|
||||
{
|
||||
KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
|
||||
|
||||
/* Clear the flip/flop register */
|
||||
WRITE_PORT_UCHAR( AdapterObject->Channel < 4 ? (PVOID)0x0C : (PVOID)0xD8, 0 );
|
||||
/* Read the offset */
|
||||
Count = READ_PORT_UCHAR( AdapterObject->CountPort );
|
||||
Count |= READ_PORT_UCHAR( AdapterObject->CountPort ) << 8;
|
||||
|
||||
KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
|
||||
|
||||
/*
|
||||
* We must return twice the sound for channel >= 4 because it's the size
|
||||
* of words (16-bit) and not bytes.
|
||||
*/
|
||||
if (AdapterObject->Channel < 4)
|
||||
return Count;
|
||||
else
|
||||
return Count << 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: halinit.c,v 1.8 2004/05/15 22:45:51 hbirr Exp $
|
||||
/* $Id: halinit.c,v 1.9 2004/07/22 18:49:18 navaraf Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -63,6 +63,7 @@ HalInitSystem (ULONG BootPhase,
|
|||
else if (BootPhase == 1)
|
||||
{
|
||||
HalpInitBusHandlers();
|
||||
HalpInitDma();
|
||||
HalpCalibrateStallExecution();
|
||||
|
||||
/* Enumerate the devices on the motherboard */
|
||||
|
|
|
@ -19,6 +19,7 @@ BOOLEAN Hal_bios32_is_service_present(ULONG service);
|
|||
VOID FASTCALL HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock);
|
||||
VOID FASTCALL HalClearDisplay (UCHAR CharAttribute);
|
||||
|
||||
/* bus.c */
|
||||
VOID HalpInitBusHandlers (VOID);
|
||||
|
||||
/* irql.c */
|
||||
|
@ -33,6 +34,9 @@ VOID HalpInitPciBus (VOID);
|
|||
/* enum.c */
|
||||
VOID HalpStartEnumerator (VOID);
|
||||
|
||||
/* dma.c */
|
||||
VOID HalpInitDma (VOID);
|
||||
|
||||
/*
|
||||
* ADAPTER_OBJECT - Track a busmaster DMA adapter and its associated resources
|
||||
*
|
||||
|
@ -59,6 +63,15 @@ struct _ADAPTER_OBJECT {
|
|||
PWAIT_CONTEXT_BLOCK WaitContextBlock;
|
||||
KDEVICE_QUEUE DeviceQueue;
|
||||
BOOLEAN ScatterGather;
|
||||
|
||||
/*
|
||||
* 18/07/04: Added these members. It's propably not the exact place where
|
||||
* this should be stored, but I can't find better one. I haven't checked
|
||||
* how Windows handles this.
|
||||
* -- Filip Navara
|
||||
*/
|
||||
BOOLEAN DemandMode;
|
||||
BOOLEAN AutoInitialize;
|
||||
};
|
||||
|
||||
/* sysinfo.c */
|
||||
|
|
Loading…
Reference in a new issue