/*!
******************************************************************************

 @Function				SYSDEVKM_OpenDevice

******************************************************************************/
IMG_RESULT SYSDEVKM_OpenDevice(
	IMG_CHAR *				pszDeviceName,
	IMG_HANDLE *			phSysDevHandle
)
{
	IMG_UINT32			ui32Result;
	SYSDEVKM_sDevice *	psDevice;

	/* Allocate a device structure...*/
	psDevice = IMG_MALLOC(sizeof(*psDevice));
	IMG_ASSERT(psDevice != IMG_NULL);
	if (psDevice == IMG_NULL)
	{
		return IMG_ERROR_OUT_OF_MEMORY;
	}
	IMG_MEMSET(psDevice, 0, sizeof(*psDevice));

	/* Get the device id...*/
	ui32Result = SYSDEVU_GetDeviceId(pszDeviceName, &psDevice->ui32DeviceId);
	IMG_ASSERT(ui32Result == IMG_SUCCESS);
	if (ui32Result != IMG_SUCCESS)
	{
		return ui32Result;
	}

	/* Return the device handle...*/
	*phSysDevHandle = psDevice;

	/* Update count...*/
	SYSOSKM_DisableInt();
	gsActiveOpenCnt++;
	SYSOSKM_EnableInt();

	return IMG_SUCCESS;
}
Example #2
0
/*!
******************************************************************************

 @Function                POOL_Deinitialise

******************************************************************************/
IMG_VOID POOL_Deinitialise(IMG_VOID)
{
    POOL_sResPool *  psResPool;
    IMG_ASSERT(0);

    /* Disable interrupts.  */
    SYSOSKM_DisableInt();

    /* If not initialised...*/
    if (!gInitialised)
    {
        /* Destroy any active pools...*/
        psResPool = (POOL_sResPool *)LST_first(&gsPoolList);
        while (psResPool != IMG_NULL)
        {
            POOL_PoolDestroy(psResPool);
            psResPool = (POOL_sResPool *)LST_first(&gsPoolList);
        }

        /* Set initialised flag...*/
        gInitialised = IMG_FALSE;
    }

    /* Enable interrupts.  */
    SYSOSKM_EnableInt();
}
Example #3
0
/*!
******************************************************************************

 @Function                POOL_PoolCreate

******************************************************************************/
IMG_RESULT POOL_PoolCreate(
    IMG_HANDLE *  phPoolHandle
)
{
    POOL_sResPool *  psResPool;
    IMG_UINT32       ui32Result;

    IMG_ASSERT(gInitialised);

    /* Allocate a pool structure...*/
    psResPool = IMG_MALLOC(sizeof(*psResPool));
    IMG_ASSERT(psResPool != IMG_NULL);
    if (psResPool == IMG_NULL)
    {
        return IMG_ERROR_OUT_OF_MEMORY;
    }
    IMG_MEMSET(psResPool, 0, sizeof(*psResPool));

    /* Initialise the pool info...*/
    LST_init(&psResPool->sFreeResList);
    LST_init(&psResPool->sActResList);

    /* Create mutex...*/
    ui32Result = SYSOSKM_CreateMutex(&psResPool->hMutexHandle);
    IMG_ASSERT(ui32Result == IMG_SUCCESS);
    if (ui32Result != IMG_SUCCESS)
    {
        goto error_create_mutex;
    }

    /* Create context for the Id generator...*/
    ui32Result = IDGEN_CreateContext(POOL_IDGEN_MAX_ID, POOL_IDGEN_BLOCK_SIZE,IMG_FALSE, &psResPool->hIdGenHandle);
    IMG_ASSERT(ui32Result == IMG_SUCCESS);
    if (ui32Result != IMG_SUCCESS)
    {
        goto error_create_context;
    }

    /* Disable interrupts.  */
    SYSOSKM_DisableInt();

    /* Add to list of pools...*/
    LST_add(&gsPoolList, psResPool);

    /* Enable interrupts.  */
    SYSOSKM_EnableInt();

    /* Return handle to pool...*/
    *phPoolHandle = psResPool;

    return IMG_SUCCESS;

    /* Error handling. */
error_create_context:
    SYSOSKM_DestroyMutex(psResPool->hMutexHandle);
error_create_mutex:
    IMG_FREE(psResPool);

    return ui32Result;
}
Example #4
0
/*!
******************************************************************************

 @Function				RMAN_Deinitialise

******************************************************************************/
IMG_VOID RMAN_Deinitialise(IMG_VOID)
{
    IMG_UINT32				i;

    /* Make sure no other cpu is using the shared resources.  */
    SYSOSKM_DisableInt();

    /* If initialised...*/
    if (gInitialised)
    {
        /* Destroy the golbal resource bucket...*/
        RMAN_DestroyBucket(gpsGlobalResBucket);

        /* Destroy the shared resource bucket...*/
        RMAN_DestroyBucket(gpsSharedResBucket);

        /* Make sure we destroy the mutex after destroying the bucket. */
        SYSOSKM_DestroyMutex(globalMutext);

        /* Destroy mutex...*/
        SYSOSKM_DestroyMutex(ghSharedResMutexHandle);

        /* Check all buckets destroyed...*/
        for (i=0; i<RMAN_CRESID_MAX_BUCKET_INDEX; i++)
        {
            IMG_ASSERT(gapsBucket[i] == IMG_NULL);
        }

        /* Reset initialised flag...*/
        gInitialised = IMG_FALSE;
    }

    SYSOSKM_EnableInt();
}
Example #5
0
/*!
******************************************************************************

 @Function				RMAN_CreateBucket

******************************************************************************/
IMG_RESULT RMAN_CreateBucket(
    IMG_HANDLE *		phResBHandle
)
{
    RMAN_sBucket *			psBucket;
    IMG_UINT32				i;
    IMG_RESULT              i32Result;

    IMG_ASSERT(gInitialised);

    /* Allocate a bucket structure...*/
    psBucket = IMG_MALLOC(sizeof(*psBucket));
    IMG_ASSERT(psBucket != IMG_NULL);
    if (psBucket == IMG_NULL)
    {
        return IMG_ERROR_OUT_OF_MEMORY;
    }
    IMG_MEMSET(psBucket, 0, sizeof(*psBucket));

    /* Intialise the resource list...*/
    DQ_init(&psBucket->sResList);

    /* The start allocating resource ids at the first...*/
    i32Result = IDGEN_CreateContext(RMAN_MAX_ID, RMAN_ID_BLOCKSIZE, IMG_FALSE, &psBucket->hIdGenerator);
    if(i32Result != IMG_SUCCESS)
    {
        IMG_FREE(psBucket);
        IMG_ASSERT(!"failed to create IDGEN context");
        return i32Result;
    }

    /* Locate free bucket index within the table...*/
    SYSOSKM_DisableInt();
    for (i=0; i<RMAN_CRESID_MAX_BUCKET_INDEX; i++)
    {
        if (gapsBucket[i] == IMG_NULL)
        {
            break;
        }
    }
    if (i >= RMAN_CRESID_MAX_BUCKET_INDEX) {
        SYSOSKM_EnableInt();
        IDGEN_DestroyContext(psBucket->hIdGenerator);
        IMG_FREE(psBucket);
        IMG_ASSERT(!"No free buckets left");
        return IMG_ERROR_GENERIC_FAILURE;
    }

    /* Allocate bucket index...*/
    psBucket->ui32BucketIndex = i;
    gapsBucket[i] = psBucket;

    SYSOSKM_EnableInt();

    /* Return the bucket handle...*/
    *phResBHandle = psBucket;

    return IMG_SUCCESS;
}
/*!
******************************************************************************

 @Function                FreePages

******************************************************************************/
static IMG_VOID FreePages(
    SYSMEM_Heap *  heap,
    IMG_HANDLE     hPagesHandle
)
{
    struct priv_params *  prv = (struct priv_params *)heap->priv;
    SYSMEMU_sPages *      psPages = hPagesHandle;
    IMG_UINT32            ui32NoPages;
    IMG_UINT32            ui32PageIndex;
    IMG_UINT32            i;
    IMG_UINT32            physAddrArrSize;

    /* Calculate required no. of pages...*/
    ui32NoPages = (psPages->ui32Size + (HOST_MMU_PAGE_SIZE-1)) / HOST_MMU_PAGE_SIZE;

    /* If mapping then free on the copy of the page structure. */
    if (psPages->bImported)
    {
        if(IMG_NULL != psPages->ppaPhysAddr)
        {
            IMG_BIGORSMALL_FREE(ui32NoPages * sizeof(psPages->ppaPhysAddr[0]), psPages->ppaPhysAddr);
            psPages->ppaPhysAddr = IMG_NULL;
        }

        return;
    }

    if (psPages->bDuplicated)
    	return;

    /* Removed this from the list of mappable regions...*/
    SYSBRGU_DestroyMappableRegion(psPages->hRegHandle);

    /* Free memory...*/
    SYSOSKM_DisableInt();
    IMG_ASSERT((IMG_UINTPTR)psPages->pvCpuKmAddr >= prv->vstart);
    IMG_ASSERT((IMG_UINTPTR)psPages->pvCpuKmAddr < (prv->vstart + prv->size));

    /* Calculate page table size and index...*/
    physAddrArrSize = sizeof(psPages->ppaPhysAddr[0]) * ui32NoPages;
    ui32PageIndex = (IMG_UINT32) ((((IMG_UINTPTR)psPages->pvCpuKmAddr) - prv->vstart) / HOST_MMU_PAGE_SIZE);

    /* Mark pages as unallocated...*/
    for (i=0; i<ui32NoPages; i++)
    {
        IMG_ASSERT(prv->alloc_pool[ui32PageIndex+i]);
        prv->alloc_pool[ui32PageIndex+i] = IMG_FALSE;
    }
    prv->cur_index -= ui32NoPages;
    SYSOSKM_EnableInt();
    IMG_BIGORSMALL_FREE(physAddrArrSize, psPages->ppaPhysAddr);

}
Example #7
0
static irqreturn_t handle_interrupt(int irq, void *dev_id)
{
	bool handled;
	if ( (gpsInfo != IMG_NULL) && (gpsInfo->pfnDevKmLisr != IMG_NULL) )
	{
		SYSOSKM_DisableInt();
		handled = gpsInfo->pfnDevKmLisr(gpsInfo->pvParam);
		SYSOSKM_EnableInt();

		if (handled)
		{
			/* Signal this...*/
			return IRQ_HANDLED;
		}
	}
	return IRQ_NONE;
}
/*!
******************************************************************************

 @Function				SYSDEVKM_CloseDevice

******************************************************************************/
IMG_VOID SYSDEVKM_CloseDevice(
	IMG_HANDLE			hSysDevHandle
)
{
	SYSDEVKM_sDevice *	psDevice = (SYSDEVKM_sDevice *)hSysDevHandle;
	
	IMG_ASSERT(hSysDevHandle != IMG_NULL);
	if (hSysDevHandle == IMG_NULL)
	{
		return;
	}

	IMG_FREE(psDevice);

	/* Update count...*/
	SYSOSKM_DisableInt();
	gsActiveOpenCnt--;
	SYSOSKM_EnableInt();
}
static irqreturn_t handle_interrupt(int irq, void *dev_id)
{
    bool handled;
    if ( (gpsInfo != IMG_NULL) && (gpsInfo->pfnDevKmLisr != IMG_NULL) )
    {
        SYSOSKM_DisableInt();
        handled = gpsInfo->pfnDevKmLisr(gpsInfo->pvParam);
        SYSOSKM_EnableInt();

        if (handled)
        {
            /* Clear the interrupt with QEMU */
            *((char *)reg_base_addr + 0x10000) = 1;
            /* Signal this...*/
            return IRQ_HANDLED;
        }
    }
    return IRQ_NONE;
}
/*!
******************************************************************************

@Function IsrCb

******************************************************************************/
static irqreturn_t IsrCb(int irq, void *dev_id)
{
    IMG_BOOL  bHandled;

    if ( (psSysDev != IMG_NULL) && (psSysDev->pfnDevKmLisr != IMG_NULL) )
    {
        //Call it
        SYSOSKM_DisableInt();
        bHandled = psSysDev->pfnDevKmLisr(psSysDev->pvParam);
        SYSOSKM_EnableInt();

        //If the LISR handled the interrupt
        if (bHandled)
        {
            //Signal this
            return IRQ_HANDLED;
        }
    }

    return IRQ_NONE;
}
Example #11
0
/*!
******************************************************************************

 @Function                POOL_Initialise

******************************************************************************/
IMG_RESULT POOL_Initialise(IMG_VOID)
{
    /* Disable interrupts.  */
    SYSOSKM_DisableInt();

    /* If not initialised...*/
    if (!gInitialised)
    {
        /* Initialise the list of pools. */
        LST_init(&gsPoolList);

        /* Set initialised flag...*/
        gInitialised = IMG_TRUE;
    }

    /* Enable interrupts.  */
    SYSOSKM_EnableInt();

    /* Return success...*/
    return IMG_SUCCESS;
}
/*!
******************************************************************************

 @Function				SYSDEVU_GetDeviceId

******************************************************************************/
IMG_RESULT SYSDEVU_GetDeviceId(
	IMG_CHAR *				pszDeviceName,
	IMG_UINT32 *			pui32DeviceId
)
{
	SYSDEVU_sInfo *dev;

	if(!gSysDevInitialised)
    {
		IMG_ASSERT(gSysDevInitialised);
        return IMG_ERROR_NOT_INITIALISED;
    }

	dev = findDeviceByName(pszDeviceName);
	if (!dev)
	{
		IMG_ASSERT(dev);
		return IMG_ERROR_DEVICE_NOT_FOUND;
	}

	/* Return device Id...*/
	*pui32DeviceId = dev->ui32DeviceId;

	/* If device not located...*/
	SYSOSKM_DisableInt();
	if (!dev->bDevLocated)
	{
		/* Device now located...*/
		dev->bDevLocated = IMG_TRUE;
		SYSOSKM_EnableInt();
	}
	else
	{
		SYSOSKM_EnableInt();
	}

	/* Return success...*/
	return IMG_SUCCESS;
}
Example #13
0
/*!
******************************************************************************

 @Function				RMAN_DestroyBucket

******************************************************************************/
IMG_VOID RMAN_DestroyBucket(
    IMG_HANDLE				hResBHandle
)
{
    RMAN_sBucket *			psBucket = (RMAN_sBucket *)hResBHandle;

    IMG_ASSERT(gInitialised);

    IMG_ASSERT(psBucket != IMG_NULL);
    if (psBucket== IMG_NULL)
    {
        return;
    }

    IMG_ASSERT(psBucket->ui32BucketIndex < RMAN_CRESID_MAX_BUCKET_INDEX);
    IMG_ASSERT(gapsBucket[psBucket->ui32BucketIndex] != IMG_NULL);

    /* Free all resources from the bucket...*/
    RMAN_FreeResources(hResBHandle, RMAN_TYPE_P1);
    RMAN_FreeResources(hResBHandle, RMAN_TYPE_P2);
    RMAN_FreeResources(hResBHandle, RMAN_TYPE_P3);
    RMAN_FreeResources(hResBHandle, RMAN_ALL_TYPES);

    /* free sticky resources last: other resources are dependent on them */
    RMAN_FreeResources(hResBHandle, RMAN_STICKY);
    /* Use proper locking around global buckets.  */
    SYSOSKM_DisableInt();

    /* Free from array of bucket pointers...*/
    gapsBucket[psBucket->ui32BucketIndex] = IMG_NULL;

    SYSOSKM_EnableInt();

    /* Free the bucket itself...*/
    IDGEN_DestroyContext(psBucket->hIdGenerator);
    IMG_FREE(psBucket);
}
/*!
 ******************************************************************************

 @Function				DMANKM_RegisterDevice

 ******************************************************************************/
