enum PVRSRV_ERROR PVRSRVWrapExtMemoryKM(void *hDevCookie,
			    struct PVRSRV_PER_PROCESS_DATA *psPerProc,
			    void *hDevMemContext, u32 ui32ByteSize,
			    u32 ui32PageOffset, IMG_BOOL bPhysContig,
			    struct IMG_SYS_PHYADDR *psExtSysPAddr,
			    void *pvLinAddr,
			    struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
{
	struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = NULL;
	struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
	u32 ui32HostPageSize = HOST_PAGESIZE();
	void *hDevMemHeap = NULL;
	struct PVRSRV_DEVICE_NODE *psDeviceNode;
	void *hBuffer;
	struct PVRSRV_MEMBLK *psMemBlock;
	IMG_BOOL bBMError;
	struct BM_HEAP *psBMHeap;
	enum PVRSRV_ERROR eError;
	void *pvPageAlignedCPUVAddr;
	struct IMG_SYS_PHYADDR *psIntSysPAddr = NULL;
	void *hOSWrapMem = NULL;
	struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
	int page_count = 0;
	u32 i;

	psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie;
	PVR_ASSERT(psDeviceNode != NULL);

	if (!psDeviceNode || (!pvLinAddr && !psExtSysPAddr)) {
		PVR_DPF(PVR_DBG_ERROR,
			 "PVRSRVWrapExtMemoryKM: invalid parameter");
		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	if (pvLinAddr) {
		get_page_details((u32)pvLinAddr, ui32ByteSize,
				&ui32PageOffset, &page_count);
		pvPageAlignedCPUVAddr = (void *)((u8 *) pvLinAddr -
					ui32PageOffset);

		if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
			       page_count * sizeof(struct IMG_SYS_PHYADDR),
			       (void **)&psIntSysPAddr, NULL) != PVRSRV_OK) {
			PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: "
					"Failed to alloc memory for block");
			return PVRSRV_ERROR_OUT_OF_MEMORY;
		}

		eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
				       page_count * 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;
	}

	psDevMemoryInfo =
	    &((struct 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 == NULL) {
		PVR_DPF(PVR_DBG_ERROR,
			 "PVRSRVWrapExtMemoryKM: unable to find mapping heap");
		eError = PVRSRV_ERROR_GENERIC;
		goto ErrorExitPhase2;
	}

	if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
		       sizeof(struct PVRSRV_KERNEL_MEM_INFO),
		       (void **) &psMemInfo, NULL) != 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));
	psMemBlock = &(psMemInfo->sMemBlk);

	bBMError = BM_Wrap(hDevMemHeap,
			   ui32ByteSize,
			   ui32PageOffset,
			   bPhysContig,
			   psExtSysPAddr,
			   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 = (void *) hBuffer;

	psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
	psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
	psMemInfo->ui32AllocSize = ui32ByteSize;

	psMemInfo->pvSysBackupBuffer = NULL;

	psBMHeap = (struct BM_HEAP *)hDevMemHeap;
	hDevMemContext = (void *) psBMHeap->pBMContext;
	eError = alloc_or_reuse_syncinfo(hDevCookie,
					 hDevMemContext,
					 &psMemInfo->psKernelSyncInfo,
					 psExtSysPAddr);
	if (eError != PVRSRV_OK)
		goto ErrorExitPhase4;

	psMemInfo->ui32RefCount++;

	psMemInfo->sMemBlk.hResItem =
	    ResManRegisterRes(psPerProc->hResManContext,
			      RESMAN_TYPE_DEVICEMEM_WRAP, psMemInfo, 0,
			      UnwrapExtMemoryCallBack);

	*ppsMemInfo = psMemInfo;

	return PVRSRV_OK;

ErrorExitPhase4:
	FreeDeviceMem(psMemInfo);
	psMemInfo = NULL;

ErrorExitPhase3:
	if (psMemInfo) {
		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
			  sizeof(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo,
			  NULL);
	}

ErrorExitPhase2:
	if (hOSWrapMem)
		OSReleasePhysPageAddr(hOSWrapMem);

ErrorExitPhase1:
	if (psIntSysPAddr) {
		OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
			  page_count * sizeof(struct IMG_SYS_PHYADDR),
			  psIntSysPAddr, NULL);
	}

	return eError;
}
Esempio n. 2
0
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;
}
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
#endif
{
	SYS_DATA *psSysData;

	if(!psMiscInfo)
	{
		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid parameters"));
		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	psMiscInfo->ui32StatePresent = 0;

	
	if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
										|PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
										|PVRSRV_MISC_INFO_MEMSTATS_PRESENT
										|PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT
										|PVRSRV_MISC_INFO_DDKVERSION_PRESENT
										|PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT
										|PVRSRV_MISC_INFO_RESET_PRESENT
										|PVRSRV_MISC_INFO_FREEMEM_PRESENT))
	{
		PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
		return PVRSRV_ERROR_INVALID_PARAMS;
	}

	SysAcquireData(&psSysData);

	
	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
		(psSysData->pvSOCTimerRegisterKM != IMG_NULL))
	{
		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
		psMiscInfo->pvSOCTimerRegisterKM = psSysData->pvSOCTimerRegisterKM;
		psMiscInfo->hSOCTimerRegisterOSMemHandle = psSysData->hSOCTimerRegisterOSMemHandle;
	}
	else
	{
		psMiscInfo->pvSOCTimerRegisterKM = IMG_NULL;
		psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
	}

	
	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
		(psSysData->pvSOCClockGateRegsBase != IMG_NULL))
	{
		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
		psMiscInfo->pvSOCClockGateRegs = psSysData->pvSOCClockGateRegsBase;
		psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
	}

	
	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
		(psMiscInfo->pszMemoryStr != IMG_NULL))
	{
		RA_ARENA			**ppArena;
		IMG_CHAR			*pszStr;
		IMG_UINT32			ui32StrLen;
		IMG_INT32			i32Count;

		pszStr = psMiscInfo->pszMemoryStr;
		ui32StrLen = psMiscInfo->ui32MemoryStrLen;

		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;

		
		ppArena = &psSysData->apsLocalDevMemArena[0];
		while(*ppArena)
		{
			CHECK_SPACE(ui32StrLen);
			i32Count = OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
			UPDATE_SPACE(pszStr, i32Count, ui32StrLen);

			RA_GetStats(*ppArena,
							&pszStr,
							&ui32StrLen);
			
			ppArena++;
		}

		
		
		List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
													&PVRSRVGetMiscInfoKM_Device_AnyVaCb,
													&ui32StrLen,
													&i32Count,
													&pszStr,
													PVRSRV_MISC_INFO_MEMSTATS_PRESENT);

		
		i32Count = OSSNPrintf(pszStr, 100, "\n");
		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
	}

	
	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0)
		&& psMiscInfo->pszMemoryStr)
	{
		IMG_CHAR			*pszStr;
		IMG_UINT32			ui32StrLen;
		IMG_INT32			i32Count;
		
		pszStr = psMiscInfo->pszMemoryStr;
		ui32StrLen = psMiscInfo->ui32MemoryStrLen;
  
		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT;

		
		List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
													&PVRSRVGetMiscInfoKM_Device_AnyVaCb,
													&ui32StrLen,
													&i32Count,
													&pszStr,
													PVRSRV_MISC_INFO_FREEMEM_PRESENT);
		
		i32Count = OSSNPrintf(pszStr, 100, "\n");
		UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
	}

	if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) != 0UL) &&
		(psSysData->psGlobalEventObject != IMG_NULL))
	{
		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
		psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
	}

	

	if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
		&& ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
		&& (psMiscInfo->pszMemoryStr != IMG_NULL))
	{
		IMG_CHAR	*pszStr;
		IMG_UINT32	ui32StrLen;
		IMG_UINT32 	ui32LenStrPerNum = 12; 
		IMG_INT32	i32Count;
		IMG_INT i;
		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;

		
		psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
		psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
		psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH;
		psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD;

		pszStr = psMiscInfo->pszMemoryStr;
		ui32StrLen = psMiscInfo->ui32MemoryStrLen;

		for (i=0; i<4; i++)
		{
			if (ui32StrLen < ui32LenStrPerNum)
			{
				return PVRSRV_ERROR_INVALID_PARAMS;
			}

			i32Count = OSSNPrintf(pszStr, ui32LenStrPerNum, "%u", psMiscInfo->aui32DDKVersion[i]);
			UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
			if (i != 3)
			{
				i32Count = OSSNPrintf(pszStr, 2, ".");
				UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
			}
		}
	}

	if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT) != 0UL)
	{
		psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT;

		if(psMiscInfo->sCacheOpCtl.bDeferOp)
		{
			
			psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType;
		}
		else
		{
#if defined (SUPPORT_SID_INTERFACE)
			PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = psMiscInfo->sCacheOpCtl.psKernelMemInfo;

			if(!psMiscInfo->sCacheOpCtl.psKernelMemInfo)
#else
			PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
			PVRSRV_PER_PROCESS_DATA *psPerProc;

			if(!psMiscInfo->sCacheOpCtl.u.psKernelMemInfo)
#endif
			{
				PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
						 "Ignoring non-deferred cache op with no meminfo"));
				return PVRSRV_ERROR_INVALID_PARAMS;
			}

			if(psSysData->ePendingCacheOpType != PVRSRV_MISC_INFO_CPUCACHEOP_NONE)
			{
				PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetMiscInfoKM: "
						 "Deferred cache op is pending. It is unlikely you want "
						 "to combine deferred cache ops with immediate ones"));
			}

