/*---------------------------------------------------------------------------- *Function: CMM_Close *Parameters: OpenHandle : *Return Value: True/False *Implementation Notes: This function closes the device context identified by OpenHandle -----------------------------------------------------------------------------*/ BOOL CMM_Close( DWORD OpenHandle ) { CODEC_MEM_CTX *CodecMem; DWORD ret; ALLOC_MEM_T *node, *tmp_node; int count=0; ret = LockCMMMutex(); if(!ret){ RETAILMSG(1, (TEXT("[CMM_Close] CMM Mutex Lock Fail\r\n"))); return FALSE; } CodecMem = (CODEC_MEM_CTX *)OpenHandle; printD("[%d][CMM Close] \n", CodecMem->inst_no); if(!CodecMem){ RETAILMSG(1, (TEXT("[CMM_Close] CMM Invalid Input Handle\r\n"))); UnlockCMMMutex(); return FALSE; } printD("[CMM_Close] CodecMem->inst_no : %d CodecMem->callerProcess : 0x%x\n", CodecMem->inst_no, CodecMem->callerProcess); __try { // release u_addr and v_addr accoring to inst_no for(node = AllocMemHead; node != AllocMemTail; node = node->next){ if(node->inst_no == CodecMem->inst_no){ tmp_node = node; node = node->prev; ReleaseAllocMem(tmp_node, CodecMem); } } } __except ( EXCEPTION_EXECUTE_HANDLER ) { RETAILMSG( 1, ( _T("CMM_Close:Exception in releasing memory\n")) ); return FALSE; } printD("[%d][CMM Close] MergeFragmentation\n", CodecMem->inst_no); MergeFragmentation(CodecMem->inst_no); ReturnInstanceNo(CodecMem->inst_no); free(CodecMem); UnlockCMMMutex(); return TRUE; }
static int s3c_cmm_release(struct inode *inode, struct file *file) { DWORD ret; CODEC_MEM_CTX *CodecMem; ALLOC_MEM_T *node, *tmp_node; ret = LockCMMMutex(); if(!ret){ LOG_MSG(LOG_ERROR, "s3c_cmm_release", "DD::CMM Mutex Lock Fail\r\n"); return -1; } CodecMem = (CODEC_MEM_CTX *)file->private_data; LOG_MSG(LOG_TRACE, "s3c_cmm_release", "[%d][CMM Close] \n", CodecMem->inst_no); if(!CodecMem){ LOG_MSG(LOG_ERROR, "s3c_cmm_close", "CMM Invalid Input Handle\r\n"); UnlockCMMMutex(); return -1; } LOG_MSG(LOG_TRACE, "s3c_cmm_close", "CodecMem->inst_no : %d\n", CodecMem->inst_no); // release u_addr and v_addr accoring to inst_no for(node = AllocMemHead; node != AllocMemTail; node = node->next){ if(node->inst_no == CodecMem->inst_no){ tmp_node = node; node = node->prev; ReleaseAllocMem(tmp_node, CodecMem); } } LOG_MSG(LOG_TRACE, "s3c_cmm_release", "[%d]instance MergeFragmentation\n", CodecMem->inst_no); MergeFragmentation(CodecMem->inst_no); ReturnInstanceNo(CodecMem->inst_no); kfree(CodecMem); UnlockCMMMutex(); return 0; }
/*---------------------------------------------------------------------------- *Function: CMM_Open *Parameters: InitHandle :Handle to JPEG context dwAccess : dwShareMode :File share mode of JPEG *Return Value: This function returns a handle that identifies the open context of JPEG to the calling application. *Implementation Notes: Opens JPEG CODEC device for reading, writing, or both -----------------------------------------------------------------------------*/ DWORD CMM_Open( DWORD InitHandle, DWORD dwAccess, DWORD dwShareMode ) { CODEC_MEM_CTX *CodecMem; DWORD ret; UINT8 inst_no; ret = LockCMMMutex(); if(!ret){ RETAILMSG(1, (TEXT("[CMM_Open] CMM Mutex Lock Fail\r\n"))); return FALSE; } // check the number of instance if((inst_no = GetInstanceNo()) < 0){ RETAILMSG(1, (TEXT("[CMM_Open] Instance Number error-too many instance\r\n"))); UnlockCMMMutex(); return FALSE; } CodecMem = (CODEC_MEM_CTX *)malloc(sizeof(CODEC_MEM_CTX)); if(CodecMem == NULL){ RETAILMSG(1, (TEXT("[CMM_Init] CodecMem allocatopn failed\r\n"))); UnlockCMMMutex(); return FALSE; } memset(CodecMem, 0x00, sizeof(CODEC_MEM_CTX)); CodecMem->inst_no = inst_no; printD("\n*****************************\n[CMM_Open] instanceNo : %d\n*****************************\n", CodecMem->inst_no); PrintList(); UnlockCMMMutex(); return (DWORD)CodecMem; }
static int s3c_cmm_open(struct inode *inode, struct file *file) { CODEC_MEM_CTX *CodecMem; int ret; int inst_no; ret = LockCMMMutex(); if (!ret){ LOG_MSG(LOG_ERROR, "s3c_cmm_open", "DD::CMM Mutex Lock Fail\n"); return -1; } // check the number of instance if((inst_no = GetInstanceNo()) < 0){ LOG_MSG(LOG_ERROR, "s3c_cmm_open", "Instance Number error-too many instance\r\n"); UnlockCMMMutex(); return -1; } CodecMem = (CODEC_MEM_CTX *)kmalloc(sizeof(CODEC_MEM_CTX), GFP_KERNEL); if(CodecMem == NULL){ LOG_MSG(LOG_ERROR, "s3c_cmm_open", "CodecMem application failed\n"); UnlockCMMMutex(); return -1; } memset(CodecMem, 0x00, sizeof(CODEC_MEM_CTX)); CodecMem->inst_no = inst_no; printk("\n*****************************\n[CMM_Open] instanceNo : %d\n*****************************\n", CodecMem->inst_no); PrintList(); file->private_data = (CODEC_MEM_CTX *)CodecMem; UnlockCMMMutex(); return 0; }
/*---------------------------------------------------------------------------- *Function: CMM_IOControl *Parameters: OpenHandle : dwIoControlCode : *Return Value: True/False *Implementation Notes: JPEG_IOControl sends commands to initiate different * operations like Init,Decode and Deinit.The test * application uses the DeviceIOControl function to * specify an operation to perform -----------------------------------------------------------------------------*/ BOOL CMM_IOControl( DWORD OpenHandle, DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned ) { CODEC_MEM_CTX *CodecMem; BOOL result = TRUE; DWORD ret; UINT8 *u_addr; ALLOC_MEM_T *node; CMM_ALLOC_PRAM_T allocParam; CodecMem = (CODEC_MEM_CTX *)OpenHandle; if(!CodecMem){ RETAILMSG(1, (TEXT("[CMM_IOControl] CMM Invalid Input Handle\r\n"))); return FALSE; } if ((pInBuf == NULL) || (nInBufSize == 0)){ RETAILMSG(1, (TEXT("[CMM_IOControl] Invalid Input buffer or size\r\n"))); return FALSE; } ret = LockCMMMutex(); if(!ret){ RETAILMSG(1, (TEXT("[CMM_IOControl] CMM Mutex Lock Fail\r\n"))); return FALSE; } switch ( dwIoControlCode ) { case IOCTL_CODEC_MEM_ALLOC: printD("\n[%d][CMM_IOControl] IOCTL_CODEC_MEM_ALLOC\n", CodecMem->inst_no); if ((pInBuf == NULL) || (nInBufSize < sizeof(CMM_ALLOC_PRAM_T)) || (pOutBuf == NULL) || (nOutBufSize < sizeof(UINT))) { RETAILMSG(1, (TEXT("[CMM_IOControl] IOCTL_CODEC_MEM_ALLOC Invalid parameters\r\n"))); result = FALSE; break; } // Create a local copy of the input buffer first. if (!CeSafeCopyMemory(&allocParam, pInBuf, sizeof(CMM_ALLOC_PRAM_T)))// Copies memory inside a __try/__except block { result = FALSE; break; } if((allocParam.size) & (0xFFF)) // For 4K alignment { allocParam.size = (allocParam.size & 0xFFFFF000) + 0x1000; } printD("[IOCTL_CODEC_MEM_ALLOC] buffSize : %ld\n", allocParam.size); if((node = GetCodecVirAddr(CodecMem->inst_no, &allocParam)) == NULL){ result = FALSE; break; } CodecMem->callerProcess = (HANDLE) GetDirectCallerProcessId(); node->u_addr = (PBYTE)VirtualAllocEx(CodecMem->callerProcess, NULL, node->size, MEM_RESERVE, PAGE_NOACCESS); if (node->u_addr == NULL) { RETAILMSG(1, (_T("[CMM_IOControl]: Memory VirtualAlloc Fail. Error = %d\r\n"), GetLastError())); result = FALSE; } else { if (!VirtualCopyEx(CodecMem->callerProcess, node->u_addr, (HANDLE) GetCurrentProcessId(), node->v_addr, node->size, allocParam.cacheFlag ? PAGE_READWRITE : (PAGE_READWRITE | PAGE_NOCACHE))) { RETAILMSG(1, (_T("[CMM_IOControl]: Memory VirtualCopyEx Fail. Error = %d\r\n"), GetLastError())); result = FALSE; } } __try { if (result) { *((UINT *)pOutBuf) = (UINT) node->u_addr; } } __except ( EXCEPTION_EXECUTE_HANDLER ) { RETAILMSG( 1, ( _T("[CMM_IOControl]: exception in IOCTL_CODEC_MEM_ALLOC \r\n")) ); result = FALSE; } if (!result) { // free alloc node ReleaseAllocMem(node, CodecMem); } break; case IOCTL_CODEC_MEM_FREE: printD("\n[%d][CMM_IOControl] IOCTL_CODEC_MEM_FREE\n", CodecMem->inst_no); u_addr = (UINT8 *)pInBuf; printD("[CMM_IOControl] free adder : 0x%x \n", u_addr); for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == u_addr) break; } if(node == AllocMemTail) { RETAILMSG(1, (TEXT("[CMM_IOControl] invalid virtual address(0x%x)\r\n"), u_addr)); result = FALSE; break; } // free alloc node ReleaseAllocMem(node, CodecMem); break; case IOCTL_CODEC_CACHE_INVALIDATE: printD("\n[CMM_IOControl] IOCTL_CODEC_CACHE_INVALIDATE\n"); u_addr = (UINT8 *)pInBuf; printD("[CMM_IOControl] flush adder : 0x%x \n", u_addr); for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == u_addr) break; } if(node == AllocMemTail){ RETAILMSG(1, (TEXT("[%d][CMM_IOControl] invalid virtual address(0x%x)\r\n"), CodecMem->inst_no, u_addr)); result = FALSE; break; } InvalidateCacheRange((PBYTE) node->v_addr, (PBYTE) node->v_addr + node->size); break; case IOCTL_CODEC_CACHE_CLEAN: printD("\n[CMM_IOControl] IOCTL_CODEC_CACHE_CLEAN\n"); u_addr = (UINT8 *)pInBuf; printD("[CMM_IOControl] flush adder : 0x%x \n", u_addr); for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == u_addr) break; } if(node == AllocMemTail){ RETAILMSG(1, (TEXT("[%d][CMM_IOControl] invalid virtual address(0x%x)\r\n"), CodecMem->inst_no, u_addr)); result = FALSE; break; } CleanCacheRange((PBYTE) node->v_addr, (PBYTE) node->v_addr + node->size); break; // IOCTL_CODEC_CACHE_FLUSH is same as IOCTL_CODEC_CACHE_CLEAN_INVALIDATE. // This is remained for backward capability case IOCTL_CODEC_CACHE_FLUSH: case IOCTL_CODEC_CACHE_CLEAN_INVALIDATE: printD("\n[CMM_IOControl] IOCTL_CODEC_CACHE_CLEAN_INVALIDATE\n"); u_addr = (UINT8 *)pInBuf; printD("[CMM_IOControl] flush adder : 0x%x \n", u_addr); for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == u_addr) break; } if(node == AllocMemTail){ RETAILMSG(1, (TEXT("[%d][CMM_IOControl] invalid virtual address(0x%x)\r\n"), CodecMem->inst_no, u_addr)); result = FALSE; break; } CleanInvalidateCacheRange((PBYTE) node->v_addr, (PBYTE) node->v_addr + node->size); break; case IOCTL_CODEC_GET_PHY_ADDR: u_addr = (UINT8 *)pInBuf; for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == u_addr) break; } if(node == AllocMemTail){ RETAILMSG(1, (TEXT("[CMM_IOControl] invalid virtual address(0x%x)\r\n"), u_addr)); result = FALSE; break; } if ((pOutBuf == NULL) || (nOutBufSize < sizeof(UINT8 *))) { RETAILMSG(1, (TEXT("[CMM_IOControl] IOCTL_CODEC_GET_PHY_ADDR Invalid Output buffer or size\r\n"))); result = FALSE; break; } __try { *((UINT *)pOutBuf) = (UINT) node->cached_p_addr; } __except ( EXCEPTION_EXECUTE_HANDLER ) { RETAILMSG( 1, ( _T("[CMM_IOControl]: exception in IOCTL_CODEC_GET_PHY_ADDR \r\n")) ); result = FALSE; } break; default : RETAILMSG(1, (TEXT("[CMM_IOControl] CMM Invalid IOControl\r\n"))); } UnlockCMMMutex(); return result; }
static int __init s3c_cmm_init(void) { HANDLE h_Mutex; int ret; FREE_MEM_T *node; ALLOC_MEM_T *alloc_node; printk(banner); // Mutex initialization h_Mutex = CreateCMMmutex(); if (h_Mutex == NULL) { LOG_MSG(LOG_ERROR, "s3c_cmm_init", "DD::CMM Mutex Initialize error\r\n"); return FALSE; } ret = LockCMMMutex(); ret = misc_register(&s3c_cmm_miscdev); // First 4MB will use cacheable memory CachedVirAddr = (unsigned char *)ioremap_cached( (unsigned long)CODEC_MEM_START, \ (int)CODEC_CACHED_MEM_SIZE ); // Second 4MB will use non-cacheable memory NonCachedVirAddr = (unsigned char *)ioremap_nocache( (unsigned long)(CODEC_MEM_START + \ CODEC_CACHED_MEM_SIZE), (int)CODEC_NON_CACHED_MEM_SIZE ); // init alloc list, if(AllocMemHead == AllocMemTail) then, the list is NULL alloc_node = (ALLOC_MEM_T *)kmalloc(sizeof(ALLOC_MEM_T), GFP_KERNEL); memset(alloc_node, 0x00, sizeof(ALLOC_MEM_T)); alloc_node->next = alloc_node; alloc_node->prev = alloc_node; AllocMemHead = alloc_node; AllocMemTail = AllocMemHead; // init free list, if(FreeMemHead == FreeMemTail) then, the list is NULL node = (FREE_MEM_T *)kmalloc(sizeof(FREE_MEM_T), GFP_KERNEL); memset(node, 0x00, sizeof(FREE_MEM_T)); node->next = node; node->prev = node; FreeMemHead = node; FreeMemTail = FreeMemHead; node = (FREE_MEM_T *)kmalloc(sizeof(FREE_MEM_T), GFP_KERNEL); memset(node, 0x00, sizeof(FREE_MEM_T)); node->startAddr = CODEC_MEM_START; node->cacheFlag = 1; node->size = CODEC_CACHED_MEM_SIZE; InsertNodeToFreeList(node, -1); node = (FREE_MEM_T *)kmalloc(sizeof(FREE_MEM_T), GFP_KERNEL); memset(node, 0x00, sizeof(FREE_MEM_T)); node->startAddr = CODEC_MEM_START + CODEC_CACHED_MEM_SIZE; node->cacheFlag = 0; node->size = CODEC_NON_CACHED_MEM_SIZE; InsertNodeToFreeList(node, -1); UnlockCMMMutex(); return 0; }
static int s3c_cmm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret; CODEC_MEM_CTX * CodecMem; CODEC_MEM_ALLOC_ARG codec_mem_alloc_arg; CODEC_CACHE_FLUSH_ARG codec_cache_flush_arg; CODEC_GET_PHY_ADDR_ARG codec_get_phy_addr_arg; int result = 0; void * start; void * end; ALLOC_MEM_T * node; CODEC_MEM_FREE_ARG codec_mem_free_arg; CodecMem = (CODEC_MEM_CTX *)file->private_data; if (!CodecMem) { LOG_MSG(LOG_ERROR, "s3c_cmm_ioctl", "CMM Invalid Input Handle\n"); return -1; } ret = LockCMMMutex(); if(!ret){ LOG_MSG(LOG_ERROR, "s3c_cmm_ioctl", "DD::CMM Mutex Lock Fail\r\n"); return -1; } switch (cmd) { case IOCTL_CODEC_MEM_ALLOC: LOG_MSG(LOG_TRACE, "s3c_cmm_ioctl", "IOCTL_CODEC_MEM_GET\n"); copy_from_user(&codec_mem_alloc_arg, (CODEC_MEM_ALLOC_ARG *)arg, sizeof(CODEC_MEM_ALLOC_ARG)); node = GetCodecVirAddr(CodecMem->inst_no, &codec_mem_alloc_arg); if(node == NULL){ LOG_MSG(LOG_WARNING, "s3c_cmm_ioctl", "GetCodecVirAddr(%d)\r\n", CodecMem->inst_no); result = -1; break; } ret = copy_to_user((void *)arg, (void *)&codec_mem_alloc_arg, sizeof(CODEC_MEM_ALLOC_ARG)); break; case IOCTL_CODEC_MEM_FREE: LOG_MSG(LOG_TRACE, "s3c_cmm_ioctl", "IOCTL_CODEC_MEM_FREE\n"); copy_from_user(&codec_mem_free_arg, (CODEC_MEM_FREE_ARG *)arg, sizeof(CODEC_MEM_FREE_ARG)); for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == (unsigned char *)codec_mem_free_arg.u_addr) break; } if(node == AllocMemTail){ LOG_MSG(LOG_ERROR, "s3c_cmm_ioctl", "invalid virtual address(0x%x)\r\n", codec_mem_free_arg.u_addr); result = -1; break; } ReleaseAllocMem(node, CodecMem); break; case IOCTL_CODEC_CACHE_FLUSH: LOG_MSG(LOG_TRACE, "s3c_cmm_ioctl", "IOCTL_CODEC_CACHE_FLUSH\n"); copy_from_user(&codec_cache_flush_arg, (CODEC_CACHE_FLUSH_ARG *)arg, sizeof(CODEC_CACHE_FLUSH_ARG)); for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == (unsigned char *)codec_cache_flush_arg.u_addr) break; } if(node == AllocMemTail){ LOG_MSG(LOG_ERROR, "s3c_cmm_ioctl", "invalid virtual address(0x%x)\r\n", codec_cache_flush_arg.u_addr); result = -1; break; } start = node->v_addr; end = start + codec_cache_flush_arg.size; dmac_clean_range(start, end); outer_clean_range(__pa(start), __pa(end)); break; case IOCTL_CODEC_GET_PHY_ADDR: copy_from_user(&codec_get_phy_addr_arg, (CODEC_GET_PHY_ADDR_ARG *)arg, sizeof(CODEC_GET_PHY_ADDR_ARG)); for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == (unsigned char *)codec_get_phy_addr_arg.u_addr) break; } if(node == AllocMemTail){ LOG_MSG(LOG_ERROR, "s3c_cmm_ioctl", "invalid virtual address(0x%x)\r\n", codec_get_phy_addr_arg.u_addr); result = -1; break; } if(node->cacheFlag) codec_get_phy_addr_arg.p_addr = node->cached_p_addr; else codec_get_phy_addr_arg.p_addr = node->uncached_p_addr; copy_to_user((void *)arg, (void *)&codec_get_phy_addr_arg, sizeof(CODEC_GET_PHY_ADDR_ARG)); break; case IOCTL_CODEC_MERGE_FRAGMENTATION: MergeFragmentation(CodecMem->inst_no); break; case IOCTL_CODEC_CACHE_INVALIDATE: LOG_MSG(LOG_TRACE, "s3c_cmm_ioctl", "IOCTL_CODEC_CACHE_INVALIDATE\n"); copy_from_user(&codec_cache_flush_arg, (CODEC_CACHE_FLUSH_ARG *)arg, sizeof(CODEC_CACHE_FLUSH_ARG)); for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == (unsigned char *)codec_cache_flush_arg.u_addr) break; } if(node == AllocMemTail){ LOG_MSG(LOG_ERROR, "s3c_cmm_ioctl", "invalid virtual address(0x%x)\r\n", codec_cache_flush_arg.u_addr); result = -1; break; } start = node->v_addr; end = start + codec_cache_flush_arg.size; dmac_flush_range(start, end); break; case IOCTL_CODEC_CACHE_CLEAN: LOG_MSG(LOG_TRACE, "s3c_cmm_ioctl", "IOCTL_CODEC_CACHE_CLEAN\n"); copy_from_user(&codec_cache_flush_arg, (CODEC_CACHE_FLUSH_ARG *)arg, sizeof(CODEC_CACHE_FLUSH_ARG)); for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == (unsigned char *)codec_cache_flush_arg.u_addr) break; } if(node == AllocMemTail){ LOG_MSG(LOG_ERROR, "s3c_cmm_ioctl", "invalid virtual address(0x%x)\r\n", codec_cache_flush_arg.u_addr); result = -1; break; } start = node->v_addr; end = start + codec_cache_flush_arg.size; dmac_clean_range(start, end); break; case IOCTL_CODEC_CACHE_CLEAN_INVALIDATE: LOG_MSG(LOG_TRACE, "s3c_cmm_ioctl", "IOCTL_CODEC_CACHE_INVALIDATE\n"); copy_from_user(&codec_cache_flush_arg, (CODEC_CACHE_FLUSH_ARG *)arg, sizeof(CODEC_CACHE_FLUSH_ARG)); for(node = AllocMemHead; node != AllocMemTail; node = node->next) { if(node->u_addr == (unsigned char *)codec_cache_flush_arg.u_addr) break; } if(node == AllocMemTail){ LOG_MSG(LOG_ERROR, "s3c_cmm_ioctl", "invalid virtual address(0x%x)\r\n", codec_cache_flush_arg.u_addr); result = -1; break; } start = node->v_addr; end = start + codec_cache_flush_arg.size; dmac_clean_range(start, end); dmac_flush_range(start, end); break; default : LOG_MSG(LOG_ERROR, "s3c_cmm_ioctl", "DD::CMM Invalid ioctl : 0x%X\r\n", cmd); } UnlockCMMMutex(); if(result == 0) return TRUE; else return FALSE; }