IMG_RESULT DMANKM_RegisterDevice(IMG_CHAR * pszDeviceName,
		DMANKM_pfnDevRegister pfnDevRegister) 
{
	DMANKM_sDevContext * psDevContext;
	IMG_UINT32 ui32Result;

	/* If the device context list is not initialised...*/
	if (!gbDevListInitialised) {
		/* Initialise the device context list...*/
		LST_init(&gsDevList);

		gbDevListInitialised = IMG_TRUE;
	}

	/* Locate the device - ensure it's not registered twice...*/
	ui32Result = DMANKM_LocateDevice(pszDeviceName,
			(IMG_HANDLE *) &psDevContext);
	if (ui32Result != IMG_ERROR_DEVICE_NOT_FOUND) {
        IMG_ASSERT(ui32Result == IMG_ERROR_DEVICE_NOT_FOUND);
		return IMG_ERROR_GENERIC_FAILURE;
	}

	/* Allocate a device context structure...*/
	psDevContext = IMG_MALLOC(sizeof(*psDevContext));
	if (psDevContext == IMG_NULL ) 
    {
        IMG_ASSERT(psDevContext != IMG_NULL);
		return IMG_ERROR_OUT_OF_MEMORY;
	}

	IMG_MEMSET(psDevContext, 0, sizeof(*psDevContext));

	/* Setup the device context...*/
	psDevContext->ui32DeviceId = gui32NextDeviceID;
	gui32NextDeviceID++;
	psDevContext->pszDeviceName = IMG_STRDUP(pszDeviceName);
	if (psDevContext->pszDeviceName == IMG_NULL ) 
    {
        IMG_ASSERT(psDevContext->pszDeviceName != IMG_NULL);
		ui32Result = IMG_ERROR_OUT_OF_MEMORY;
		goto error_dev_name;
	}
	psDevContext->pfnDevRegister = pfnDevRegister;
	psDevContext->ui8ApmPpmFlags = 0;
	ui32Result = SYSOSKM_CreateMutex(&psDevContext->hMutexHandle);
	IMG_ASSERT(ui32Result == IMG_SUCCESS);
	if (ui32Result != IMG_SUCCESS) {
		goto error_create_mutex;
	}
	LST_init(&psDevContext->sConnList);

	/* Disable interrupts...*/
	SYSOSKM_DisableInt();

	/* Add device to list...*/
	LST_add(&gsDevList, psDevContext);

	/* Re-enable interrupts...*/
	SYSOSKM_EnableInt();

	/* If initialised...*/
	if (gDmanKmInitialised) {
		/* Call device registration function...*/
		ui32Result = psDevContext->pfnDevRegister(&psDevContext->sDevRegister);
		IMG_ASSERT(ui32Result == IMG_SUCCESS);
		if (ui32Result != IMG_SUCCESS) {
			goto error_dev_register;
		}

		/* Set default if required...*/
		if (psDevContext->sDevRegister.ui32ConnFlags == 0) {
			psDevContext->sDevRegister.ui32ConnFlags = DMAN_CFLAG_EXCLUSIVE;
		}
	}

	/* Return success...*/
	return IMG_SUCCESS;

	/* Error handling. */
	error_dev_register: SYSOSKM_DisableInt();
	LST_remove(&gsDevList, psDevContext);
	SYSOSKM_EnableInt();
	SYSOSKM_DestroyMutex(psDevContext->hMutexHandle);
	error_create_mutex:
	IMG_FREE(psDevContext->pszDeviceName);
	error_dev_name:
	IMG_FREE(psDevContext);

	return ui32Result;
}
Example #15
0
/*!
******************************************************************************

 @Function                POOL_PoolDestroy

******************************************************************************/
IMG_RESULT POOL_PoolDestroy(
    IMG_HANDLE  hPoolHandle
)
{
    POOL_sResPool *   psResPool = hPoolHandle;
    POOL_sResource *  psResource;
    POOL_sResource *  psCloneResource;
    IMG_UINT32        ui32Result;

    IMG_ASSERT(gInitialised);
    IMG_ASSERT(psResPool != IMG_NULL);

    if (!gInitialised ||
        psResPool == IMG_NULL)
    {
        ui32Result = IMG_ERROR_INVALID_PARAMETERS;
        goto error_nolock;
    }

    /* Lock the pool...*/
    SYSOSKM_LockMutex(psResPool->hMutexHandle);

    /* Disable interrupts.  */
    SYSOSKM_DisableInt();

    /* Remove the pool from the active list...*/
    LST_remove(&gsPoolList, psResPool);

    /* Enable interrupts.  */
    SYSOSKM_EnableInt();

    /* Destroy any resources in the free list...*/
    psResource = (POOL_sResource *)LST_removeHead(&psResPool->sFreeResList);
    while (psResource != IMG_NULL)
    {
        psResource->pfnDestructor(psResource->pvParam);
        IMG_FREE(psResource);

        psResource = (POOL_sResource *)LST_removeHead(&psResPool->sFreeResList);
    }

    /* Destroy any resources in the active list...*/
    psResource = (POOL_sResource *)LST_removeHead(&psResPool->sActResList);
    while (psResource != IMG_NULL)
    {
        psCloneResource = (POOL_sResource *)LST_removeHead(&psResource->sCloneResList);
        while (psCloneResource != IMG_NULL)
        {
            /* If we created a copy of the resources pvParam then free it...*/
            if (psCloneResource->pvParam != IMG_NULL)
            {
                IMG_FREE(psCloneResource->pvParam );
            }
            IMG_FREE(psCloneResource);
            psCloneResource = (POOL_sResource *)LST_removeHead(&psResource->sCloneResList);
        }

        /* Call the resource destructor...*/
        psResource->pfnDestructor(psResource->pvParam);
        IMG_FREE(psResource);

        psResource = (POOL_sResource *)LST_removeHead(&psResPool->sActResList);
    }

    /* Destroy the context for the Id generator...*/
    if (psResPool->hIdGenHandle != IMG_NULL)
    {
        ui32Result = IDGEN_DestroyContext(psResPool->hIdGenHandle);
        IMG_ASSERT(ui32Result == IMG_SUCCESS);
    }

    /* Unlock the pool...*/
    SYSOSKM_UnlockMutex(psResPool->hMutexHandle);

    /* Destroy mutex...*/
    SYSOSKM_DestroyMutex(psResPool->hMutexHandle);

    /* Free the pool structure */
    IMG_FREE(psResPool);
    
	return IMG_SUCCESS;

error_nolock:
    return ui32Result;
}
Example #16
0
/*!
******************************************************************************

 @Function				RMAN_RegisterResource

******************************************************************************/
IMG_RESULT RMAN_RegisterResource(
    IMG_HANDLE				hResBHandle,
    IMG_UINT32				ui32TypeId,
    RMAN_pfnFree			pfnFree,
    IMG_VOID *              pvParam,
    IMG_HANDLE *			phResHandle,
    IMG_UINT32 *			pui32ResId
)
{
    RMAN_sBucket *				psBucket = (RMAN_sBucket *) hResBHandle;
    RMAN_sResource *			psResource;
    IMG_RESULT                  i32Result;

    IMG_ASSERT(gInitialised);
    IMG_ASSERT(ui32TypeId		!= RMAN_ALL_TYPES);

    IMG_ASSERT(hResBHandle != IMG_NULL);
    if (hResBHandle == IMG_NULL)
    {
        return IMG_ERROR_GENERIC_FAILURE;
    }

    /* Allocate a resource structure...*/
    psResource = IMG_MALLOC(sizeof(*psResource));
    IMG_ASSERT(psResource != IMG_NULL);
    if (psResource == IMG_NULL)
    {
        return IMG_ERROR_OUT_OF_MEMORY;
    }
    IMG_MEMSET(psResource, 0, sizeof(*psResource));

    /* Fill in the resource structure...*/
    psResource->psBucket		= psBucket;
    psResource->ui32TypeId		= ui32TypeId;
    psResource->pfnFree			= pfnFree;
    psResource->pvParam         = pvParam;

    /* Allocate resource Id...*/
    SYSOSKM_LockMutex(globalMutext);
    i32Result = IDGEN_AllocId(psBucket->hIdGenerator, psResource, &psResource->ui32ResId);
    SYSOSKM_UnlockMutex(globalMutext);
    if(i32Result != IMG_SUCCESS)
    {
        IMG_ASSERT(!"failed to allocate RMAN id");
        return i32Result;
    }
    IMG_ASSERT(psResource->ui32ResId <= RMAN_CRESID_MAX_RES_ID);

    // add this resource to the bucket
    SYSOSKM_DisableInt();
    DQ_addTail(&psBucket->sResList, psResource);

    /* Update count of resources...*/
    psBucket->ui32ResCnt++;
    SYSOSKM_EnableInt();

    /* If resource handle required...*/
    if (phResHandle != IMG_NULL)
    {
        *phResHandle = psResource;
    }

    /* If resource id required...*/
    if (pui32ResId != IMG_NULL)
    {
        *pui32ResId = RMAN_GetResourceId(psResource);
    }

    /* Return success...*/
    return IMG_SUCCESS;
}
static IMG_RESULT AllocPages(
    SYSMEM_Heap *     heap,
    IMG_UINT32        ui32Size,
    SYSMEMU_sPages *  psPages,
    SYS_eMemAttrib    eMemAttrib
)
{
    IMG_UINT32  ui32NoPages;
    IMG_UINT32  ui32ExamPages;
    IMG_UINT32  i;
    IMG_UINT64  ui64DeviceMemoryBase;
    IMG_PHYSADDR  paCpuPhysAddr;
    IMG_UINT32  ui32Result;
    size_t      physAddrArrSize;

    struct priv_params *  prv = (struct priv_params *)heap->priv;

    /* If we don't know where the memory is...*/
    SYSOSKM_DisableInt();

    /* Calculate required no. of pages...*/
    ui32NoPages = (ui32Size + (HOST_MMU_PAGE_SIZE-1)) / HOST_MMU_PAGE_SIZE;

    /* Loop over allocated pages until we find an unallocated slot big enough for this allocation...*/
    ui32ExamPages = 0;
    while (ui32ExamPages < prv->npages)
    {
        /* If the current page is not allocated and we might have enough remaining to make this allocation...*/
        if (
                (!prv->alloc_pool[prv->cur_index]) &&
                ((prv->cur_index + ui32NoPages) <= prv->npages)
            )
        {
            /* Can we make this allocation...*/
            for (i=0; i<ui32NoPages; i++)
            {
                if (prv->alloc_pool[prv->cur_index+i])
                {
                    break;
                }
            }
            if (i == ui32NoPages)
            {
                /* Yes, mark pages as allocated...*/
                for (i=0; i<ui32NoPages; i++)
                {
                    prv->alloc_pool[prv->cur_index+i] = IMG_TRUE;
                }

                /* Calculate the memory address of the start of the allocation...*/
                //psPages->pvCpuKmAddr = (IMG_VOID *)((IMG_UINTPTR)prv->vstart + (prv->cur_index * HOST_MMU_PAGE_SIZE));
                psPages->pvImplData = (IMG_VOID *)(prv->vstart + (prv->cur_index * HOST_MMU_PAGE_SIZE));

                /* Update the current page index....*/
                prv->cur_index += ui32NoPages;
                if (prv->cur_index >= prv->npages)
                {
                    prv->cur_index = 0;
                }
                break;
            }
        }

        /* Update examined pages and page index...*/
        ui32ExamPages++;
        prv->cur_index++;
        if (prv->cur_index >= prv->npages)
        {
            prv->cur_index = 0;
        }
    }
    SYSOSKM_EnableInt();

    /* Check if allocation failed....*/
    IMG_ASSERT(ui32ExamPages < prv->npages);
    if (ui32ExamPages >= prv->npages)
    {
        /* Failed...*/
        /* dump some fragmentation information */
        int i = 0;
        int nAllocated = 0;
        int n64kBlocks  = 0;    // number of blocks of <16 consecutive pages
        int n128kBlocks = 0;
        int n256kBlocks = 0;
        int nBigBlocks  = 0;    // number of blocks of >=64 consecutive pages
        int nMaxBlocks  = 0;
        int nPages = 0;
        for(i = 0; i < (int)prv->npages; i++)
        {
            IMG_UINT8 isallocated = prv->alloc_pool[i];
            nPages++;
            if(i == prv->npages-1 || isallocated != prv->alloc_pool[i+1])
            {
                if(isallocated)
                    nAllocated += nPages;
                else if(nPages < 16)
                    n64kBlocks++;
                else if(nPages < 32)
                    n128kBlocks++;
                else if(nPages < 64)
                    n256kBlocks++;
                else
                    nBigBlocks++;
                    if(nMaxBlocks < nPages)
                        nMaxBlocks = nPages;
                isallocated = prv->alloc_pool[i];
                nPages = 0;
            }
        }
#ifdef printk
        /* hopefully, this will give some idea of the fragmentation of the memory */
        printk("AllocPages not able to allocate memory \n");
        printk("  number available memory areas under 64k:%d\n", n64kBlocks);
        printk("  number available memory areas under 128k:%d\n", n128kBlocks);
        printk("  number available memory areas under 256k:%d\n", n256kBlocks);
        printk("  number available memory areas over 256k:%d\n", nBigBlocks);
        printk("  total allocated memory:%dk/%dk\n", nAllocated*4, prv->npages*4);
#endif


        return IMG_ERROR_OUT_OF_MEMORY;
    }


    paCpuPhysAddr = CpuKmAddrToCpuPAddr(heap, psPages->pvImplData);
    IMG_ASSERT(paCpuPhysAddr != 0);
    if (paCpuPhysAddr == 0)
    {
        return IMG_ERROR_GENERIC_FAILURE;
    }

#ifdef CONFIG_ARM
    /* This flushes the outer cache in ARM, so we avoid memory corruption by late
       flushes of memory previously marked as cached. */
    if ((eMemAttrib & SYS_MEMATTRIB_CACHED) == 0) {
        mb();
        /* the following two calls are somewhat expensive, but are there for defensive reasons */
        flush_cache_all();
        outer_flush_all();
    }
#endif
    {
        IMG_PHYSADDR *      ppaCpuPhysAddrs;
        size_t numPages, pg_i, offset;

        // Memory for physical addresses
        numPages = (ui32Size + HOST_MMU_PAGE_SIZE - 1)/HOST_MMU_PAGE_SIZE;
        physAddrArrSize = sizeof(*ppaCpuPhysAddrs) * numPages;
        ppaCpuPhysAddrs = IMG_BIGORSMALL_ALLOC(physAddrArrSize);
        if (!ppaCpuPhysAddrs)
        {
            return IMG_ERROR_OUT_OF_MEMORY;
        }
        for (pg_i = 0, offset = 0; pg_i < numPages; offset += HOST_MMU_PAGE_SIZE, ++pg_i)
        {
                ppaCpuPhysAddrs[pg_i] = paCpuPhysAddr + offset;
        }
        // Set pointer to physical address in structure
        psPages->ppaPhysAddr = ppaCpuPhysAddrs;

    }
    /* Add this to the list of mappable regions...*/
    ui32Result = SYSBRGU_CreateMappableRegion(paCpuPhysAddr, ui32Size, eMemAttrib, psPages, &psPages->hRegHandle);
    IMG_ASSERT(ui32Result == IMG_SUCCESS);
    if (ui32Result != IMG_SUCCESS) 
    {
        goto error_mappable_region;
    }

#if defined (CLEAR_PAGES)
        if (psPages->pvImplData)
    IMG_MEMSET( psPages->pvImplData, 0, ui32Size);
#endif

    return IMG_SUCCESS;

    /* Error handling. */
error_mappable_region:
    IMG_BIGORSMALL_FREE(physAddrArrSize, psPages->ppaPhysAddr);
    psPages->ppaPhysAddr = IMG_NULL;

    return ui32Result;
}