PVRSRV_ERROR OSConnectionPrivateDataInit(IMG_HANDLE *phOsPrivateData, IMG_PVOID pvOSData) { ENV_CONNECTION_DATA *psEnvConnection; #if defined(SUPPORT_ION) ENV_ION_CONNECTION_DATA *psIonConnection; #endif *phOsPrivateData = OSAllocMem(sizeof(ENV_CONNECTION_DATA)); if (*phOsPrivateData == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed", __FUNCTION__)); return PVRSRV_ERROR_OUT_OF_MEMORY; } psEnvConnection = (ENV_CONNECTION_DATA *)*phOsPrivateData; OSMemSet(psEnvConnection, 0, sizeof(*psEnvConnection)); /* Save the pointer to our struct file */ psEnvConnection->psFile = pvOSData; #if defined(SUPPORT_ION) psIonConnection = (ENV_ION_CONNECTION_DATA *)OSAllocMem(sizeof(ENV_ION_CONNECTION_DATA)); if (psIonConnection == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed", __FUNCTION__)); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psIonConnection, 0, sizeof(*psIonConnection)); psEnvConnection->psIonData = psIonConnection; /* We can have more then one connection per process so we need more then the PID to have a unique name */ psEnvConnection->psIonData->psIonDev = IonDevAcquire(); OSSNPrintf(psEnvConnection->psIonData->azIonClientName, ION_CLIENT_NAME_SIZE, "pvr_ion_client-%p-%d", *phOsPrivateData, OSGetCurrentProcessIDKM()); psEnvConnection->psIonData->psIonClient = ion_client_create(psEnvConnection->psIonData->psIonDev, psEnvConnection->psIonData->azIonClientName); if (IS_ERR_OR_NULL(psEnvConnection->psIonData->psIonClient)) { PVR_DPF((PVR_DBG_ERROR, "OSConnectionPrivateDataInit: Couldn't create " "ion client for per connection data")); return PVRSRV_ERROR_OUT_OF_MEMORY; } psEnvConnection->psIonData->ui32IonClientRefCount = 1; #endif /* SUPPORT_ION */ return PVRSRV_OK; }
PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig) { PLAT_DATA *psPlatData; PVRSRV_ERROR eError; psPlatData = OSAllocMem(sizeof(PLAT_DATA)); OSMemSet(psPlatData, 0, sizeof(PLAT_DATA)); /* Query the Emu for reg and IRQ information */ eError = PCIInitDev(psPlatData); if (eError != PVRSRV_OK) { goto e0; } /* Save data for this device */ sSysConfig.pasDevices[0].hSysData = (IMG_HANDLE) psPlatData; #if defined (LMA) /* Save private data for the physical memory heaps */ gsPhysHeapConfig[0].hPrivData = (IMG_HANDLE) psPlatData; gsPhysHeapConfig[1].hPrivData = (IMG_HANDLE) psPlatData; #endif *ppsSysConfig = &sSysConfig; /* Ion is only supported on UMA builds */ #if (defined(SUPPORT_ION) && (!defined(LMA))) IonInit(NULL); #endif gpsPlatData = psPlatData; return PVRSRV_OK; e0: return eError; }
PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line) { OSMEM_DEBUG_INFO *psInfo; OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line); OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER); psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS); psInfo->uSize = 0; psInfo->uSizeParityCheck = 0; psInfo->eValid = isFree; psInfo->uLineNo = ui32Line; debug_strcpy(psInfo->sFileName, pszFilename); return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line); }
PVRSRV_ERROR OSFreeMem_Debug_Wrapper(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line) { OSMEM_DEBUG_INFO *psInfo; /*check dbginfo (arg pointing to user memory)*/ OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line); /*mark memory as freed*/ OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER); /*point to the starting address of the total allocated memory*/ psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINTPTR_T) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS); /*update dbg info struct*/ psInfo->uSize = 0; psInfo->uSizeParityCheck = 0; psInfo->eValid = isFree; psInfo->uLineNo = ui32Line; debug_strcpy(psInfo->sFileName, pszFilename); return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, psInfo, hBlockAlloc, pszFilename, ui32Line); }
static BT * _BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize) { BT *pBT; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), (IMG_VOID **)&pBT, IMG_NULL, "Boundary Tag") != PVRSRV_OK) { return IMG_NULL; } OSMemSet(pBT, 0, sizeof(BT)); #if defined(VALIDATE_ARENA_TEST) pBT->ui32BoundaryTagID = ++ui32BoundaryTagID; #endif pBT->type = btt_free; pBT->base = base; pBT->uSize = uSize; return pBT; }
static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData) { #if defined(NO_HARDWARE) PVRSRV_ERROR eError; IMG_CPU_PHYADDR sCpuPAddr; #endif PVR_UNREFERENCED_PARAMETER(psSysData); gsSGXDeviceMap.ui32Flags = 0x0; #if defined(NO_HARDWARE) eError = OSBaseAllocContigMemory(SYS_OMAP3430_SGX_REGS_SIZE, &gsSGXRegsCPUVAddr, &sCpuPAddr); if(eError != PVRSRV_OK) { return eError; } gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr; gsSGXDeviceMap.sRegsSysPBase = SysCpuPAddrToSysPAddr(gsSGXDeviceMap.sRegsCpuPBase); gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE; #if defined(__linux__) gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr; #else gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL; #endif OSMemSet(gsSGXRegsCPUVAddr, 0, SYS_OMAP3430_SGX_REGS_SIZE); gsSGXDeviceMap.ui32IRQ = 0; #else gsSGXDeviceMap.sRegsSysPBase.uiAddr = SYS_OMAP3430_SGX_REGS_SYS_PHYS_BASE; gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase); gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE; gsSGXDeviceMap.ui32IRQ = SYS_OMAP3430_SGX_IRQ; #endif #if defined(PDUMP) { static IMG_CHAR pszPDumpDevName[] = "SGXMEM"; gsSGXDeviceMap.pszPDumpDevName = pszPDumpDevName; } #endif return PVRSRV_OK; }
PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData) { PVRSRV_ERROR eError; IMG_HANDLE hBlockAlloc; PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc; eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_ENV_PER_PROCESS_DATA), phOsPrivateData, &hBlockAlloc, "Environment per Process Data"); if (eError != PVRSRV_OK) { *phOsPrivateData = IMG_NULL; PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError)); return eError; } psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData; OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc)); psEnvPerProc->hBlockAlloc = hBlockAlloc; LinuxMMapPerProcessConnect(psEnvPerProc); return PVRSRV_OK; }
/*! ****************************************************************************** @Function PVRSRVTimeTraceBufferCreate @Description Create a trace buffer. Note: We assume that this will only be called once per process. @Input ui32PID : PID of the process that is creating the buffer @Return none ******************************************************************************/ PVRSRV_ERROR PVRSRVTimeTraceBufferCreate(IMG_UINT32 ui32PID) { sTimeTraceBuffer *psBuffer; PVRSRV_ERROR eError = PVRSRV_OK; eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT, sizeof(sTimeTraceBuffer) + TIME_TRACE_BUFFER_SIZE, (IMG_VOID **)&psBuffer, IMG_NULL, "Time Trace Buffer"); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferCreate: Error allocating trace buffer")); return eError; } OSMemSet(psBuffer, 0, TIME_TRACE_BUFFER_SIZE); if (!HASH_Insert(g_psBufferTable, (IMG_UINTPTR_T) ui32PID, (IMG_UINTPTR_T) psBuffer)) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(sTimeTraceBuffer) + TIME_TRACE_BUFFER_SIZE, psBuffer, NULL); PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferCreate: Error adding trace buffer to hash table")); return PVRSRV_ERROR_OUT_OF_MEMORY; } return eError; }
PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line) { OSMEM_DEBUG_INFO *psInfo; PVRSRV_ERROR eError; eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, ppvCpuVAddr, phBlockAlloc, pszFilename, ui32Line); if (eError != PVRSRV_OK) { return eError; } OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size); OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER); /*fill the dbg info struct*/ psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr); OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)); debug_strcpy(psInfo->sFileName, pszFilename); psInfo->uLineNo = ui32Line; psInfo->eValid = isAllocated; psInfo->uSize = ui32Size; psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size; /*point to the user data section*/ *ppvCpuVAddr = (IMG_PVOID) ((IMG_UINTPTR_T)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS; #ifdef PVRSRV_LOG_MEMORY_ALLOCS /*this is here to simplify the surounding logging macro, that is a expression maybe the macro should be an expression */ PVR_TRACE(("Allocated pointer (after debug info): 0x%p from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line)); #endif return PVRSRV_OK; }
PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line) { OSMEM_DEBUG_INFO *psInfo; PVRSRV_ERROR eError; eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags, ui32Size + TEST_BUFFER_PADDING, ppvCpuVAddr, phBlockAlloc, pszFilename, ui32Line); if (eError != PVRSRV_OK) { return eError; } OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size); OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER); psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr); OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)); debug_strcpy(psInfo->sFileName, pszFilename); psInfo->uLineNo = ui32Line; psInfo->eValid = isAllocated; psInfo->uSize = ui32Size; psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size; *ppvCpuVAddr = (IMG_PVOID) ((IMG_UINT32)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS; #ifdef PVRSRV_LOG_MEMORY_ALLOCS PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line)); #endif return PVRSRV_OK; }
IMG_BOOL BM_Alloc(void *hDevMemHeap, struct IMG_DEV_VIRTADDR *psDevVAddr, size_t uSize, u32 *pui32Flags, u32 uDevVAddrAlignment, void **phBuf) { struct BM_BUF *pBuf; struct BM_CONTEXT *pBMContext; struct BM_HEAP *psBMHeap; struct SYS_DATA *psSysData; u32 uFlags; if (pui32Flags == NULL) { PVR_DPF(PVR_DBG_ERROR, "BM_Alloc: invalid parameter"); PVR_DBG_BREAK; return IMG_FALSE; } uFlags = *pui32Flags; PVR_DPF(PVR_DBG_MESSAGE, "BM_Alloc (uSize=0x%x, uFlags=0x%x, uDevVAddrAlignment=0x%x)", uSize, uFlags, uDevVAddrAlignment); if (SysAcquireData(&psSysData) != PVRSRV_OK) return IMG_FALSE; psBMHeap = (struct BM_HEAP *)hDevMemHeap; pBMContext = psBMHeap->pBMContext; if (uDevVAddrAlignment == 0) uDevVAddrAlignment = 1; if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_BUF), (void **)&pBuf, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "BM_Alloc: BM_Buf alloc FAILED"); return IMG_FALSE; } OSMemSet(pBuf, 0, sizeof(struct BM_BUF)); if (AllocMemory(pBMContext, psBMHeap, psDevVAddr, uSize, uFlags, uDevVAddrAlignment, pBuf) != IMG_TRUE) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_BUF), pBuf, NULL); PVR_DPF(PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED"); return IMG_FALSE; } PVR_DPF(PVR_DBG_MESSAGE, "BM_Alloc (uSize=0x%x, uFlags=0x%x)=%08X", uSize, uFlags, pBuf); pBuf->ui32RefCount = 1; pvr_get_ctx(pBMContext); *phBuf = (void *) pBuf; *pui32Flags = uFlags | psBMHeap->ui32Attribs; return IMG_TRUE; }
static enum PVRSRV_ERROR AllocDeviceMem(void *hDevCookie, void *hDevMemHeap, u32 ui32Flags, u32 ui32Size, u32 ui32Alignment, struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo) { struct PVRSRV_KERNEL_MEM_INFO *psMemInfo; void *hBuffer; struct PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; PVR_UNREFERENCED_PARAMETER(hDevCookie); *ppsMemInfo = NULL; if (OSAllocMem(PVRSRV_PAGEABLE_SELECT, sizeof(struct PVRSRV_KERNEL_MEM_INFO), (void **) &psMemInfo, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "AllocDeviceMem: Failed to alloc memory for block"); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemBlock = &(psMemInfo->sMemBlk); psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION; bBMError = BM_Alloc(hDevMemHeap, NULL, ui32Size, &psMemInfo->ui32Flags, ui32Alignment, &hBuffer); if (!bBMError) { PVR_DPF(PVR_DBG_ERROR, "AllocDeviceMem: BM_Alloc Failed"); OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo, NULL); return PVRSRV_ERROR_OUT_OF_MEMORY; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hBuffer = (void *)hBuffer; psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer); psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = ui32Size; psMemInfo->pvSysBackupBuffer = NULL; *ppsMemInfo = psMemInfo; return PVRSRV_OK; }
IMG_EXPORT PVRSRV_ERROR PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_UINT32 ui32Flags, IMG_SIZE_T uSize, PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo) { PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), (IMG_VOID **)&psKernelMemInfo, IMG_NULL, "Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for meminfo")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psKernelMemInfo, 0, sizeof(*psKernelMemInfo)); ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK; ui32Flags |= PVRSRV_HAP_MULTI_PROCESS; psKernelMemInfo->ui32Flags = ui32Flags; psKernelMemInfo->uAllocSize = uSize; if(OSAllocPages(psKernelMemInfo->ui32Flags, psKernelMemInfo->uAllocSize, (IMG_UINT32)HOST_PAGESIZE(), IMG_NULL, 0, IMG_NULL, &psKernelMemInfo->pvLinAddrKM, &psKernelMemInfo->sMemBlk.hOSMemHandle) != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for block")); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psKernelMemInfo, 0); return PVRSRV_ERROR_OUT_OF_MEMORY; } /* register with the resman */ psKernelMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_SHARED_MEM_INFO, psKernelMemInfo, 0, &FreeSharedSysMemCallBack); *ppsKernelMemInfo = psKernelMemInfo; return PVRSRV_OK; }
IMG_INTERNAL PVRSRV_ERROR TLClientCloseStream(IMG_HANDLE hSrvHandle, IMG_HANDLE hSD) { PVRSRV_ERROR eError = PVRSRV_OK; TL_STREAM_DESC* psSD = (TL_STREAM_DESC*) hSD; PVR_ASSERT(hSrvHandle); PVR_ASSERT(hSD); /* Check the caller provided connection is valid */ if(!psSD->hServerSD) { PVR_DPF((PVR_DBG_ERROR, "TLClientCloseStream: descriptor already closed/not open")); return PVRSRV_ERROR_HANDLE_NOT_FOUND; } /* Check if acquire is outstanding, perform release if it is, ignore result * as there is not much we can do if it is an error other than close */ if (psSD->uiReadLen != NO_ACQUIRE) { (void) BridgeTLReleaseData(hSrvHandle, psSD->hServerSD, psSD->uiReadOffset, psSD->uiReadLen); psSD->uiReadLen = psSD->uiReadOffset = NO_ACQUIRE; } /* Clean up DevMem resources used for this stream in this client */ DevmemReleaseCpuVirtAddr(psSD->psUMmemDesc); DevmemFree(psSD->psUMmemDesc); /* Ignore error, not much that can be done */ (void) DevmemUnmakeServerExportClientExport(hSrvHandle, &psSD->sExportCookie); /* Send close to server to clean up kernel mode resources for this * handle and release the memory. */ eError = BridgeTLCloseStream(hSrvHandle, psSD->hServerSD); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "BridgeTLCloseStream: KM returned %d", eError)); /*/ Not much we can do with error, fall through to clean up * return eError; */ } OSMemSet(psSD, 0x00, sizeof(TL_STREAM_DESC)); OSFreeMem (psSD); return eError; }
IMG_INTERNAL PVRSRV_ERROR _DevmemMemDescAlloc(DEVMEM_MEMDESC **ppsMemDesc) { DEVMEM_MEMDESC *psMemDesc; PVRSRV_ERROR eError; psMemDesc = OSAllocMem(sizeof(DEVMEM_MEMDESC)); if (psMemDesc == IMG_NULL) { eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto failAlloc; } /* Structure must be zero'd incase it needs to be freed before it is initialised! */ OSMemSet(psMemDesc, 0, sizeof(DEVMEM_MEMDESC)); eError = OSLockCreate(&psMemDesc->hLock, LOCK_TYPE_PASSIVE); if (eError != PVRSRV_OK) { goto failMDLock; } eError = OSLockCreate(&psMemDesc->sDeviceMemDesc.hLock, LOCK_TYPE_PASSIVE); if (eError != PVRSRV_OK) { goto failDMDLock; } eError = OSLockCreate(&psMemDesc->sCPUMemDesc.hLock, LOCK_TYPE_PASSIVE); if (eError != PVRSRV_OK) { goto failCMDLock; } *ppsMemDesc = psMemDesc; return PVRSRV_OK; failCMDLock: OSLockDestroy(psMemDesc->sDeviceMemDesc.hLock); failDMDLock: OSLockDestroy(psMemDesc->hLock); failMDLock: OSFreeMem(psMemDesc); failAlloc: PVR_ASSERT(eError != PVRSRV_OK); return eError; }
/*! ****************************************************************************** @Function PVRSRVRegisterDevice @Description registers a device with the system @Input psSysData : sysdata structure @Input pfnRegisterDevice : device registration function @Input ui32SOCInterruptBit : SoC interrupt bit for this device @Output pui32DeviceIndex : unique device key (for case of multiple identical devices) @Return PVRSRV_ERROR : ******************************************************************************/ PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData, PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*), IMG_UINT32 ui32SOCInterruptBit, IMG_UINT32 *pui32DeviceIndex) { PVRSRV_ERROR eError; PVRSRV_DEVICE_NODE *psDeviceNode; /* Allocate device node */ if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), (IMG_VOID **)&psDeviceNode, IMG_NULL, "Device Node") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode")); return (PVRSRV_ERROR_OUT_OF_MEMORY); } OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE)); eError = pfnRegisterDevice(psDeviceNode); if (eError != PVRSRV_OK) { OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); /*not nulling pointer, out of scope*/ PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device")); return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED); } /* make the refcount 1 and test on this to initialise device at acquiredevinfo. On release if refcount is 1, deinitialise and when refcount is 0 (sysdata de-alloc) deallocate the device structures */ psDeviceNode->ui32RefCount = 1; psDeviceNode->psSysData = psSysData; psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit; /* all devices need a unique identifier */ AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex); /* and finally insert the device into the dev-list */ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode); /* and copy back index */ *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex; return PVRSRV_OK; }
PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData) { PVRSRV_ERROR eError; IMG_HANDLE hBlockAlloc; PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc; eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_ENV_PER_PROCESS_DATA), phOsPrivateData, &hBlockAlloc, "Environment per Process Data"); if (eError != PVRSRV_OK) { *phOsPrivateData = IMG_NULL; PVR_DPF((PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __FUNCTION__, eError)); return eError; } psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData; OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc)); psEnvPerProc->hBlockAlloc = hBlockAlloc; /* Linux specific mmap processing */ LinuxMMapPerProcessConnect(psEnvPerProc); #if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) /* Linked list of PVRSRV_FILE_PRIVATE_DATA structures */ INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead); #endif #if defined(SUPPORT_ION) OSSNPrintf(psEnvPerProc->azIonClientName, ION_CLIENT_NAME_SIZE, "pvr_ion_client-%d", OSGetCurrentProcessIDKM()); psEnvPerProc->psIONClient = ion_client_create(gpsIonDev, psEnvPerProc->azIonClientName); if (IS_ERR_OR_NULL(psEnvPerProc->psIONClient)) { PVR_DPF((PVR_DBG_ERROR, "OSPerProcessPrivateDataInit: Couldn't create " "ion client for per process data")); return PVRSRV_ERROR_OUT_OF_MEMORY; } #endif /* defined(SUPPORT_ION) */ return PVRSRV_OK; }
PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData, PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*), IMG_UINT32 ui32SOCInterruptBit, IMG_UINT32 *pui32DeviceIndex) { PVRSRV_ERROR eError; PVRSRV_DEVICE_NODE *psDeviceNode; if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), (IMG_VOID **)&psDeviceNode, IMG_NULL, "Device Node") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode")); return (PVRSRV_ERROR_OUT_OF_MEMORY); } OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE)); eError = pfnRegisterDevice(psDeviceNode); if (eError != PVRSRV_OK) { OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device")); return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED); } psDeviceNode->ui32RefCount = 1; psDeviceNode->psSysData = psSysData; psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit; AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex); List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode); *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex; return PVRSRV_OK; }
/*! ****************************************************************************** @Function PVRSRVTimeTraceBufferCreate @Description Create a trace buffer. Note: We assume that this will only be called once per process. @Input ui32PID : PID of the process that is creating the buffer @Return none ******************************************************************************/ PVRSRV_ERROR PVRSRVTimeTraceBufferCreate(IMG_UINT32 ui32PID) { sTimeTraceBuffer *psBuffer; psBuffer = (sTimeTraceBuffer*) KMallocWrapper(sizeof(sTimeTraceBuffer), GFP_NOWAIT | __GFP_NOWARN); if (psBuffer == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferCreate: Error allocating trace buffer header")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psBuffer, 0, sizeof(sTimeTraceBuffer)); psBuffer->pui8Data = (IMG_UINT8*) KMallocWrapper(TIME_TRACE_BUFFER_SIZE, GFP_NOWAIT | __GFP_NOWARN); if (psBuffer->pui8Data == IMG_NULL) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(sTimeTraceBuffer), psBuffer, NULL); PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferCreate: Error allocating trace buffer data")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psBuffer->pui8Data, 0, TIME_TRACE_BUFFER_SIZE); if (!HASH_Insert_NoWait(g_psBufferTable, (IMG_UINTPTR_T) ui32PID, (IMG_UINTPTR_T) psBuffer)) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, TIME_TRACE_BUFFER_SIZE, psBuffer->pui8Data, NULL); OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(sTimeTraceBuffer), psBuffer, NULL); PVR_DPF((PVR_DBG_ERROR, "PVRSRVTimeTraceBufferCreate: Error adding trace buffer to hash table")); return PVRSRV_ERROR_OUT_OF_MEMORY; } return PVRSRV_OK; }
/* PVRSRVConnectionConnect*/ PVRSRV_ERROR PVRSRVConnectionConnect(IMG_PVOID *ppvPrivData, IMG_PVOID pvOSData) { PVRSRV_DATA *psPVRSRVData = PVRSRVGetPVRSRVData(); CONNECTION_DATA *psConnection; PVRSRV_ERROR eError = PVRSRV_OK; /* Allocate per-process data area */ psConnection = OSAllocMem(sizeof(*psConnection)); if (psConnection == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't allocate per-process data (%d)", eError)); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psConnection, 0, sizeof(*psConnection)); /* Call environment specific per process init function */ eError = OSConnectionPrivateDataInit(&psConnection->hOsPrivateData, pvOSData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: OSConnectionPrivateDataInit failed (%d)", eError)); goto failure; } /* Allocate handle base for this process */ eError = PVRSRVAllocHandleBase(&psConnection->psHandleBase); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't allocate handle base for process (%d)", eError)); goto failure; } /* Create a resource manager context for the process */ eError = PVRSRVResManConnect(psPVRSRVData->hResManDeferContext, &psConnection->hResManContext); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVConnectionConnect: Couldn't register with the resource manager")); goto failure; } *ppvPrivData = psConnection; return eError; failure: (IMG_VOID)FreeConnectionData(psConnection); return eError; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie, PVRSRV_HEAP_INFO *psHeapInfo) { PVRSRV_DEVICE_NODE *psDeviceNode; IMG_UINT32 ui32HeapCount; DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; IMG_UINT32 i; if (hDevCookie == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetDeviceMemHeapsKM: hDevCookie invalid")); PVR_DBG_BREAK; return PVRSRV_ERROR_INVALID_PARAMS; } psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie; ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount; psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap; PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS); for(i=0; i<ui32HeapCount; i++) { psHeapInfo[i].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID; psHeapInfo[i].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap; psHeapInfo[i].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase; psHeapInfo[i].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize; psHeapInfo[i].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs; } for(; i < PVRSRV_MAX_CLIENT_HEAPS; i++) { OSMemSet(psHeapInfo + i, 0, sizeof(*psHeapInfo)); psHeapInfo[i].ui32HeapID = (IMG_UINT32)PVRSRV_UNDEFINED_HEAP_ID; } return PVRSRV_OK; }
enum PVRSRV_ERROR PVRSRVAllocSharedSysMemoryKM( struct PVRSRV_PER_PROCESS_DATA *psPerProc, u32 ui32Flags, u32 ui32Size, struct PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo) { struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo; if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_KERNEL_MEM_INFO), (void **) &psKernelMemInfo, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: " "Failed to alloc memory for meminfo"); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psKernelMemInfo, 0, sizeof(*psKernelMemInfo)); ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK; ui32Flags |= PVRSRV_HAP_MULTI_PROCESS; psKernelMemInfo->ui32Flags = ui32Flags; psKernelMemInfo->ui32AllocSize = ui32Size; if (OSAllocPages(psKernelMemInfo->ui32Flags, psKernelMemInfo->ui32AllocSize, HOST_PAGESIZE(), &psKernelMemInfo->pvLinAddrKM, &psKernelMemInfo->sMemBlk.hOSMemHandle) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: " "Failed to alloc memory for block"); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_KERNEL_MEM_INFO), psKernelMemInfo, NULL); return PVRSRV_ERROR_OUT_OF_MEMORY; } psKernelMemInfo->sMemBlk.hResItem = ResManRegisterRes( psPerProc->hResManContext, RESMAN_TYPE_SHARED_MEM_INFO, psKernelMemInfo, 0, FreeSharedSysMemCallBack); *ppsKernelMemInfo = psKernelMemInfo; return PVRSRV_OK; }
PVRSRV_ERROR SysCreateConfigData(PVRSRV_SYSTEM_CONFIG **ppsSysConfig) { PLAT_DATA *psPlatData; PVRSRV_ERROR eError; psPlatData = OSAllocMem(sizeof(PLAT_DATA)); OSMemSet(psPlatData, 0, sizeof(PLAT_DATA)); /* Query the Emu for reg and IRQ information */ eError = PCIInitDev(psPlatData); if (eError != PVRSRV_OK) { goto e0; } /* Save data for this device */ sSysConfig.pasDevices[0].hSysData = (IMG_HANDLE) psPlatData; /* Save private data for the physical memory heap */ gsPhysHeapConfig[0].hPrivData = (IMG_HANDLE) psPlatData; #if defined(TDMETACODE) #error "Not supported services/3rdparty/intel_drm/sysconfig.c" gsPhysHeapConfig[1].hPrivData = IMG_NULL; #endif *ppsSysConfig = &sSysConfig; gpsPlatData = psPlatData; /* Setup other system specific stuff */ #if defined(SUPPORT_ION) #error "Need to check this function call" IonInit(NULL); #endif return PVRSRV_OK; e0: return eError; }
enum PVRSRV_ERROR PVRSRVRegisterDevice(struct SYS_DATA *psSysData, enum PVRSRV_ERROR(*pfnRegisterDevice) (struct PVRSRV_DEVICE_NODE *), u32 ui32SOCInterruptBit, u32 *pui32DeviceIndex) { enum PVRSRV_ERROR eError; struct PVRSRV_DEVICE_NODE *psDeviceNode; if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(struct PVRSRV_DEVICE_NODE), (void **) &psDeviceNode, NULL) != PVRSRV_OK) { PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterDevice : " "Failed to alloc memory for psDeviceNode"); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psDeviceNode, 0, sizeof(struct PVRSRV_DEVICE_NODE)); eError = pfnRegisterDevice(psDeviceNode); if (eError != PVRSRV_OK) { OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(struct PVRSRV_DEVICE_NODE), psDeviceNode, NULL); PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterDevice : " "Failed to register device"); return PVRSRV_ERROR_DEVICE_REGISTER_FAILED; } psDeviceNode->ui32RefCount = 1; psDeviceNode->psSysData = psSysData; psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit; AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex); psDeviceNode->psNext = psSysData->psDeviceNodeList; psSysData->psDeviceNodeList = psDeviceNode; *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex; return PVRSRV_OK; }
/*! ****************************************************************************** @Function SysInitialise @Description Initialises kernel services at 'driver load' time @Return PVRSRV_ERROR : ******************************************************************************/ PVRSRV_ERROR SysInitialise(IMG_VOID) { IMG_UINT32 i; PVRSRV_ERROR eError; PVRSRV_DEVICE_NODE *psDeviceNode; #if !defined(PVR_NO_OMAP_TIMER) IMG_CPU_PHYADDR TimerRegPhysBase; #endif #if !defined(SGX_DYNAMIC_TIMING_INFO) SGX_TIMING_INFORMATION* psTimingInfo; #endif PVR_TRACE(("SysInitialise started")); gpsSysData = &gsSysData; OSMemSet(gpsSysData, 0, sizeof(SYS_DATA)); gpsSysSpecificData = &gsSysSpecificData; OSMemSet(gpsSysSpecificData, 0, sizeof(SYS_SPECIFIC_DATA)); gpsSysData->pvSysSpecificData = gpsSysSpecificData; eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to setup env structure")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA); gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT; /* init device ID's */ for(i=0; i<SYS_DEVICE_COUNT; i++) { gpsSysData->sDeviceID[i].uiID = i; gpsSysData->sDeviceID[i].bInUse = IMG_FALSE; } gpsSysData->psDeviceNodeList = IMG_NULL; gpsSysData->psQueueList = IMG_NULL; eError = SysInitialiseCommon(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed in SysInitialiseCommon")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } #if !defined(SGX_DYNAMIC_TIMING_INFO) /* Set up timing information*/ psTimingInfo = &gsSGXDeviceMap.sTimingInfo; psTimingInfo->ui32CoreClockSpeed = SYS_SGX_CLOCK_SPEED; psTimingInfo->ui32HWRecoveryFreq = SYS_SGX_HWRECOVERY_TIMEOUT_FREQ; #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) psTimingInfo->bEnableActivePM = IMG_TRUE; #else psTimingInfo->bEnableActivePM = IMG_FALSE; #endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */ psTimingInfo->ui32ActivePowManLatencyms = SYS_SGX_ACTIVE_POWER_LATENCY_MS; psTimingInfo->ui32uKernelFreq = SYS_SGX_PDS_TIMER_FREQ; #endif /* Setup the Source Clock Divider value */ gpsSysSpecificData->ui32SrcClockDiv = 3; /* Locate the devices within the system, specifying the physical addresses of each devices components (regs, mem, ports etc.) */ eError = SysLocateDevices(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to locate devices")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV); eError = SysPMRuntimeRegister(); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register with OSPM!")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PM_RUNTIME); eError = SysDvfsInitialize(gpsSysSpecificData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialize DVFS")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_DVFS_INIT); /* Register devices with the system This also sets up their memory maps/heaps */ eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice, DEVICE_SGX_INTERRUPT, &gui32SGXDeviceID); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to register device!")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_REGDEV); /* Once all devices are registered, specify the backing store and, if required, customise the memory heap config */ psDeviceNode = gpsSysData->psDeviceNodeList; while(psDeviceNode) { /* perform any OEM SOC address space customisations here */ switch(psDeviceNode->sDevId.eDeviceType) { case PVRSRV_DEVICE_TYPE_SGX: { DEVICE_MEMORY_INFO *psDevMemoryInfo; DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; /* specify the backing store to use for the devices MMU PT/PDs - the PT/PDs are always UMA in this system */ psDeviceNode->psLocalDevMemArena = IMG_NULL; /* useful pointers */ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo; psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap; /* specify the backing store for all SGX heaps */ for(i=0; i<psDevMemoryInfo->ui32HeapCount; i++) { psDeviceMemoryHeap[i].ui32Attribs |= PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG; } gpsSGXDevNode = psDeviceNode; gsSysSpecificData.psSGXDevNode = psDeviceNode; break; } default: PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to find SGX device node!")); return PVRSRV_ERROR_INIT_FAILURE; } /* advance to next device */ psDeviceNode = psDeviceNode->psNext; } eError = EnableSystemClocksWrap(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to Enable system clocks (%d)", eError)); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS); #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) eError = EnableSGXClocksWrap(gpsSysData); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to Enable SGX clocks (%d)", eError)); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } #endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */ eError = PVRSRVInitialiseDevice(gui32SGXDeviceID); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"SysInitialise: Failed to initialise device!")); (IMG_VOID)SysDeinitialise(gpsSysData); gpsSysData = IMG_NULL; return eError; } SYS_SPECIFIC_DATA_SET(&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV); #if defined(SUPPORT_ACTIVE_POWER_MANAGEMENT) /* SGX defaults to D3 power state */ DisableSGXClocks(gpsSysData); #endif /* SUPPORT_ACTIVE_POWER_MANAGEMENT */ #if !defined(PVR_NO_OMAP_TIMER) #if defined(PVR_OMAP_TIMER_BASE_IN_SYS_SPEC_DATA) TimerRegPhysBase = gsSysSpecificData.sTimerRegPhysBase; #else TimerRegPhysBase.uiAddr = SYS_OMAP3630_GP11TIMER_REGS_SYS_PHYS_BASE; #endif gpsSysData->pvSOCTimerRegisterKM = IMG_NULL; gpsSysData->hSOCTimerRegisterOSMemHandle = 0; if (TimerRegPhysBase.uiAddr != 0) { OSReservePhys(TimerRegPhysBase, 4, PVRSRV_HAP_MULTI_PROCESS|PVRSRV_HAP_UNCACHED, IMG_NULL, (IMG_VOID **)&gpsSysData->pvSOCTimerRegisterKM, &gpsSysData->hSOCTimerRegisterOSMemHandle); } #endif /* !defined(PVR_NO_OMAP_TIMER) */ PVR_TRACE(("SysInitialise OK")); return PVRSRV_OK; }
/*! ****************************************************************************** @Function SysLocateDevices @Description Specifies devices in the systems memory map @Input psSysData - sys data @Return PVRSRV_ERROR ******************************************************************************/ static PVRSRV_ERROR SysLocateDevices(SYS_DATA *psSysData) { #if defined(NO_HARDWARE) PVRSRV_ERROR eError; IMG_CPU_PHYADDR sCpuPAddr; #else #if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) struct resource *dev_res; int dev_irq; #endif #endif PVR_UNREFERENCED_PARAMETER(psSysData); /* SGX Device: */ gsSGXDeviceMap.ui32Flags = 0x0; #if defined(NO_HARDWARE) /* * For no hardware, allocate some contiguous memory for the * register block. */ /* Registers */ gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3630_SGX_REGS_SIZE; eError = OSBaseAllocContigMemory(gsSGXDeviceMap.ui32RegsSize, &gsSGXRegsCPUVAddr, &sCpuPAddr); if(eError != PVRSRV_OK) { return eError; } gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr; gsSGXDeviceMap.sRegsSysPBase = SysCpuPAddrToSysPAddr(gsSGXDeviceMap.sRegsCpuPBase); #if defined(__linux__) /* Indicate the registers are already mapped */ gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr; #else /* * FIXME: Could we just use the virtual address returned by * OSBaseAllocContigMemory? */ gsSGXDeviceMap.pvRegsCpuVBase = IMG_NULL; #endif OSMemSet(gsSGXRegsCPUVAddr, 0, gsSGXDeviceMap.ui32RegsSize); /* device interrupt IRQ Note: no interrupts available on no hardware system */ gsSGXDeviceMap.ui32IRQ = 0; #else /* defined(NO_HARDWARE) */ #if defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) /* get the resource and IRQ through platform resource API */ dev_res = platform_get_resource(gpsPVRLDMDev, IORESOURCE_MEM, 0); if (dev_res == NULL) { PVR_DPF((PVR_DBG_ERROR, "%s: platform_get_resource failed", __FUNCTION__)); return PVRSRV_ERROR_INVALID_DEVICE; } dev_irq = platform_get_irq(gpsPVRLDMDev, 0); if (dev_irq < 0) { PVR_DPF((PVR_DBG_ERROR, "%s: platform_get_irq failed (%d)", __FUNCTION__, -dev_irq)); return PVRSRV_ERROR_INVALID_DEVICE; } gsSGXDeviceMap.sRegsSysPBase.uiAddr = dev_res->start; gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase); PVR_TRACE(("SGX register base: 0x%lx", (unsigned long)gsSGXDeviceMap.sRegsCpuPBase.uiAddr)); #if defined(SGX544) && defined(SGX_FEATURE_MP) /* FIXME: Workaround due to HWMOD change. Otherwise this region is too small. */ gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3630_SGX_REGS_SIZE; #else gsSGXDeviceMap.ui32RegsSize = (unsigned int)(dev_res->end - dev_res->start); #endif PVR_TRACE(("SGX register size: %d",gsSGXDeviceMap.ui32RegsSize)); gsSGXDeviceMap.ui32IRQ = dev_irq; PVR_TRACE(("SGX IRQ: %d", gsSGXDeviceMap.ui32IRQ)); #else /* defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) */ gsSGXDeviceMap.sRegsSysPBase.uiAddr = SYS_OMAP3630_SGX_REGS_SYS_PHYS_BASE; gsSGXDeviceMap.sRegsCpuPBase = SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase); gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3630_SGX_REGS_SIZE; gsSGXDeviceMap.ui32IRQ = SYS_OMAP3630_SGX_IRQ; #endif /* defined(PVR_LINUX_DYNAMIC_SGX_RESOURCE_INFO) */ #if defined(SGX_OCP_REGS_ENABLED) gsSGXRegsCPUVAddr = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase, gsSGXDeviceMap.ui32RegsSize, PVRSRV_HAP_UNCACHED|PVRSRV_HAP_KERNEL_ONLY, IMG_NULL); if (gsSGXRegsCPUVAddr == IMG_NULL) { PVR_DPF((PVR_DBG_ERROR,"SysLocateDevices: Failed to map SGX registers")); return PVRSRV_ERROR_BAD_MAPPING; } /* Indicate the registers are already mapped */ gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr; gpvOCPRegsLinAddr = gsSGXRegsCPUVAddr; #endif #endif /* defined(NO_HARDWARE) */ #if defined(PDUMP) { /* initialise memory region name for pdumping */ static IMG_CHAR pszPDumpDevName[] = "SGXMEM"; gsSGXDeviceMap.pszPDumpDevName = pszPDumpDevName; } #endif /* add other devices here: */ 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; }
static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie, IMG_HANDLE hDevMemHeap, IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_SIZE_T ui32Alignment, PVRSRV_KERNEL_MEM_INFO **ppsMemInfo) { PVRSRV_KERNEL_MEM_INFO *psMemInfo; BM_HANDLE hBuffer; PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; PVR_UNREFERENCED_PARAMETER(hDevCookie); *ppsMemInfo = IMG_NULL; if(OSAllocMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), (IMG_VOID **)&psMemInfo, IMG_NULL, "Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: Failed to alloc memory for block")); return (PVRSRV_ERROR_OUT_OF_MEMORY); } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemBlock = &(psMemInfo->sMemBlk); psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION; bBMError = BM_Alloc (hDevMemHeap, IMG_NULL, ui32Size, &psMemInfo->ui32Flags, IMG_CAST_TO_DEVVADDR_UINT(ui32Alignment), &hBuffer); if (!bBMError) { PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: BM_Alloc Failed")); OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); return PVRSRV_ERROR_OUT_OF_MEMORY; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hBuffer = (IMG_HANDLE)hBuffer; psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer); psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = ui32Size; psMemInfo->pvSysBackupBuffer = IMG_NULL; *ppsMemInfo = psMemInfo; return (PVRSRV_OK); }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_HANDLE hDevMemContext, IMG_HANDLE hDeviceClassBuffer, PVRSRV_KERNEL_MEM_INFO **ppsMemInfo, IMG_HANDLE *phOSMapInfo) { PVRSRV_ERROR eError; PVRSRV_DEVICE_NODE* psDeviceNode; PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL; PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer; IMG_SYS_PHYADDR *psSysPAddr; IMG_VOID *pvCPUVAddr, *pvPageAlignedCPUVAddr; IMG_BOOL bPhysContig; BM_CONTEXT *psBMContext; DEVICE_MEMORY_INFO *psDevMemoryInfo; DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap; IMG_HANDLE hDevMemHeap = IMG_NULL; IMG_SIZE_T ui32ByteSize; IMG_SIZE_T ui32Offset; IMG_SIZE_T ui32PageSize = HOST_PAGESIZE(); BM_HANDLE hBuffer; PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; IMG_UINT32 i; PVRSRV_DC_MAPINFO *psDCMapInfo = IMG_NULL; if(!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo || !hDevMemContext) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_MAPINFO), (IMG_VOID **)&psDCMapInfo, IMG_NULL, "PVRSRV_DC_MAPINFO") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for psDCMapInfo")); return PVRSRV_ERROR_OUT_OF_MEMORY; } OSMemSet(psDCMapInfo, 0, sizeof(PVRSRV_DC_MAPINFO)); psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer; eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice, psDeviceClassBuffer->hExtBuffer, &psSysPAddr, &ui32ByteSize, &pvCPUVAddr, phOSMapInfo, &bPhysContig, &psDCMapInfo->ui32TilingStride); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: unable to get buffer address")); goto ErrorExitPhase1; } psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext; psDeviceNode = psBMContext->psDeviceNode; psDevMemoryInfo = &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,"PVRSRVMapDeviceClassMemoryKM: unable to find mapping heap")); eError = PVRSRV_ERROR_UNABLE_TO_FIND_RESOURCE; goto ErrorExitPhase1; } ui32Offset = ((IMG_UINTPTR_T)pvCPUVAddr) & (ui32PageSize - 1); pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - ui32Offset); eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), (IMG_VOID **)&psMemInfo, IMG_NULL, "Kernel Memory Info"); if(eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block")); goto ErrorExitPhase1; } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemBlock = &(psMemInfo->sMemBlk); bBMError = BM_Wrap(hDevMemHeap, ui32ByteSize, ui32Offset, bPhysContig, psSysPAddr, pvPageAlignedCPUVAddr, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed")); eError = PVRSRV_ERROR_BAD_MAPPING; goto ErrorExitPhase2; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hBuffer = (IMG_HANDLE)hBuffer; psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer); psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = ui32ByteSize; psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo; psMemInfo->pvSysBackupBuffer = IMG_NULL; psDCMapInfo->psMemInfo = psMemInfo; #if defined(SUPPORT_MEMORY_TILING) psDCMapInfo->psDeviceNode = psDeviceNode; if(psDCMapInfo->ui32TilingStride > 0) { eError = psDeviceNode->pfnAllocMemTilingRange(psDeviceNode, psMemInfo, psDCMapInfo->ui32TilingStride, &psDCMapInfo->ui32RangeIndex); if (eError != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: AllocMemTilingRange failed")); goto ErrorExitPhase3; } } #endif psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, psDCMapInfo, 0, &UnmapDeviceClassMemoryCallBack); psMemInfo->ui32RefCount++; psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS; *ppsMemInfo = psMemInfo; #if defined(SUPPORT_PDUMP_MULTI_PROCESS) PDUMPCOMMENT("Dump display surface"); PDUMPMEM(IMG_NULL, psMemInfo, ui32Offset, psMemInfo->ui32AllocSize, PDUMP_FLAGS_CONTINUOUS, ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping); #endif return PVRSRV_OK; #if defined(SUPPORT_MEMORY_TILING) ErrorExitPhase3: if(psMemInfo) { FreeDeviceMem(psMemInfo); psMemInfo = IMG_NULL; } #endif ErrorExitPhase2: if(psMemInfo) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); } ErrorExitPhase1: if(psDCMapInfo) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psDCMapInfo, IMG_NULL); } return eError; }
IMG_EXPORT PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc, PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo, IMG_HANDLE hDstDevMemHeap, PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo) { PVRSRV_ERROR eError; IMG_UINT32 i; IMG_SIZE_T ui32PageCount, ui32PageOffset; IMG_SIZE_T ui32HostPageSize = HOST_PAGESIZE(); IMG_SYS_PHYADDR *psSysPAddr = IMG_NULL; IMG_DEV_PHYADDR sDevPAddr; BM_BUF *psBuf; IMG_DEV_VIRTADDR sDevVAddr; PVRSRV_KERNEL_MEM_INFO *psMemInfo = IMG_NULL; BM_HANDLE hBuffer; PVRSRV_MEMBLK *psMemBlock; IMG_BOOL bBMError; PVRSRV_DEVICE_NODE *psDeviceNode; IMG_VOID *pvPageAlignedCPUVAddr; RESMAN_MAP_DEVICE_MEM_DATA *psMapData = IMG_NULL; if(!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters")); return PVRSRV_ERROR_INVALID_PARAMS; } *ppsDstMemInfo = IMG_NULL; ui32PageOffset = psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1); ui32PageCount = HOST_PAGEALIGN(psSrcMemInfo->ui32AllocSize + ui32PageOffset) / ui32HostPageSize; pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psSrcMemInfo->pvLinAddrKM - ui32PageOffset); if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageCount*sizeof(IMG_SYS_PHYADDR), (IMG_VOID **)&psSysPAddr, IMG_NULL, "Array of Page Addresses") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block")); return PVRSRV_ERROR_OUT_OF_MEMORY; } psBuf = psSrcMemInfo->sMemBlk.hBuffer; psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode; sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - IMG_CAST_TO_DEVVADDR_UINT(ui32PageOffset); for(i=0; i<ui32PageCount; i++) { BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr); psSysPAddr[i] = SysDevPAddrToSysPAddr (psDeviceNode->sDevId.eDeviceType, sDevPAddr); sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize); } if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), (IMG_VOID **)&psMapData, IMG_NULL, "Resource Manager Map Data") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc resman map data")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExit; } if(OSAllocMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), (IMG_VOID **)&psMemInfo, IMG_NULL, "Kernel Memory Info") != PVRSRV_OK) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block")); eError = PVRSRV_ERROR_OUT_OF_MEMORY; goto ErrorExit; } OSMemSet(psMemInfo, 0, sizeof(*psMemInfo)); psMemInfo->ui32Flags = psSrcMemInfo->ui32Flags; psMemBlock = &(psMemInfo->sMemBlk); bBMError = BM_Wrap(hDstDevMemHeap, psSrcMemInfo->ui32AllocSize, ui32PageOffset, IMG_FALSE, psSysPAddr, pvPageAlignedCPUVAddr, &psMemInfo->ui32Flags, &hBuffer); if (!bBMError) { PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: BM_Wrap Failed")); eError = PVRSRV_ERROR_BAD_MAPPING; goto ErrorExit; } psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer); psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer); psMemBlock->hBuffer = (IMG_HANDLE)hBuffer; psMemBlock->psIntSysPAddr = psSysPAddr; psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM; psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr; psMemInfo->ui32AllocSize = psSrcMemInfo->ui32AllocSize; psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo; if( psMemInfo->psKernelSyncInfo ) psMemInfo->psKernelSyncInfo->ui32RefCount++; psMemInfo->pvSysBackupBuffer = IMG_NULL; psMemInfo->ui32RefCount++; psSrcMemInfo->ui32RefCount++; BM_Export(psSrcMemInfo->sMemBlk.hBuffer); psMemInfo->memType = PVRSRV_MEMTYPE_MAPPED; psMapData->psMemInfo = psMemInfo; psMapData->psSrcMemInfo = psSrcMemInfo; psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext, RESMAN_TYPE_DEVICEMEM_MAPPING, psMapData, 0, &UnmapDeviceMemoryCallBack); *ppsDstMemInfo = psMemInfo; return PVRSRV_OK; ErrorExit: if(psSysPAddr) { OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psSysPAddr, IMG_NULL); } if(psMemInfo) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL); } if(psMapData) { OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL); } return eError; }