#if defined (SUPPORT_SID_INTERFACE)
			PVR_DBG_BREAK
#else
			
			psPerProc = PVRSRVFindPerProcessData();

			if(PVRSRVLookupHandle(psPerProc->psHandleBase,
								  (IMG_PVOID *)&psKernelMemInfo,
								  psMiscInfo->sCacheOpCtl.u.psKernelMemInfo,
								  PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
			{
				PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
						 "Can't find kernel meminfo"));
				return PVRSRV_ERROR_INVALID_PARAMS;
			}
#endif

			if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
			{
				if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
										   psMiscInfo->sCacheOpCtl.pvBaseVAddr,
										   psMiscInfo->sCacheOpCtl.ui32Length))
				{
					return PVRSRV_ERROR_CACHEOP_FAILED;
				}
			}
			else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
			{
				if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
										   psMiscInfo->sCacheOpCtl.pvBaseVAddr,
										   psMiscInfo->sCacheOpCtl.ui32Length))
				{
					return PVRSRV_ERROR_CACHEOP_FAILED;
				}
			}
/* FIXME: Temporary fix needs to be revisited
 * LinuxMemArea struct listing is not registered for memory areas
 * wrapped through PVR2DMemWrap() call. For now, we are doing
 * cache flush/inv by grabbing the physical pages through
 * get_user_pages() for every blt call.
 */
			else if (psMiscInfo->sCacheOpCtl.eCacheOpType ==
						PVRSRV_MISC_INFO_CPUCACHEOP_CUSTOM_FLUSH)
			{
#if defined(CONFIG_OUTER_CACHE) && defined(PVR_NO_FULL_CACHE_OPS)
				if (1)
				{
					IMG_SIZE_T 	uPageOffset, uPageCount;
					IMG_VOID	*pvPageAlignedCPUVAddr;
					IMG_SYS_PHYADDR	 	*psIntSysPAddr = IMG_NULL;
					IMG_HANDLE	hOSWrapMem = IMG_NULL;
					PVRSRV_ERROR eError;
					int i;

					uPageOffset = (IMG_UINTPTR_T)psMiscInfo->sCacheOpCtl.pvBaseVAddr & (HOST_PAGESIZE() - 1);
					uPageCount =
						HOST_PAGEALIGN(psMiscInfo->sCacheOpCtl.ui32Length + uPageOffset)/HOST_PAGESIZE();
					pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psMiscInfo->sCacheOpCtl.pvBaseVAddr - uPageOffset);

					if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
						uPageCount * 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,
										uPageCount * HOST_PAGESIZE(),
										psIntSysPAddr,
										&hOSWrapMem);
					for (i = 0; i < uPageCount; i++)
					{
						outer_flush_range(psIntSysPAddr[i].uiAddr, psIntSysPAddr[i].uiAddr + HOST_PAGESIZE() -1);
					}

					OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
						uPageCount * sizeof(IMG_SYS_PHYADDR),
						psIntSysPAddr, IMG_NULL);

					OSReleasePhysPageAddr(hOSWrapMem);

				}
