/*---------------------------------------------------------------------------- *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 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; }