static IMG_INT
PVRSRVBridgeEnumerateDevices(IMG_UINT32 ui32BridgeID,
					 PVRSRV_BRIDGE_IN_ENUMERATEDEVICES *psEnumerateDevicesIN,
					 PVRSRV_BRIDGE_OUT_ENUMERATEDEVICES *psEnumerateDevicesOUT,
					 CONNECTION_DATA *psConnection)
{
	PVRSRV_DEVICE_IDENTIFIER *psDeviceIdentifierInt = IMG_NULL;

	PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SRVCORE_ENUMERATEDEVICES);

	PVR_UNREFERENCED_PARAMETER(psConnection);
	PVR_UNREFERENCED_PARAMETER(psEnumerateDevicesIN);

	psEnumerateDevicesOUT->psDeviceIdentifier = psEnumerateDevicesIN->psDeviceIdentifier;


	
	{
		psDeviceIdentifierInt = OSAllocMem(PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_IDENTIFIER));
		if (!psDeviceIdentifierInt)
		{
			psEnumerateDevicesOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
	
			goto EnumerateDevices_exit;
		}
	}


	psEnumerateDevicesOUT->eError =
		PVRSRVEnumerateDevicesKM(
					&psEnumerateDevicesOUT->ui32NumDevices,
					psDeviceIdentifierInt);


	if ( !OSAccessOK(PVR_VERIFY_WRITE, (IMG_VOID*) psEnumerateDevicesOUT->psDeviceIdentifier, (PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_IDENTIFIER))) 
		|| (OSCopyToUser(NULL, psEnumerateDevicesOUT->psDeviceIdentifier, psDeviceIdentifierInt,
		(PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_IDENTIFIER))) != PVRSRV_OK) )
	{
		psEnumerateDevicesOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;

		goto EnumerateDevices_exit;
	}


EnumerateDevices_exit:
	if (psDeviceIdentifierInt)
		OSFreeMem(psDeviceIdentifierInt);

	return 0;
}
/*
 * Can't call from module initialization, since PVR services are started when
 * the Xorg server starts.
 */
