/*! ****************************************************************************** @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(); }
/*! ****************************************************************************** @Function dmankm_DisconnectComps ******************************************************************************/ static IMG_RESULT dmankm_DisconnectComps(DMANKM_sConnContext * psConnContext) { DMANKM_sAttachContext * psAttachContext; IMG_UINT32 ui32Result; psAttachContext = (DMANKM_sAttachContext *) LST_first( &psConnContext->sAttachList); while (psAttachContext != IMG_NULL ) { /* If there is a disconnect function...*/ if (psAttachContext->sCompAttach.pfnCompDisconnect != IMG_NULL ) { /* Call it...*/ ui32Result = psAttachContext->sCompAttach.pfnCompDisconnect( psAttachContext, psAttachContext->pvCompAttachmentData); if (ui32Result != IMG_SUCCESS) { IMG_ASSERT(ui32Result == IMG_SUCCESS); return ui32Result; } } /* Remove, free the name and control block...*/ LST_remove(&psConnContext->sAttachList, psAttachContext); RMAN_DestroyBucket(psAttachContext->hResBHandle); RMAN_FreeResource(psAttachContext->hResHandle); IMG_FREE(psAttachContext->pszCompName); IMG_FREE(psAttachContext); psAttachContext = (DMANKM_sAttachContext *) LST_first( &psConnContext->sAttachList); } /* Return success...*/ return IMG_SUCCESS; }
/*! ****************************************************************************** @Function palloc_fnCompDisconnect ******************************************************************************/ static IMG_RESULT palloc_fnCompDisconnect ( IMG_HANDLE hAttachHandle, IMG_VOID * pvCompAttachmentData ) { PALLOC_sAttachContext * psAttachContext = pvCompAttachmentData; LOG_EVENT(PALLOC, PALLOC_COMPDISCONNECT, (LOG_FLAG_START), 0, 0); /* Destroy the bucket and it's resources...*/ RMAN_DestroyBucket(psAttachContext->hResBHandle); /* If we opened a device...*/ if (psAttachContext->hSysDevHandle != IMG_NULL) { SYSDEVKM_CloseDevice(psAttachContext->hSysDevHandle); } /* Free attachment context...*/ IMG_FREE(psAttachContext); LOG_EVENT(PALLOC, PALLOC_COMPDISCONNECT, (LOG_FLAG_END), 0, 0); /* Return success...*/ return IMG_SUCCESS; }
/*! ****************************************************************************** @Function palloc_fnCompConnect ******************************************************************************/ static IMG_RESULT palloc_fnCompConnect ( IMG_HANDLE hAttachHandle, IMG_VOID ** ppvCompAttachmentData ) { PALLOC_sAttachContext * psAttachContext; IMG_UINT32 ui32Result; IMG_CHAR * pszDeviceName; /* Allocate attachment context structure...*/ psAttachContext = IMG_MALLOC(sizeof(*psAttachContext)); IMG_ASSERT(psAttachContext != IMG_NULL); if (psAttachContext == IMG_NULL) { return IMG_ERROR_OUT_OF_MEMORY; } IMG_MEMSET(psAttachContext, 0, sizeof(*psAttachContext)); /* Ensure the resource manager is initialised...*/ ui32Result = RMAN_Initialise(); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_rman_init; } /* Create a bucket for the resources...*/ ui32Result = RMAN_CreateBucket(&psAttachContext->hResBHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_rman_bucket; } /* Get device information...*/ psAttachContext->hDevHandle = DMANKM_GetDevHandleFromAttach(hAttachHandle); pszDeviceName = DMANKM_GetDeviceName(psAttachContext->hDevHandle); ui32Result = SYSDEVU_OpenDevice(pszDeviceName, &psAttachContext->hSysDevHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_sysdev_open; } /* Return attachment context...*/ *ppvCompAttachmentData = psAttachContext; /* Return success...*/ return IMG_SUCCESS; /* Error handling. */ error_sysdev_open: RMAN_DestroyBucket(psAttachContext->hResBHandle); error_rman_bucket: error_rman_init: IMG_FREE(psAttachContext); return ui32Result; }
/*! ****************************************************************************** @Function wrapu_fnCompDisconnect ******************************************************************************/ static IMG_RESULT wrapu_fnCompDisconnect ( IMG_HANDLE hAttachHandle, IMG_VOID * pvCompAttachmentData ) { WRAPU_sAttachContext * psAttachContext = pvCompAttachmentData; /* Destroy the bucket and it's resources...*/ RMAN_DestroyBucket(psAttachContext->hResBHandle); /* If we opened a device...*/ if (psAttachContext->hSysDevHandle != IMG_NULL) { SYSDEVKM_CloseDevice(psAttachContext->hSysDevHandle); } /* Free attachment context...*/ IMG_FREE(psAttachContext); /* Return success...*/ return IMG_SUCCESS; }
/*! ****************************************************************************** @Function DMANKM_OpenDevice ******************************************************************************/ IMG_RESULT DMANKM_OpenDevice(IMG_HANDLE hDevHandle, DMAN_eOpenMode eOpenMode, IMG_HANDLE * phConnHandle, IMG_UINT32 * pui32ConnId) { DMANKM_sDevContext * psDevContext = (DMANKM_sDevContext *) hDevHandle; DMANKM_sConnContext * psConnContext; DMANKM_sConnContext * psInitConnContext = IMG_NULL; IMG_UINT32 ui32Result; IMG_HANDLE hProcessId; /* Check mode. */ if ((eOpenMode != DMAN_OMODE_EXCLUSIVE) && (eOpenMode != DMAN_OMODE_SHARED)) { IMG_ASSERT(IMG_FALSE); return IMG_ERROR_INVALID_PARAMETERS; } /* Loop over the device connections to see if this process already has a connection...*/ hProcessId = SYSOSKM_GetProcessId(); psConnContext = (DMANKM_sConnContext *) LST_first(&psDevContext->sConnList); while (psConnContext != IMG_NULL ) { /* If process already has a connection. */ if (psConnContext->hProcessId == hProcessId) { /* Update the open count...*/ psConnContext->ui32OpenCnt++; /* Return the connection handle and/or id...*/ if (phConnHandle != IMG_NULL ) { *phConnHandle = psConnContext; } if (pui32ConnId != IMG_NULL ) { *pui32ConnId = psConnContext->ui32ConnId; } /* Return success...*/ return IMG_SUCCESS; } /* Look at next connection. */ psConnContext = (DMANKM_sConnContext *) LST_next(psConnContext); } /* See if we have a connection exclusive access required or only exclusive access available. */ psConnContext = (DMANKM_sConnContext *) LST_first(&psDevContext->sConnList); if ((psConnContext != IMG_NULL )&& ( (eOpenMode == DMAN_OMODE_EXCLUSIVE) || (psConnContext->psDevContext->sDevRegister.ui32ConnFlags == DMAN_CFLAG_EXCLUSIVE) ) ){ IMG_ASSERT(IMG_FALSE); return IMG_ERROR_DEVICE_UNAVAILABLE; } /* Allocate connection context...*/ psConnContext = IMG_MALLOC(sizeof(*psConnContext)); if (psConnContext == IMG_NULL ) { IMG_ASSERT(psConnContext != IMG_NULL); return IMG_ERROR_OUT_OF_MEMORY; } IMG_MEMSET(psConnContext, 0, sizeof(*psConnContext)); /* Initialise list of resource allocator...*/ LST_init(&psConnContext->sAttachList); /* Setup connection context...*/ psConnContext->psDevContext = psDevContext; psConnContext->ui32OpenCnt = 1; psConnContext->hProcessId = hProcessId; /* Update the count of connections...*/ psDevContext->ui32ConnCnt++; /* If this is the first connection...*/ if (psDevContext->ui32ConnCnt == 1) { /* Create resource bucket for connections and attachments...*/ RMAN_Initialise(); ui32Result = RMAN_CreateBucket(&psDevContext->hResBHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_create_bucket; } } /* Add to list of connections...*/ LST_add(&psDevContext->sConnList, psConnContext); ui32Result = RMAN_RegisterResource(psDevContext->hResBHandle, DMAN_CONN_TYPE_ID, IMG_NULL, psConnContext, &psConnContext->hResHandle, &psConnContext->ui32ConnId); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_register_resource; } /* Register with the Process Manager in case the process dies...*/ ui32Result = PMAN_Initialise(); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_pman_init; } PMAN_RegisterProcessLostCb(dmankm_fnProcessLostCb, psConnContext, &psConnContext->hProcLostCbHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_pman_register_cb; } /* If this the first connection and initialise function...*/ if ((psDevContext->ui32ConnCnt == 1) && (psDevContext->sDevRegister.pfnDevInit != IMG_NULL )) { /* Allocate implicit connection context...*/ psInitConnContext = IMG_MALLOC(sizeof(*psInitConnContext)); if (psInitConnContext == IMG_NULL ) { IMG_ASSERT(psInitConnContext != IMG_NULL); ui32Result = IMG_ERROR_OUT_OF_MEMORY; goto error_init_conn_ctx; } IMG_MEMSET(psInitConnContext, 0, sizeof(*psInitConnContext)); /* Associated this connection with the device and process...*/ psInitConnContext->psDevContext = psDevContext; psInitConnContext->ui32OpenCnt = 1; psInitConnContext->hProcessId = hProcessId; /* Mark this as the init connection...*/ psInitConnContext->bInitConn = IMG_TRUE; /* Add implicit to list of connections...*/ LST_add(&psDevContext->sConnList, psInitConnContext); ui32Result = RMAN_RegisterResource(psDevContext->hResBHandle, DMAN_CONN_TYPE_ID, IMG_NULL, psInitConnContext, &psInitConnContext->hResHandle, &psInitConnContext->ui32ConnId); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_register_resource_init_ctx; } IMG_ASSERT( (psDevContext->sDevRegister.ui32ConnFlags == DMAN_CFLAG_EXCLUSIVE) || (psDevContext->sDevRegister.ui32ConnFlags == DMAN_CFLAG_SHARED)); /* If it's not a pseudo device... */ if ((psDevContext->sDevRegister.ui32DevFlags & DMAN_DFLAG_PSEUDO_DEVICE) == 0) { /* Open the device...*/ ui32Result = SYSDEVU_OpenDevice(psDevContext->pszDeviceName, &psDevContext->hSysDevHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_open_device; } /* Power the device on. */ SYSDEVU_SetPowerState(psDevContext->hSysDevHandle, SYSOSKM_POWERSTATE_S0, IMG_FALSE); } ui32Result = psDevContext->sDevRegister.pfnDevInit(psDevContext, psInitConnContext, &psDevContext->pvDevInstanceData); if (ui32Result != IMG_SUCCESS) { REPORT(REPORT_MODULE_DMAN, REPORT_ERR, "dev init failed (%d)", ui32Result); goto error_dev_init; } /* If there is a Device Kernel mode HISR...*/ if (psDevContext->sDevRegister.pfnDevKmHisr != IMG_NULL ) { IMG_ASSERT(psDevContext->sDevRegister.pfnDevKmLisr != IMG_NULL); ui32Result = SYSOSKM_CreateKmHisr(&dmankm_fnDevKmHisr, psDevContext, &psDevContext->hHISRHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_create_km_hisr; } } /* If there is a Device Kernel mode LISR...*/ if (psDevContext->sDevRegister.pfnDevKmLisr != IMG_NULL ) { /* Register the LISR wrapper...*/ SYSDEVU_RegisterDevKmLisr(psDevContext->hSysDevHandle, &dmankm_fnDevKmLisr, psDevContext); } } /* If connect/open function...*/ if (psDevContext->sDevRegister.pfnDevConnect != IMG_NULL ) { ui32Result = psDevContext->sDevRegister.pfnDevConnect(psConnContext, psDevContext->pvDevInstanceData, &psConnContext->pvDevConnectionData); IMG_ASSERT( ui32Result == IMG_SUCCESS || ui32Result == IMG_ERROR_INTERRUPTED); if (ui32Result != IMG_SUCCESS && ui32Result != IMG_ERROR_INTERRUPTED) { goto error_dev_connect; } } /* Return the connection handle and/or id...*/ if (phConnHandle != IMG_NULL ) { *phConnHandle = psConnContext; } if (pui32ConnId != IMG_NULL ) { *pui32ConnId = psConnContext->ui32ConnId; } /* Return success...*/ return ui32Result; /* Error handling. */ error_dev_connect: /* If this not the first connection or there's no initialise function...*/ if ((1 != psDevContext->ui32ConnCnt) || (IMG_NULL == psDevContext->sDevRegister.pfnDevInit)) { /* ...skip de-initialisation of this part. */ goto error_init_conn_ctx; } if (IMG_NULL != psDevContext->sDevRegister.pfnDevKmHisr) { SYSOSKM_DestroyKmHisr(psDevContext->hHISRHandle); } error_create_km_hisr: if (IMG_NULL != psDevContext->sDevRegister.pfnDevDeinit) { psDevContext->sDevRegister.pfnDevDeinit(psDevContext, psInitConnContext, psDevContext->pvDevInstanceData); } error_dev_init: if ((psDevContext->sDevRegister.ui32DevFlags & DMAN_DFLAG_PSEUDO_DEVICE) == 0) { SYSDEVU_CloseDevice(psDevContext->hSysDevHandle); } error_open_device: RMAN_FreeResource(psInitConnContext->hResHandle); error_register_resource_init_ctx: LST_remove(&psDevContext->sConnList, psInitConnContext); IMG_FREE(psInitConnContext); error_init_conn_ctx: PMAN_RemoveProcessLostCb(psConnContext->hProcLostCbHandle); /* release per-process resources in PMAN, allocated inside PMAN_RegisterProcessLostCb. We have to use device disconnect, although the device wasn't actually initialised, because no other function is exposed by PMAN */ PMAN_DevDisconnectComplete(hProcessId); error_pman_register_cb: error_pman_init: RMAN_FreeResource(psConnContext->hResHandle); error_register_resource: LST_remove(&psDevContext->sConnList,psConnContext); if (1 == psDevContext->ui32ConnCnt) { RMAN_DestroyBucket(psDevContext->hResBHandle); } error_create_bucket: psDevContext->ui32ConnCnt--; IMG_FREE(psConnContext); return ui32Result; }
/*! ****************************************************************************** @Function DMANKM_AttachComponent ******************************************************************************/ IMG_RESULT DMANKM_AttachComponent(IMG_HANDLE hConnHandle, IMG_CHAR * pszCompName, DMANKM_pfnCompAttach pfnCompAttach, IMG_HANDLE * phAttachHandle, IMG_UINT32 * pui32AttachId) { DMANKM_sConnContext * psConnContext = (DMANKM_sConnContext *) hConnHandle; IMG_BOOL bFound; DMANKM_sAttachContext * psAttachContext; IMG_UINT32 ui32Result; IMG_ASSERT(gDmanKmInitialised); /* See if this component is already register with this connection...*/ bFound = dman_LocateComponentKM(pszCompName, psConnContext, &psAttachContext); if (bFound) { /* Cross check name and attach function should be the same...*/ IMG_ASSERT(psAttachContext->pfnCompAttach == pfnCompAttach); /* Return the attachment handle and/or id...*/ if (phAttachHandle != IMG_NULL ) { *phAttachHandle = psAttachContext; } if (pui32AttachId != IMG_NULL ) { *pui32AttachId = psAttachContext->ui32AttachId; } return IMG_SUCCESS; } /* Allocate a attachment context structure...*/ psAttachContext = IMG_MALLOC(sizeof(*psAttachContext)); if (psAttachContext == IMG_NULL ) { IMG_ASSERT(psAttachContext != IMG_NULL); return IMG_ERROR_OUT_OF_MEMORY; } IMG_MEMSET(psAttachContext, 0, sizeof(*psAttachContext)); /* Copy the component name etc...*/ psAttachContext->pszCompName = IMG_STRDUP(pszCompName); if (psAttachContext->pszCompName == IMG_NULL ) { IMG_ASSERT(psAttachContext->pszCompName != IMG_NULL); ui32Result = IMG_ERROR_OUT_OF_MEMORY; goto error_comp_name; } psAttachContext->pfnCompAttach = pfnCompAttach; psAttachContext->psConnContext = psConnContext; ui32Result = RMAN_CreateBucket(&psAttachContext->hResBHandle); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_create_bucket; } /* Add to the attachment component list...*/ LST_add(&psConnContext->sAttachList, psAttachContext); ui32Result = RMAN_RegisterResource(psConnContext->psDevContext->hResBHandle, DMAN_ATTACH_TYPE_ID, IMG_NULL, psAttachContext, &psAttachContext->hResHandle, &psAttachContext->ui32AttachId); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_register_resource; } /* Call components attach function...*/ ui32Result = pfnCompAttach(psAttachContext, &psAttachContext->sCompAttach); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_comp_attach; } /* If connect/open function...*/ if (psAttachContext->sCompAttach.pfnCompConnect != IMG_NULL ) { ui32Result = psAttachContext->sCompAttach.pfnCompConnect( psAttachContext, &psAttachContext->pvCompAttachmentData); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { goto error_comp_connect; } } /* Return the attachment handle and/or id...*/ if (phAttachHandle != IMG_NULL ) { *phAttachHandle = psAttachContext; } if (pui32AttachId != IMG_NULL ) { *pui32AttachId = psAttachContext->ui32AttachId; } /* Return success...*/ return IMG_SUCCESS; /* Error handling. */ error_comp_connect: error_comp_attach: RMAN_FreeResource( psAttachContext->hResHandle); error_register_resource: LST_remove(&psConnContext->sAttachList, psAttachContext); RMAN_DestroyBucket(psAttachContext->hResBHandle); error_create_bucket: IMG_FREE(psAttachContext->pszCompName); error_comp_name: IMG_FREE(psAttachContext); return ui32Result; }
/*! ****************************************************************************** @Function DMANKM_DevDisconnectComplete ******************************************************************************/ IMG_RESULT DMANKM_DevDisconnectComplete(IMG_HANDLE hConnHandle) { IMG_UINT32 ui32Result; DMANKM_sConnContext * psConnContext = hConnHandle; DMANKM_sConnContext * psInitConnContext; DMANKM_sDevContext * psDevContext = psConnContext->psDevContext; IMG_HANDLE hProcessId; /* Disconnect components attached to this connection...*/ ui32Result = dmankm_DisconnectComps(psConnContext); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { return ui32Result; } /* Save the process id...*/ hProcessId = psConnContext->hProcessId; /* Remove and free this connection...*/ LST_remove(&psDevContext->sConnList, psConnContext); RMAN_FreeResource(psConnContext->hResHandle); IMG_FREE(psConnContext); /* Update the connection count...*/ psDevContext->ui32ConnCnt--; /* If connection count 0...*/ if (psDevContext->ui32ConnCnt == 0) { /* Deinitailise the device....*/ psInitConnContext = (DMANKM_sConnContext *) LST_first( &psDevContext->sConnList); if(psInitConnContext == NULL) { IMG_ASSERT(psInitConnContext != IMG_NULL); return IMG_ERROR_GENERIC_FAILURE; } else { IMG_ASSERT(psInitConnContext->bInitConn); } /* Deregister the LISR...*/ if (psDevContext->sDevRegister.pfnDevKmLisr != IMG_NULL ) { SYSDEVU_RemoveDevKmLisr(psDevContext->hSysDevHandle); } /* Deregister the HISR...*/ if (psDevContext->sDevRegister.pfnDevKmHisr != IMG_NULL ) { if (psDevContext->hHISRHandle) { IMG_HANDLE HISRHandle = psDevContext->hHISRHandle; psDevContext->hHISRHandle = IMG_NULL; SYSOSKM_DestroyKmHisr(HISRHandle); } } /* If we have a deinitialise function...*/ if (psDevContext->sDevRegister.pfnDevDeinit != IMG_NULL ) { psDevContext->sDevRegister.pfnDevDeinit(psDevContext, psInitConnContext, psDevContext->pvDevInstanceData); } if ((psDevContext->sDevRegister.ui32DevFlags & DMAN_DFLAG_PSEUDO_DEVICE) == 0) { /* Power the device off. */ SYSDEVU_SetPowerState(psDevContext->hSysDevHandle, SYSOSKM_POWERSTATE_S5, IMG_FALSE); } /* Disconnect components attached to the implicit connection...*/ ui32Result = dmankm_DisconnectComps(psInitConnContext); IMG_ASSERT(ui32Result == IMG_SUCCESS); if (ui32Result != IMG_SUCCESS) { return ui32Result; } /* Remove and free the implicit connection...*/ LST_remove(&psDevContext->sConnList, psInitConnContext); RMAN_FreeResource(psInitConnContext->hResHandle); IMG_FREE(psInitConnContext); /* Destroy the resource bucket used for connections and attachments...*/ RMAN_DestroyBucket(psDevContext->hResBHandle); psDevContext->hResBHandle = IMG_NULL; /* If we opened the device with SYSDEVKM...*/ if (psDevContext->hSysDevHandle != IMG_NULL ) { /* Close it...*/ SYSDEVU_CloseDevice(psDevContext->hSysDevHandle); psDevContext->hSysDevHandle = IMG_NULL; } } /* Let the Process Manager know the connection has been broken...*/ PMAN_DevDisconnectComplete(hProcessId); /* Unlock the device...*/ DMANKM_UnlockDeviceContext(psDevContext); /* Return success...*/ return IMG_SUCCESS; }