#else
				OSFlushCPUCacheKM();
#endif /* CONFIG_OUTER_CACHE && PVR_NO_FULL_CACHE_OPS*/
			}
			else if (psMiscInfo->sCacheOpCtl.eCacheOpType ==
							PVRSRV_MISC_INFO_CPUCACHEOP_CUSTOM_INV)
			{
#if defined(CONFIG_OUTER_CACHE)
				/* TODO: Need to check full cache invalidation, but
				 * currently it is not exported through
				 * outer_cache interface.
				 */
				if (1)
				{
					IMG_SIZE_T 	uPageOffset, uPageCount;
					IMG_VOID	*pvPageAlignedCPUVAddr;
					IMG_SYS_PHYADDR	 	*psIntSysPAddr = IMG_NULL;
					IMG_HANDLE	hOSWrapMem = IMG_NULL;
					PVRSRV_ERROR eError;
					int i;

					uPageOffset = (IMG_UINTPTR_T)psMiscInfo->sCacheOpCtl.pvBaseVAddr & (HOST_PAGESIZE() - 1);
					uPageCount =
						HOST_PAGEALIGN(psMiscInfo->sCacheOpCtl.ui32Length + uPageOffset)/HOST_PAGESIZE();
					pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psMiscInfo->sCacheOpCtl.pvBaseVAddr - uPageOffset);

					if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
						uPageCount * 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,
										uPageCount * HOST_PAGESIZE(),
										psIntSysPAddr,
										&hOSWrapMem);
					for (i = 0; i < uPageCount; i++)
					{
						outer_inv_range(psIntSysPAddr[i].uiAddr, psIntSysPAddr[i].uiAddr + HOST_PAGESIZE() -1);
					}

					OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
						uPageCount * sizeof(IMG_SYS_PHYADDR),
						psIntSysPAddr, IMG_NULL);

					OSReleasePhysPageAddr(hOSWrapMem);

				}

#endif /* CONFIG_OUTER_CACHE */
			}

		}
	}

#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
	if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
	{
		PVR_LOG(("User requested OS reset"));
		OSPanic();
	}
#endif 

	return PVRSRV_OK;
}