int msvdx_pvr_init(void)
{
	drm_emgd_priv_t        *priv;
	igd_context_t           *context;
	platform_context_plb_t  *platform;
	struct msvdx_pvr_info   *pvr;
	PVRSRV_DEVICE_IDENTIFIER dev_id_list[PVRSRV_MAX_DEVICES];
	IMG_UINT32   pid;
	IMG_UINT32   num_devices;
	IMG_UINT32   i;
	IMG_BOOL     mem_created;
	PVRSRV_ERROR err;
	int ret;

	priv     = gpDrmDevice->dev_private;
	context  = priv->context;
	platform = (platform_context_plb_t *)context->platform_context;

	if (platform->msvdx_pvr) {
		printk(KERN_INFO "[EMGD] MSVDX: PVR services already "
			"initialized\n");
		return 0;
	}

    pvr = kzalloc(sizeof(*pvr), GFP_KERNEL);
	if (!pvr)
		return -ENOMEM;

    /*
	 * Create a dummy kernel thread so that a persistent PVR per process
	 * data could be created.
	 */
	pvr->kthread = kthread_run(msvdx_pvr_kthread, NULL, "msvdx-pvr");
	if (IS_ERR(pvr->kthread)) {
		ret = PTR_ERR(pvr->kthread);
		printk(KERN_ERR "[EMGD] MSVDX: failed to create MSVDX PVR "
			"kernel tread, error=%i\n", ret);
		pvr->kthread = NULL;
		goto out_free;
	}

	ret = -ENODEV;
	pid = OSGetCurrentProcessIDKM(); //(IMG_UINT32)pvr->kthread->pid;
    err = PVRSRVPerProcessDataConnect(pid);
	if (err != PVRSRV_OK) {
		printk(KERN_ERR "[EMGD] MSVDX: connect to PVR failed (pid=%u), "
			"error=%i\n", (unsigned int)err, err);
		goto out_stop_kthread;
	}
	pvr->per_proc = PVRSRVPerProcessData(pid);
	if (pvr->per_proc == IMG_NULL) {
		printk(KERN_ERR "[EMGD] MSVDX: Couldn't find per process "
			"data for pid=%u\n", (unsigned int)pid);
		goto out_stop_kthread;
	}

	err = PVRSRVEnumerateDevicesKM(&num_devices, dev_id_list);
	if (err != PVRSRV_OK) {
		printk(KERN_ERR "[EMGD] MSVDX: PVRSRVEnumerateDevice() failed, "
			"error=%u\n", (unsigned int)err);
		goto out_stop_kthread;
	}

	for (i = 0 ; i < num_devices ; i++) {
		PVRSRV_DEVICE_IDENTIFIER *id;
		IMG_HANDLE cookie;

		cookie = IMG_NULL;
		id = &dev_id_list[i];

		if (id->eDeviceType != PVRSRV_DEVICE_TYPE_EXT) {
			err = PVRSRVAcquireDeviceDataKM(id->ui32DeviceIndex,
				PVRSRV_DEVICE_TYPE_UNKNOWN, &cookie);
			if (err != PVRSRV_OK) {
				printk(KERN_ERR "[EMGD] MSVDX: "
					"PVRSRVAcquireDeviceDataKM() failed, "
					"error=%u\n", err);
				break;
			}
			if (PVRSRV_DEVICE_TYPE_SGX == id->eDeviceType) {
				pvr->sgx_cookie = cookie;
				break;
			}
		}
	}

	if (pvr->sgx_cookie == IMG_NULL)
		goto out_stop_kthread;

	err = PVRSRVCreateDeviceMemContextKM(pvr->sgx_cookie, pvr->per_proc,
			&pvr->dev_mem_context, &pvr->heap_count,
			pvr->heap_info, &mem_created, pvr->heap_shared);
	if (err != PVRSRV_OK) {
		printk(KERN_ERR "[EMGD] MSVDX: PVRSRVCreateDeviceMemContextKM()"
			" failed, error=%u\n", (unsigned int)err);
		goto out_stop_kthread;
	}

	for (i = 0; i < pvr->heap_count; i++) {
		if (HEAP_IDX(pvr->heap_info[i].ui32HeapID) ==
			SGX_VIDEO_HEAP_ID) {
			pvr->mapping_heap_index = i;
			break;
		}
	}

	platform->msvdx_pvr = pvr;
	pvr->pid = pid;


	return 0;

out_stop_kthread:
	kthread_stop(pvr->kthread);
out_free:
	kfree(pvr);
	return ret;
}
int alloc_ramdec_region(unsigned long *base_addr0, unsigned long *base_addr1,
				unsigned long size0, unsigned long size1)
{
	unsigned long pid = OSGetCurrentProcessIDKM();
    unsigned long num = 10;
	unsigned long heap_count = 0;
    void *sgx_cookie = NULL;
    unsigned long heapIndex = 0, generalHeapIndex = 0;
	PVRSRV_ERROR err;
	PVRSRV_KERNEL_MEM_INFO *rendec0MemInfo;
	PVRSRV_KERNEL_MEM_INFO *rendec1MemInfo;
	int i;

	printk(KERN_INFO "Calling PVRSRVPerProcessData()\n");
	if (PVRSRVPerProcessDataConnect(200) != PVRSRV_OK) {
		printk(KERN_ERR "msvdx_init: connect to PVR failed\n");
	}

	psPerProc = PVRSRVPerProcessData(200);
	if (psPerProc == IMG_NULL)
	{
		printk(KERN_ERR "msvdx_init:  Couldn't find per process data for pid=%lx\n", pid);
	}

	printk(KERN_INFO "  TEST: pp_data = 0x%p\n", psPerProc);


	PVRSRVEnumerateDevicesKM(&num, dev_id_list);
	printk(KERN_INFO "Calling PVRSRVEnumerateDevicesKM()\n");
	if (PVRSRVEnumerateDevicesKM(&num, dev_id_list) != PVRSRV_OK) {
		printk(KERN_ERR "msvdx_init: PVRSRVEnumerateDevice failed\n");
	} else {
		printk(KERN_INFO "  PVRSRVEnumerateDevicesKM() found %ld devices\n", num);
		for (i = 0 ; i < num ; i++) {
			PVRSRV_DEVICE_IDENTIFIER *id = dev_id_list + i;
			unsigned long cookie = 0;
			printk(KERN_INFO "    Device %d has type %d, class %d & index %ld\n", i,
					id->eDeviceType, id->eDeviceClass, id->ui32DeviceIndex);
			if (PVRSRV_DEVICE_TYPE_EXT != id->eDeviceType) {
				// Call PVRSRVAcquireDeviceDataKM():
				printk(KERN_INFO "Calling PVRSRVAcquireDeviceDataKM()\n");
				err = PVRSRVAcquireDeviceDataKM(id->ui32DeviceIndex,
						PVRSRV_DEVICE_TYPE_UNKNOWN, (void *) &cookie);
				if (err != PVRSRV_OK) {
					printk(KERN_ERR "[EMGD] PVRSRVAcquireDeviceDataKM() "
							"returned %d\n", err);
					break;
				}
				if (PVRSRV_DEVICE_TYPE_SGX == id->eDeviceType) {
					printk(KERN_INFO "  Found cookie = 0x%lx\n", cookie);
					// Save this away for later:
					sgx_cookie = (void *) cookie;
				}
			}
		}
	}

	// Enumerate the display class devices to be able to find the 3DD:
	printk(KERN_INFO "Calling PVRSRVEnumerateDCKM()\n");
	err = PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS_DISPLAY,
			&num, dev_ids);
	if (err != PVRSRV_OK) {
		printk(KERN_ERR "[EMGD] PVRSRVEnumerateDCKM() returned %d\n", err);
	} else {
		// Find the 3DD:
		printk(KERN_INFO "  PVRSRVEnumerateDCKM() found %ld devices\n", num);
		for (i = 0 ; i < num ; i++) {
			printk(KERN_INFO "    device %d has ID %ld\n", i, dev_ids[i]);
		}
		if (0 == dev_ids[0]) {
			printk(KERN_ERR "[EMGD] Did not find 3rd-party display driver ID\n");
		}
	}

	// Call PVRSRVCreateDeviceMemContextKM():

	printk(KERN_INFO "Calling PVRSRVCreateDeviceMemContextKM()\n");
	err = PVRSRVCreateDeviceMemContextKM(sgx_cookie, psPerProc,
			&dev_mem_context, &heap_count, heap_info, &mem_created, &dummy);
	if (err != PVRSRV_OK) {
		printk(KERN_ERR "[EMGD] PVRSRVCreateDeviceMemContextKM() "
				"returned %d\n", err);
	}


	for (heapIndex=0; heapIndex<heap_count; heapIndex++) {
		if (HEAP_IDX(heap_info[heapIndex].ui32HeapID) == SGX_GENERAL_HEAP_ID)
		{
			generalHeapIndex = heapIndex;
			break;
		}
	}

	if (PVRSRVAllocDeviceMemKM(sgx_cookie, psPerProc, heap_info[generalHeapIndex].hDevMemHeap,
                        PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
                        size0, 0, &rendec0MemInfo, "") != PVRSRV_OK) {
		printk(KERN_ERR "msvdx: PVRSRVAllocDeviceMemKM failed\n");
	}

	if (PVRSRVAllocDeviceMemKM(sgx_cookie, psPerProc, heap_info[generalHeapIndex].hDevMemHeap,
                        PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
                        size1, 0, &rendec1MemInfo, "") != PVRSRV_OK) {
		printk(KERN_ERR "msvdx: PVRSRVAllocDeviceMemKM failed\n");
	}

	*base_addr0 = rendec0MemInfo->sDevVAddr.uiAddr;
	*base_addr1 = rendec1MemInfo->sDevVAddr.uiAddr;

	//printk(KERN_INFO "pvr size0=%lx, size1=%lx, heap=%ld\n", size0, size1, generalHeapIndex);

