enum PVRSRV_ERROR PVRSRVAllocDeviceMemKM(void *hDevCookie, struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDevMemHeap, u32 ui32Flags, u32 ui32Size, u32 ui32Alignment, struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo) { struct PVRSRV_KERNEL_MEM_INFO *psMemInfo; enum PVRSRV_ERROR eError; struct BM_HEAP *psBMHeap; void *hDevMemContext; if (!hDevMemHeap || (ui32Size == 0)) return PVRSRV_ERROR_INVALID_PARAMS; eError = AllocDeviceMem(hDevCookie, hDevMemHeap, ui32Flags, ui32Size, ui32Alignment, &psMemInfo); if (eError != PVRSRV_OK) return eError; if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ) { psMemInfo->psKernelSyncInfo = NULL; } else { psBMHeap = (struct BM_HEAP *)hDevMemHeap; hDevMemContext = (void *) psBMHeap->pBMContext; eError = PVRSRVAllocSyncInfoKM(hDevCookie, hDevMemContext, &psMemInfo->psKernelSyncInfo); if (eError != PVRSRV_OK) goto free_mainalloc; } *ppsMemInfo = psMemInfo; if (ui32Flags & PVRSRV_MEM_NO_RESMAN) { psMemInfo->sMemBlk.hResItem = NULL; } else { psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_ALLOCATION, psMemInfo, 0, FreeDeviceMemCallBack); if (psMemInfo->sMemBlk.hResItem == NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto free_mainalloc; } } psMemInfo->ui32RefCount++; return PVRSRV_OK; free_mainalloc: FreeDeviceMem(psMemInfo); return eError; }
static inline enum PVRSRV_ERROR alloc_or_reuse_syncinfo(void *dev_cookie, void *mem_context_handle, struct PVRSRV_KERNEL_SYNC_INFO **syncinfo, struct IMG_SYS_PHYADDR *phys_addr) { enum PVRSRV_ERROR error; struct PVRSRV_DEVICE_NODE *dev; dev = (struct PVRSRV_DEVICE_NODE *) dev_cookie; *syncinfo = (struct PVRSRV_KERNEL_SYNC_INFO *) HASH_Retrieve(dev->sync_table, phys_addr->uiAddr); if (!*syncinfo) { /* Dont' have one so create one */ error = PVRSRVAllocSyncInfoKM(dev_cookie, mem_context_handle, syncinfo); if (error != PVRSRV_OK) return error; /* Setup our extra data */ (*syncinfo)->phys_addr.uiAddr = phys_addr->uiAddr; (*syncinfo)->dev_cookie = dev_cookie; (*syncinfo)->refcount = 1; if (!HASH_Insert(dev->sync_table, phys_addr->uiAddr, (u32) *syncinfo)) { PVR_DPF(PVR_DBG_ERROR, "alloc_or_reuse_syncinfo: " "Failed to add syncobject to hash table"); return PVRSRV_ERROR_GENERIC; } } else get_syncinfo(*syncinfo); return PVRSRV_OK; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie, PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevMemContext, IMG_SIZE_T ui32ByteSize, IMG_SIZE_T ui32PageOffset, IMG_BOOL bPhysContig, IMG_SYS_PHYADDR *psExtSysPAddr, IMG_VOID *pvLinAddr, IMG_UINT32 ui32Flags, PVRSRV_KERNEL_MEM_INFO **ppsMemInfo) { PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL; DEVICE_MEMORY_INFO *psDevMemoryInfo; IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE(); IMG_HANDLE hDevMemHeap = IMG_NULL; PVRSRV_DEVICE_NODE* psDeviceNode; BM_HANDLE hBuffer; PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; BM_HEAP *psBMHeap; PVRSRV_ERROR eError; IMG_VOID *pvPageAlignedCPUVAddr; IMG_SYS_PHYADDR *psIntSysPAddr = IMG_NULL; IMG_HANDLE hOSWrapMem = IMG_NULL; DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; IMG_UINT32 i; IMG_SIZE_T ui32PageCount = 0; psDeviceNode = (PVRSRV_DEVICE_NODE*)hDevCookie; PVR_ASSERT(psDeviceNode != IMG_NULL); if (psDeviceNode == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: invalid parameter")); return PVRSRV_ERROR_INVALID_PARAMS; } if(pvLinAddr) { ui32PageOffset = (IMG_UINTPTR_T)pvLinAddr & (ui32HostPageSize - 1); ui32PageCount = HOST_PAGEALIGN(ui32ByteSize + ui32PageOffset) / ui32HostPageSize; pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvLinAddr - ui32PageOffset); if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageCount * sizeof(IMG_SYS_PHYADDR), (IMG_VOID **)&psIntSysPAddr, IMG_NULL, "Array of Page Addresses") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block")); return PVRSRV_ERROR_OUT_OF_MEMORY; } eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr, ui32PageCount * ui32HostPageSize, psIntSysPAddr, &hOSWrapMem); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExitPhase1; } psExtSysPAddr = psIntSysPAddr; bPhysContig = IMG_FALSE; } else { } psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo; psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap; for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++) { if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32MappingHeapID) { if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT) { hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]); } else { hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap; } break; } } if(hDevMemHeap == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: unable to find mapping heap")); eError = PVRSRV_ERROR_UNABLE_TO_FIND_MAPPING_HEAP; goto ErrorExitPhase2; } if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), (IMG_VOID **)&psMemInfo, IMG_NULL, "Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExitPhase2; } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemInfo->ui32Flags = ui32Flags; psMemBlock = &(psMemInfo->sMemBlk); bBMError = BM_Wrap(hDevMemHeap, ui32ByteSize, ui32PageOffset, bPhysContig, psExtSysPAddr, IMG_NULL, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: BM_Wrap Failed")); eError = PVRSRV_ERROR_BAD_MAPPING; goto ErrorExitPhase3; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hOSWrapMem = hOSWrapMem; psMemBlock->psIntSysPAddr = psIntSysPAddr; psMemBlock->hBuffer = (IMG_HANDLE)hBuffer; psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer); psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = ui32ByteSize; psMemInfo->pvSysBackupBuffer = IMG_NULL; psBMHeap = (BM_HEAP*)hDevMemHeap; hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext; eError = PVRSRVAllocSyncInfoKM(hDevCookie, hDevMemContext, &psMemInfo->psKernelSyncInfo); if(eError != PVRSRV_OK) { goto ErrorExitPhase4; } psMemInfo->psKernelSyncInfo->ui32RefCount++; psMemInfo->ui32RefCount++; psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED; psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_WRAP, psMemInfo, 0, &UnwrapExtMemoryCallBack); *ppsMemInfo = psMemInfo; return PVRSRV_OK; ErrorExitPhase4: if(psMemInfo) { FreeDeviceMem(psMemInfo); psMemInfo = IMG_NULL; } ErrorExitPhase3: if(psMemInfo) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); } ErrorExitPhase2: if(psIntSysPAddr) { OSReleasePhysPageAddr(hOSWrapMem); } ErrorExitPhase1: if(psIntSysPAddr) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL); } return eError; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie, PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevMemHeap, IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_SIZE_T ui32Alignment, PVRSRV_KERNEL_MEM_INFO **ppsMemInfo) { PVRSRV_KERNEL_MEM_INFO *psMemInfo; PVRSRV_ERROR eError; BM_HEAP *psBMHeap; IMG_HANDLE hDevMemContext; if (!hDevMemHeap || (ui32Size == 0)) { return PVRSRV_ERROR_INVALID_PARAMS; } if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) { if (((ui32Size % HOST_PAGESIZE()) != 0) || ((ui32Alignment % HOST_PAGESIZE()) != 0)) { return PVRSRV_ERROR_INVALID_PARAMS; } } eError = AllocDeviceMem(hDevCookie, hDevMemHeap, ui32Flags, ui32Size, ui32Alignment, &psMemInfo); if (eError != PVRSRV_OK) { return eError; } #if defined(PVRSRV_RESOURCE_PROFILING) psBMHeap = (BM_HEAP*)hDevMemHeap; if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB) psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie, psMemInfo->ui32AllocSize, IMG_TRUE); #endif if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ) { psMemInfo->psKernelSyncInfo = IMG_NULL; } else { psBMHeap = (BM_HEAP*)hDevMemHeap; hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext; eError = PVRSRVAllocSyncInfoKM(hDevCookie, hDevMemContext, &psMemInfo->psKernelSyncInfo); if(eError != PVRSRV_OK) { goto free_mainalloc; } psMemInfo->psKernelSyncInfo->ui32RefCount++; #if defined(PVRSRV_RESOURCE_PROFILING) if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB) psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie, psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize, IMG_TRUE); #endif } *ppsMemInfo = psMemInfo; if (ui32Flags & PVRSRV_MEM_NO_RESMAN) { psMemInfo->sMemBlk.hResItem = IMG_NULL; } else { psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_ALLOCATION, psMemInfo, 0, &FreeDeviceMemCallBack); if (psMemInfo->sMemBlk.hResItem == IMG_NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto free_mainalloc; } } psMemInfo->ui32RefCount++; psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE; return (PVRSRV_OK); free_mainalloc: #if defined(PVRSRV_RESOURCE_PROFILING) if (psBMHeap->pBMContext->psDeviceNode->pfnResProfCB) psBMHeap->pBMContext->psDeviceNode->pfnResProfCB(hDevCookie, psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize, IMG_FALSE); #endif FreeDeviceMem(psMemInfo); return eError; }
enum PVRSRV_ERROR PVRSRVCreateDCSwapChainKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDeviceKM, u32 ui32Flags, struct DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib, struct DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib, u32 ui32BufferCount, u32 ui32OEMFlags, void **phSwapChain, u32 *pui32SwapChainID) { struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo; struct PVRSRV_DC_SWAPCHAIN *psSwapChain = NULL; struct PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS]; struct PVRSRV_QUEUE_INFO *psQueue = NULL; enum PVRSRV_ERROR eError; u32 i; if (!hDeviceKM || !psDstSurfAttrib || !psSrcSurfAttrib || !phSwapChain || !pui32SwapChainID) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: Invalid parameters"); return PVRSRV_ERROR_INVALID_PARAMS; } if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: Too many buffers"); return PVRSRV_ERROR_TOOMANYBUFFERS; } if (ui32BufferCount < 2) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: Too few buffers"); return PVRSRV_ERROR_TOO_FEW_BUFFERS; } psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_DC_SWAPCHAIN), (void **) &psSwapChain, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc"); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExit; } OSMemSet(psSwapChain, 0, sizeof(struct PVRSRV_DC_SWAPCHAIN)); eError = PVRSRVCreateCommandQueueKM(1024, &psQueue); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue"); goto ErrorExit; } psSwapChain->psQueue = psQueue; for (i = 0; i < ui32BufferCount; i++) { eError = PVRSRVAllocSyncInfoKM(NULL, psDCInfo->hDevMemContext, &psSwapChain->asBuffer[i]. sDeviceClassBuffer. psKernelSyncInfo); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: " "Failed to alloc syninfo for psSwapChain"); goto ErrorExit; } psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr; psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext; psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice; psSwapChain->asBuffer[i].psDCInfo = psDCInfo; psSwapChain->asBuffer[i].psSwapChain = psSwapChain; apsSyncData[i] = (struct PVRSRV_SYNC_DATA *)psSwapChain->asBuffer[i]. sDeviceClassBuffer.psKernelSyncInfo-> psSyncDataMemInfoKM->pvLinAddrKM; } psSwapChain->ui32BufferCount = ui32BufferCount; psSwapChain->psDCInfo = psDCInfo; eError = psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice, ui32Flags, psDstSurfAttrib, psSrcSurfAttrib, ui32BufferCount, apsSyncData, ui32OEMFlags, &psSwapChain->hExtSwapChain, pui32SwapChainID); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: " "Failed to create 3rd party SwapChain"); goto ErrorExit; } *phSwapChain = (void *) psSwapChain; psSwapChain->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN, psSwapChain, 0, DestroyDCSwapChainCallBack); return eError; ErrorExit: for (i = 0; i < ui32BufferCount; i++) { if (psSwapChain->asBuffer[i].sDeviceClassBuffer. psKernelSyncInfo) { PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i]. sDeviceClassBuffer. psKernelSyncInfo); } } if (psQueue) PVRSRVDestroyCommandQueueKM(psQueue); if (psSwapChain) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_DC_SWAPCHAIN), psSwapChain, NULL); } return eError; }
enum PVRSRV_ERROR PVRSRVOpenDCDeviceKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, u32 ui32DeviceID, void *hDevCookie, void **phDeviceKM) { struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo; struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; struct PVRSRV_DEVICE_NODE *psDeviceNode; struct SYS_DATA *psSysData; if (!phDeviceKM || !hDevCookie) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: Invalid params"); return PVRSRV_ERROR_GENERIC; } if (SysAcquireData(&psSysData) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: Failed to get SysData"); return PVRSRV_ERROR_GENERIC; } psDeviceNode = psSysData->psDeviceNodeList; while (psDeviceNode) { if ((psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY) && (psDeviceNode->sDevId.ui32DeviceIndex == ui32DeviceID)) { psDCInfo = (struct PVRSRV_DISPLAYCLASS_INFO *) psDeviceNode->pvDevice; goto FoundDevice; } psDeviceNode = psDeviceNode->psNext; } PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID); return PVRSRV_ERROR_GENERIC; FoundDevice: if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psDCPerContextInfo), (void **)&psDCPerContextInfo, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: " "Failed psDCPerContextInfo alloc"); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo)); if (psDCInfo->ui32RefCount++ == 0) { enum PVRSRV_ERROR eError; struct PVRSRV_DC_SRV2DISP_KMJTABLE *jtbl; psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie; jtbl = psDCInfo->psFuncTable; if (!try_module_get(jtbl->owner)) { PVR_DPF(PVR_DBG_ERROR, "%s: can't get DC module"); return PVRSRV_ERROR_INVALID_DEVICE; } psDCInfo->hDevMemContext = (void *) psDeviceNode->sDevMemoryInfo.pBMKernelContext; eError = PVRSRVAllocSyncInfoKM(NULL, (void *)psDeviceNode-> sDevMemoryInfo.pBMKernelContext, &psDCInfo->sSystemBuffer. sDeviceClassBuffer. psKernelSyncInfo); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: Failed sync info alloc"); psDCInfo->ui32RefCount--; module_put(jtbl->owner); return eError; } eError = jtbl->pfnOpenDCDevice(ui32DeviceID, &psDCInfo->hExtDevice, (struct PVRSRV_SYNC_DATA *)psDCInfo->sSystemBuffer. sDeviceClassBuffer.psKernelSyncInfo-> psSyncDataMemInfoKM->pvLinAddrKM); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: " "Failed to open external DC device"); psDCInfo->ui32RefCount--; module_put(jtbl->owner); PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer. sDeviceClassBuffer.psKernelSyncInfo); return eError; } } psDCPerContextInfo->psDCInfo = psDCInfo; psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DISPLAYCLASS_DEVICE, psDCPerContextInfo, 0, CloseDCDeviceCallBack); *phDeviceKM = (void *) psDCPerContextInfo; return PVRSRV_OK; }
enum PVRSRV_ERROR PVRSRVOpenBCDeviceKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, u32 ui32DeviceID, void *hDevCookie, void **phDeviceKM) { struct PVRSRV_BUFFERCLASS_INFO *psBCInfo; struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; struct PVRSRV_DEVICE_NODE *psDeviceNode; struct SYS_DATA *psSysData; u32 i; enum PVRSRV_ERROR eError; if (!phDeviceKM || !hDevCookie) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: Invalid params"); return PVRSRV_ERROR_GENERIC; } if (SysAcquireData(&psSysData) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: Failed to get SysData"); return PVRSRV_ERROR_GENERIC; } psDeviceNode = psSysData->psDeviceNodeList; while (psDeviceNode) { if ((psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_BUFFER) && (psDeviceNode->sDevId.ui32DeviceIndex == ui32DeviceID)) { psBCInfo = (struct PVRSRV_BUFFERCLASS_INFO *) psDeviceNode->pvDevice; goto FoundDevice; } psDeviceNode = psDeviceNode->psNext; } PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID); return PVRSRV_ERROR_GENERIC; FoundDevice: if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psBCPerContextInfo), (void **)&psBCPerContextInfo, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: " "Failed psBCPerContextInfo alloc"); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo)); if (psBCInfo->ui32RefCount++ == 0) { struct BUFFER_INFO sBufferInfo; psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie; psBCInfo->hDevMemContext = (void *) psDeviceNode->sDevMemoryInfo.pBMKernelContext; eError = psBCInfo->psFuncTable->pfnOpenBCDevice(&psBCInfo-> hExtDevice); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: " "Failed to open external BC device"); return eError; } eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM : Failed to get BC Info"); return eError; } psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount; eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount, (void **) &psBCInfo->psBuffer, NULL); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: " "Failed to allocate BC buffers"); return eError; } OSMemSet(psBCInfo->psBuffer, 0, sizeof(struct PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount); for (i = 0; i < psBCInfo->ui32BufferCount; i++) { eError = PVRSRVAllocSyncInfoKM(NULL, psBCInfo->hDevMemContext, &psBCInfo->psBuffer[i].sDeviceClassBuffer. psKernelSyncInfo); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: " "Failed sync info alloc"); goto ErrorExit; } eError = psBCInfo->psFuncTable->pfnGetBCBuffer( psBCInfo->hExtDevice, i, psBCInfo->psBuffer[i].sDeviceClassBuffer. psKernelSyncInfo-> psSyncData, &psBCInfo->psBuffer[i].sDeviceClassBuffer. hExtBuffer); if (eError != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: " "Failed to get BC buffers"); goto ErrorExit; } psBCInfo->psBuffer[i].sDeviceClassBuffer. pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr; psBCInfo->psBuffer[i].sDeviceClassBuffer. hDevMemContext = psBCInfo->hDevMemContext; psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice; } } psBCPerContextInfo->psBCInfo = psBCInfo; psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_BUFFERCLASS_DEVICE, psBCPerContextInfo, 0, CloseBCDeviceCallBack); *phDeviceKM = (void *)psBCPerContextInfo; return PVRSRV_OK; ErrorExit: for (i = 0; i < psBCInfo->ui32BufferCount; i++) { if (psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i]. sDeviceClassBuffer. psKernelSyncInfo); } } if (psBCInfo->psBuffer) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_BC_BUFFER), psBCInfo->psBuffer, NULL); } return eError; }
IMG_EXPORT PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_UINT32 ui32DeviceID, IMG_HANDLE hDevCookie, IMG_HANDLE *phDeviceKM) { PVRSRV_DISPLAYCLASS_INFO *psDCInfo; PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; PVRSRV_DEVICE_NODE *psDeviceNode; SYS_DATA *psSysData; PVRSRV_ERROR eError; if(!phDeviceKM || !hDevCookie) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params")); return PVRSRV_ERROR_GENERIC; } SysAcquireData(&psSysData); psDeviceNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, MatchDeviceKM_AnyVaCb, ui32DeviceID, IMG_FALSE, PVRSRV_DEVICE_CLASS_DISPLAY); if (!psDeviceNode) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID)); return PVRSRV_ERROR_GENERIC; } psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psDCPerContextInfo), (IMG_VOID **)&psDCPerContextInfo, IMG_NULL, "Display Class per Context Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo)); if(psDCInfo->ui32RefCount++ == 0) { psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie; psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext; eError = PVRSRVAllocSyncInfoKM(IMG_NULL, (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext, &psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc")); psDCInfo->ui32RefCount--; return eError; } eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID, &psDCInfo->hExtDevice, (PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device")); psDCInfo->ui32RefCount--; PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); return eError; } } psDCPerContextInfo->psDCInfo = psDCInfo; psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DISPLAYCLASS_DEVICE, psDCPerContextInfo, 0, CloseDCDeviceCallBack); *phDeviceKM = (IMG_HANDLE)psDCPerContextInfo; return PVRSRV_OK; }
IMG_EXPORT PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_UINT32 ui32DeviceID, IMG_HANDLE hDevCookie, IMG_HANDLE *phDeviceKM) { PVRSRV_BUFFERCLASS_INFO *psBCInfo; PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; PVRSRV_DEVICE_NODE *psDeviceNode; SYS_DATA *psSysData; IMG_UINT32 i; PVRSRV_ERROR eError; if(!phDeviceKM || !hDevCookie) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params")); return PVRSRV_ERROR_GENERIC; } SysAcquireData(&psSysData); psDeviceNode = (PVRSRV_DEVICE_NODE*) List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, MatchDeviceKM_AnyVaCb, ui32DeviceID, IMG_FALSE, PVRSRV_DEVICE_CLASS_BUFFER); if (!psDeviceNode) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID)); return PVRSRV_ERROR_GENERIC; } psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psBCPerContextInfo), (IMG_VOID **)&psBCPerContextInfo, IMG_NULL, "Buffer Class per Context Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo)); if(psBCInfo->ui32RefCount++ == 0) { BUFFER_INFO sBufferInfo; psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie; psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext; eError = psBCInfo->psFuncTable->pfnOpenBCDevice(&psBCInfo->hExtDevice); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device")); return eError; } eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info")); return eError; } psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount; eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount, (IMG_VOID **)&psBCInfo->psBuffer, IMG_NULL, "Array of Buffer Class Buffer"); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers")); return eError; } OSMemSet (psBCInfo->psBuffer, 0, sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount); for(i=0; i<psBCInfo->ui32BufferCount; i++) { eError = PVRSRVAllocSyncInfoKM(IMG_NULL, psBCInfo->hDevMemContext, &psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc")); goto ErrorExit; } eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice, i, psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData, &psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers")); goto ErrorExit; } psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr; psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext; psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice; } } psBCPerContextInfo->psBCInfo = psBCInfo; psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_BUFFERCLASS_DEVICE, psBCPerContextInfo, 0, CloseBCDeviceCallBack); *phDeviceKM = (IMG_HANDLE)psBCPerContextInfo; return PVRSRV_OK; ErrorExit: for(i=0; i<psBCInfo->ui32BufferCount; i++) { if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) { PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); } } if(psBCInfo->psBuffer) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL); psBCInfo->psBuffer = IMG_NULL; } return eError; }