- 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:
Filip Navara 2004-07-22 18:49:18 +00:00
parent ec5f846d4c
commit 6e64d6266e
4 changed files with 183 additions and 79 deletions

View file

@ -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;
}
@ -304,14 +301,18 @@ IoMapTransfer (
* - If the controller supports scatter/gather, the copyover should not happen
*/
{
PHYSICAL_ADDRESS Address;
PHYSICAL_ADDRESS Address;
PVOID MaskReg, ClearReg, ModeReg;
UCHAR ModeMask, LengthShift;
KIRQL OldIrql;
#if defined(__GNUC__)
Address.QuadPart = 0ULL;
Address.QuadPart = 0ULL;
#else
Address.QuadPart = 0;
Address.QuadPart = 0;
#endif
/* Isa System (slave) DMA? */
/* Isa System (slave) DMA? */
if (AdapterObject && AdapterObject->InterfaceType == Isa && !AdapterObject->Master)
{
#if 0
@ -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
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));
if (!AdapterObject->AutoInitialize)
Address = MmGetPhysicalAddress( MapRegisterBase );
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.
@ -436,7 +475,7 @@ IoMapTransfer (
return MmGetPhysicalAddress(MapRegisterBase);
}
DPRINT1("IoMapTransfer: Unsupported operation\n");
KEBUGCHECK(0);
return Address;

View file

@ -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)
{
if (DeviceDescription->Master == FALSE)
return NULL;
case PCIBus:
if (DeviceDescription->Master == FALSE)
return NULL;
return &PciBusMasterAdapterObjects[0];
return &PciBusMasterAdapterObjects[0];
case Isa:
/* There are only 8 DMA channels on ISA. */
if (DeviceDescription->DmaChannel >= 8)
return NULL;
/* Channels 1-4 are for 8-bit transfers... */
if (DeviceDescription->DmaWidth != Width8Bits &&
DeviceDescription->DmaChannel < 4)
return NULL;
/* ...and the rest is for 16-bit transfers. */
if (DeviceDescription->DmaWidth != Width16Bits &&
DeviceDescription->DmaChannel >= 4)
return NULL;
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->Master )
return NULL;
if( DeviceDescription->ScatterGather )
return NULL;
if( DeviceDescription->AutoInitialize )
return NULL;
if( DeviceDescription->Dma32BitAddresses )
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 */

View file

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

View file

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