//	return PVRSRV_OK;
	return 0;

}
static PVRSRV_DEVICE_NODE* RGXGetDeviceNode(void)
{
	if(pDevNode == NULL)
	{
		PVRSRV_DEVICE_TYPE *peDeviceTypeInt = NULL;
		PVRSRV_DEVICE_CLASS *peDeviceClassInt = NULL;
		IMG_UINT32 *pui32DeviceIndexInt = NULL;
		IMG_HANDLE hDevCookie = NULL;
		IMG_UINT32 numDevices = 0;
		IMG_UINT32 i = 0;
		IMG_UINT32 rgxIndex = IMG_UINT32_MAX;
		IMG_UINT32 error = 0;

		peDeviceTypeInt = kzalloc(PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_TYPE), GFP_KERNEL);
		if (!peDeviceTypeInt)
		{
			error = PVRSRV_ERROR_OUT_OF_MEMORY;
			goto EnumerateDevices_exit;
		}

		peDeviceClassInt = kzalloc(PVRSRV_MAX_DEVICES * sizeof(PVRSRV_DEVICE_CLASS), GFP_KERNEL);
		if (!peDeviceClassInt)
		{
			error = PVRSRV_ERROR_OUT_OF_MEMORY;
			goto EnumerateDevices_exit;
		}

		pui32DeviceIndexInt = kzalloc(PVRSRV_MAX_DEVICES * sizeof(IMG_UINT32), GFP_KERNEL);
		if (!pui32DeviceIndexInt)
		{
			error = PVRSRV_ERROR_OUT_OF_MEMORY;
			goto EnumerateDevices_exit;
		}

		/* Enumerate active devices */
		error = PVRSRVEnumerateDevicesKM(
						&numDevices,
						peDeviceTypeInt,
						peDeviceClassInt,
						pui32DeviceIndexInt);
		if (error == 0){
			for(i =0; i < numDevices; i++){
				if (peDeviceTypeInt[i] == PVRSRV_DEVICE_TYPE_RGX){
					rgxIndex = pui32DeviceIndexInt[i];
				}
 			}

			if(rgxIndex != IMG_UINT32_MAX){
				/* Now we have to acquire the node to work with, RGX device required*/
				error = PVRSRVAcquireDeviceDataKM (rgxIndex, PVRSRV_DEVICE_TYPE_RGX, &hDevCookie);

				if (error == 0)
					pDevNode = (PVRSRV_DEVICE_NODE*)hDevCookie;
			}
		}

EnumerateDevices_exit:
		if (peDeviceTypeInt)
			kfree(peDeviceTypeInt);
		if (peDeviceClassInt)
			kfree(peDeviceClassInt);
		if (pui32DeviceIndexInt)
			kfree(pui32DeviceIndexInt);
	}

	return pDevNode;
}