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