You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
261 lines
7.5 KiB
261 lines
7.5 KiB
/******************************Module*Header**********************************\
|
|
*
|
|
* ***************
|
|
* * SAMPLE CODE *
|
|
* ***************
|
|
*
|
|
* Module Name: mini.c
|
|
*
|
|
* Content:
|
|
*
|
|
* Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
|
|
* Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
|
|
\*****************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// AllocateDMABuffer
|
|
//
|
|
// Allocate physical continous memory for DMA operation. This function returns
|
|
// a pointer to a previously allocated DMA buffer if there is still an unfreed
|
|
// allocation left. That way the reallocation of continous memory can be
|
|
// avoided when a new ppdev is created on lets say a mode switch, since
|
|
// allocation of continous memory cannot be guaranteed. The memory is only
|
|
// physically freed after all allocations have called a FreeDMABuffer.
|
|
//
|
|
// Calls to AllocateDMABuffer and FreeDMABuffer should be paired, otherwise
|
|
// the usage count logic in the miniport driver gets confused!
|
|
//
|
|
// The VideoPort currently restricts the size of a DMA buffer to 256kb.
|
|
//
|
|
// hDriver-------videoport driver handle
|
|
// plSize--------pointer to LONG size of requested DMA buffer. Returns size
|
|
// of allocated DMA buffer
|
|
// (return value can be smaller than requested size)
|
|
// ppVirtAddr----returns virtual address of requested DMA buffer.
|
|
// pPhysAddr-----returns physical address of DMA buffer as seen from graphics
|
|
// device.
|
|
//
|
|
// return TRUE, allocation successful
|
|
// FALSE, allocation failed
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
AllocateDMABuffer( HANDLE hDriver,
|
|
PLONG plSize,
|
|
PULONG *ppVirtAddr,
|
|
LARGE_INTEGER *pPhysAddr)
|
|
{
|
|
|
|
LINE_DMA_BUFFER ldb;
|
|
ldb.size = *plSize;
|
|
ldb.virtAddr = 0;
|
|
|
|
ldb.cacheEnabled = TRUE;
|
|
|
|
*ppVirtAddr=0;
|
|
pPhysAddr->HighPart=
|
|
pPhysAddr->LowPart=0;
|
|
|
|
ULONG ulLength = sizeof(LINE_DMA_BUFFER);
|
|
|
|
if (EngDeviceIoControl( hDriver,
|
|
IOCTL_VIDEO_QUERY_LINE_DMA_BUFFER,
|
|
(PVOID)&ldb,
|
|
ulLength,
|
|
(PVOID)&ldb,
|
|
ulLength,
|
|
&ulLength))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
*ppVirtAddr=(PULONG)ldb.virtAddr;
|
|
|
|
if (ldb.virtAddr!=NULL)
|
|
{
|
|
*pPhysAddr=ldb.physAddr;
|
|
*plSize=ldb.size;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// FreeDMABuffer
|
|
//
|
|
// free continous buffer previously allocated by AllocateDMABuffer.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
FreeDMABuffer( HANDLE hDriver,
|
|
PVOID pVirtAddr)
|
|
{
|
|
LINE_DMA_BUFFER ldb;
|
|
ldb.size = 0;
|
|
ldb.virtAddr = pVirtAddr;
|
|
|
|
ULONG ulLength = sizeof(LINE_DMA_BUFFER);
|
|
|
|
if (EngDeviceIoControl( hDriver,
|
|
IOCTL_VIDEO_QUERY_LINE_DMA_BUFFER,
|
|
(PVOID)&ldb,
|
|
ulLength,
|
|
NULL,
|
|
0,
|
|
&ulLength))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// AllocateEmulatedDMABuffer
|
|
//
|
|
// Allocate memory for emulated DMA operation.
|
|
//
|
|
// hDriver-------videoport driver handle
|
|
// ulSize--------ULONG size of requested DMA buffer
|
|
// ulTag---------ULONG tag to mark allocation
|
|
//
|
|
// return NULL, allocation failed
|
|
// otherwise, virtual address of emulated DMA buffer
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
PULONG
|
|
AllocateEmulatedDMABuffer(
|
|
HANDLE hDriver,
|
|
ULONG ulSize,
|
|
ULONG ulTag
|
|
)
|
|
{
|
|
EMULATED_DMA_BUFFER edb;
|
|
|
|
edb.virtAddr = NULL;
|
|
edb.size = ulSize;
|
|
edb.tag = ulTag;
|
|
|
|
ULONG ulLength = sizeof(edb);
|
|
|
|
if (EngDeviceIoControl( hDriver,
|
|
IOCTL_VIDEO_QUERY_EMULATED_DMA_BUFFER,
|
|
(PVOID)&edb,
|
|
ulLength,
|
|
(PVOID)&edb,
|
|
ulLength,
|
|
&ulLength))
|
|
{
|
|
return (NULL);
|
|
}
|
|
|
|
return (PULONG)(edb.virtAddr);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// FreeEmulatedDMABuffer
|
|
//
|
|
// free buffer previously allocated by AllocateEmulatedDMABuffer.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
FreeEmulatedDMABuffer(
|
|
HANDLE hDriver,
|
|
PVOID pVirtAddr
|
|
)
|
|
{
|
|
EMULATED_DMA_BUFFER edb;
|
|
|
|
edb.virtAddr = pVirtAddr;
|
|
|
|
ULONG ulLength = sizeof(edb);
|
|
|
|
if (EngDeviceIoControl( hDriver,
|
|
IOCTL_VIDEO_QUERY_EMULATED_DMA_BUFFER,
|
|
(PVOID)&edb,
|
|
ulLength,
|
|
NULL,
|
|
0,
|
|
&ulLength))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// StallExecution
|
|
//
|
|
// calls VideoPortStallExecution in the miniport for defined delay when
|
|
// polling Permedia registers. VideoPortStallexecution does not yield
|
|
// to another process and should only be used in rare cases.
|
|
//
|
|
// hDriver--------handle to videoport
|
|
// ulMicroSeconds-number of microseconds to stall CPU execution
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
StallExecution( HANDLE hDriver, ULONG ulMicroSeconds)
|
|
{
|
|
ULONG Length = 0;
|
|
EngDeviceIoControl(hDriver,
|
|
IOCTL_VIDEO_STALL_EXECUTION,
|
|
&ulMicroSeconds,
|
|
sizeof(ULONG),
|
|
NULL,
|
|
0,
|
|
&Length);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// GetPInterlockedExchange
|
|
//
|
|
// We need to call the same InterlockedExchange function from the display
|
|
// driver and the miniport to make sure they work properly. The miniport
|
|
// will give us a pointer to the function which we will call directly...
|
|
// On Alpha and Risc machines, InterlockedExchange compiles as inline and
|
|
// we don't need to call in the kernel.
|
|
//
|
|
// note: the InterlockedExchange function exported from ntoskrnl has calling
|
|
// convention __fastcall.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#if defined(_X86_)
|
|
PVOID
|
|
GetPInterlockedExchange( HANDLE hDriver)
|
|
{
|
|
ULONG Length = 0;
|
|
PVOID pWorkPtr=NULL;
|
|
|
|
if (EngDeviceIoControl( hDriver,
|
|
IOCTL_VIDEO_QUERY_INTERLOCKEDEXCHANGE,
|
|
NULL,
|
|
0,
|
|
&pWorkPtr,
|
|
sizeof(pWorkPtr),
|
|
&Length))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return pWorkPtr;
|
|
}
|
|
#endif
|