/*
 * Project Name JPG DRIVER IN WINCE
 * Copyright  2009 Samsung Electronics Co, Ltd. All Rights Reserved.
 *
 * This file implements JPG driver.
 *
 * @name JPG DRIVER Module (JPGIntr.c)
 * @author Jiyoung Shin (idon.shin@samsung.com)
 * @date 2009/06/05
 */

#include <windows.h>
#include <nkintr.h>
#include "bsp_cfg.h"
#include "bsp_args.h"
#include "JPGIntr.h"
#include "JPGMem.h"
#include "intr_reg.h"


UINT32 g_JPGIrq     = IRQ_JPEG;
UINT32 g_JPGSysIntr = SYSINTR_UNDEFINED;


static HANDLE gJPGDoneEvent = NULL;
static HANDLE gJPGIntrEvent = NULL;
static HANDLE gJPGIntrThread = NULL;

static BOOL CreateJPGInterruptNotification(void);
static DWORD JPGIntrThread(void);

static BOOL CreateJPGInterruptNotification(void)
{
    DBGMSG(JPG_FUNC,(_T("[JPGDRV] %s++\r\n"), _T(__FUNCTION__)));
    gJPGIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!gJPGIntrEvent) {
        ERRMSG((_T("[JPGDRV] %s :: gJPGIntrEvent CreateEvent Failed\r\n"), _T(__FUNCTION__)));
        return FALSE;
    }
    gJPGDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!gJPGDoneEvent){
        ERRMSG((_T("[JPGDRV] %s :: gJPGDoneEvent CreateEvent Failed\r\n"), _T(__FUNCTION__)));
        return FALSE;
    }
    DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
    return TRUE;
}

JPG_RETURN_STATUS waitForJPGIRQ()
{
    volatile JPG_SFR *JpgSfr;
    JPG_RETURN_STATUS retVal = JPG_FAIL;
    unsigned int intrStatus;
    int ret;

    JpgSfr = GetJPGSfrVirAddr();
    if (gJPGDoneEvent == NULL){
        ERRMSG((_T("[JPGDRV] %s :: gJPGDoneEvent == NULL\r\n"), _T(__FUNCTION__)));
        return JPG_FAIL;
    }

    ret = WaitForSingleObject(gJPGDoneEvent, 5000);

    if (ret == WAIT_TIMEOUT){
        ERRMSG((_T("[JPGDRV] %s :: Interrupt Time Out\r\n"), _T(__FUNCTION__)));
        return JPG_FAIL;
    }
    
    intrStatus = (JpgSfr->JPGINTST & ((1<<6)|(1<<5)));
    if(intrStatus == 0x40)
        retVal = OK_ENC_OR_DEC;
    else if(intrStatus == 0x20)
        retVal = ERR_ENC_OR_DEC;
    else
        retVal = ERR_UNKNOWN;

    if(JpgSfr->JPGOPR != 0) retVal = ERR_UNKNOWN;

    DBGMSG(JPG_DBG,(_T("[JPGDRV] waitForJPGIRQ :: intrStatus(0x%x)\r\n"), intrStatus));
    ResetEvent(gJPGDoneEvent);

    return retVal;
}

void JPGClearIntr()
{
    volatile JPG_SFR *JpgSfr;


    JpgSfr = GetJPGSfrVirAddr(); 
    JpgSfr->JPGCOM = 0x4; 
}

static DWORD JPGIntrThread(void)
{

    DBGMSG(JPG_FUNC,(_T("[JPGDRV] %s++\r\n"), _T(__FUNCTION__)));
    while (1)
    {

        WaitForSingleObject(gJPGIntrEvent, INFINITE);

        JPGClearIntr();
        
        SetEvent(gJPGDoneEvent); 

        // Notify to Kernel that JPG Interrupt processing is completed.
        InterruptDone(g_JPGSysIntr);
    }
    DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
}

JPG_RETURN_STATUS CreateJPGIntrResource()
{
    BOOL r;

    DBGMSG(JPG_FUNC,(_T("[JPGDRV] %s++\r\n"), _T(__FUNCTION__)));
    if (!CreateJPGInterruptNotification()) 
        return JPG_FAIL;
    

    r = KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR,
                        &g_JPGIrq,     sizeof(UINT32),
                        &g_JPGSysIntr, sizeof(UINT32),
                        NULL);
    if (r != TRUE) {
        ERRMSG((_T("[JPGDRV] %s :: OCTL_HAL_REQUEST_SYSINTR Failed\r\n"), _T(__FUNCTION__)));
        return JPG_FAIL;
    }


    r = InterruptInitialize(g_JPGSysIntr, gJPGIntrEvent, NULL, 0);
    if (r != TRUE) {
        ERRMSG((_T("[JPGDRV] %s :: InterruptInitialize Failed\r\n"), _T(__FUNCTION__)));
        return JPG_FAIL;
    }

    gJPGIntrThread = CreateThread((LPSECURITY_ATTRIBUTES)NULL,
                                  0,
                                  (LPTHREAD_START_ROUTINE)JPGIntrThread,
                                  0,
                                  0,
                                  NULL);
    if (!gJPGIntrThread) {
        ERRMSG((_T("[JPGDRV] %s :: CreateThread Failed\r\n"), _T(__FUNCTION__)));
        return JPG_FAIL;
    }

    // Bump up the priority since the interrupt must be serviced immediately.
    CeSetThreadPriority(gJPGIntrThread, 100);

    DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));

    return JPG_SUCCESS;
}


void DeleteJPGIntrResource(void)
{
    DBGMSG(JPG_FUNC,(_T("[JPGDRV] %s++\r\n"), _T(__FUNCTION__)));
    CloseHandle(gJPGDoneEvent);
    gJPGDoneEvent = NULL;

    CloseHandle(gJPGIntrEvent);
    gJPGIntrEvent = NULL;

    CloseHandle(gJPGIntrThread);
    DBGMSG(JPG_FUNC,(_T("[JPGAPI] %s--\r\n"), _T(__FUNCTION__)));
}

