Exemplo n.º 1
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;
}
Exemplo n.º 2
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;
}