/**
 * Handler for shared region get config API.
 *
 * \param ctp	Thread's associated context information.
 * \param msg	The actual devctl() message.
 * \param ocb	OCB associated with client's session.
 *
 * \return POSIX errno value.
 *
 * \retval EOK		Success.
 * \retval ENOTSUP	Unsupported devctl().
 */
int syslink_sharedregion_getconfig(resmgr_context_t *ctp, io_devctl_t *msg, syslink_ocb_t *ocb) {

	SharedRegionDrv_CmdArgs *		cargs = (SharedRegionDrv_CmdArgs *) (_DEVCTL_DATA (msg->i));

	SharedRegion_Config *config = (SharedRegion_Config *)(cargs+1);

	SharedRegion_getConfig (config);
	cargs->apiStatus = SharedRegion_S_SUCCESS;

	SETIOV(&ctp->iov[0], &msg->o, sizeof(msg->o) + sizeof(SharedRegionDrv_CmdArgs));
	SETIOV(&ctp->iov[1], config, sizeof(SharedRegion_Config));

    return _RESMGR_NPARTS(2);
}
/**
 * Handler for shared region get region info API.
 *
 * \param ctp	Thread's associated context information.
 * \param msg	The actual devctl() message.
 * \param ocb	OCB associated with client's session.
 *
 * \return POSIX errno value.
 *
 * \retval EOK		Success.
 * \retval ENOTSUP	Unsupported devctl().
 */
int syslink_sharedregion_getregioninfo(
        resmgr_context_t *      ctp,
        io_devctl_t *           msg,
        syslink_ocb_t *         ocb)
{
    SharedRegionDrv_CmdArgs *   cmdArgs;
    SharedRegion_Region   *     region;
    SharedRegion_Config         config;
    UInt16                      i;

    cmdArgs = (SharedRegionDrv_CmdArgs *)(_DEVCTL_DATA(msg->i));
    region = (SharedRegion_Region *)(cmdArgs + 1);
    SharedRegion_getConfig(&config);

    for (i = 0; i < config.numEntries; i++) {
        SharedRegion_getRegionInfo(i, &region[i]);

        if (region[i].entry.isValid) {
            if (region[i].entry.createHeap) {
                /* convert the kernel virtual address to physical addresses */
                region[i].entry.base = MemoryOS_translate(
                    (Ptr)region[i].entry.base, Memory_XltFlags_Virt2Phys);
                GT_assert(curTrace, (region[i].entry.base != NULL));
            }
            /* else, nothing to do, entry.base is already physical address */
        }
        else {
            region[i].entry.base = NULL;
        }
    }

    SETIOV(&ctp->iov[0], &msg->o,
        sizeof(msg->o) + sizeof(SharedRegionDrv_CmdArgs));
    SETIOV(&ctp->iov[1], region,
        (sizeof(SharedRegion_Region) * config.numEntries));

    return(_RESMGR_NPARTS(2));  /* config.numEntries */
}
/*!
 *  @brief  Function to invoke the APIs through ioctl.
 *
 *  @param  cmd     Command for driver ioctl
 *  @param  args    Arguments for the ioctl command
 *
 *  @sa
 */
Int
SharedRegionDrv_ioctl (UInt32 cmd, Ptr args)
{
    Int                       status   = SharedRegion_S_SUCCESS;
    int                       osStatus = -1;
    SharedRegionDrv_CmdArgs * cargs    = (SharedRegionDrv_CmdArgs *) args;
    SharedRegion_Region    *  regions  = NULL;
    SharedRegion_Config *     config;
    Memory_MapInfo            mapInfo;
    UInt16                    i;

    GT_2trace (curTrace, GT_ENTER, "SharedRegionDrv_ioctl", cmd, args);

/*  TODO: SharedRegionDrv_refCount not defined in QNX build
 *  GT_assert (curTrace, (SharedRegionDrv_refCount > 0));
 */

    switch (cmd) {

        case CMD_SHAREDREGION_GETCONFIG:
        {
			SharedRegionDrv_CmdArgs *cargs = (SharedRegionDrv_CmdArgs *)args;
			iov_t sharedregion_getconfig_iov[2];
			SharedRegion_Config * shreg_config = cargs->args.getConfig.config;

			SETIOV( &sharedregion_getconfig_iov[0], cargs, sizeof(SharedRegionDrv_CmdArgs) );
			SETIOV( &sharedregion_getconfig_iov[1], cargs->args.getConfig.config, sizeof(SharedRegion_Config) );

			/* the osal_drv handle is used instead of ipcdrv_handle as the ipcdrc_handle is not yet initialized */
			osStatus = devctlv( OsalDrv_handle, DCMD_SHAREDREGION_GETCONFIG, 1, 2, sharedregion_getconfig_iov, sharedregion_getconfig_iov, NULL);

			if ( osStatus == 0 ){
				cargs->args.getConfig.config = shreg_config;
			}
        }
        break;

        case CMD_SHAREDREGION_SETUP:
        {
			SharedRegionDrv_CmdArgs *cargs = (SharedRegionDrv_CmdArgs *)args;
			iov_t sharedregion_setup_iov[3];

			SETIOV( &sharedregion_setup_iov[0], cargs, sizeof(SharedRegionDrv_CmdArgs) );
			SETIOV( &sharedregion_setup_iov[1], cargs->args.setup.config, sizeof(SharedRegion_Config) );
			SETIOV( &sharedregion_setup_iov[2], cargs->args.setup.regions, cargs->args.setup.config->numEntries * sizeof(SharedRegion_Region) );

			osStatus = devctlv( IpcDrv_handle, DCMD_SHAREDREGION_SETUP, 2, 3, sharedregion_setup_iov, sharedregion_setup_iov, NULL);
        }
        break;


        case CMD_SHAREDREGION_GETREGIONINFO:
        {
			SharedRegionDrv_CmdArgs *cargs = (SharedRegionDrv_CmdArgs *)args;
			iov_t sharedregion_getregconfig_iov[2];	/* no of max shared region entries + 1 */
            //UInt16              i=0;
            SharedRegion_Config   config;

            SharedRegion_getConfig (&config);
			SETIOV( &sharedregion_getregconfig_iov[0], cargs, sizeof(SharedRegionDrv_CmdArgs) );
			SETIOV( &sharedregion_getregconfig_iov[1], cargs->args.getRegionInfo.regions, (sizeof(SharedRegion_Region) * config.numEntries));

			//for (i = 1; i< cargs->args.getConfig.config->numEntries+1;i++) {
			//	SETIOV( &sharedregion_getregconfig_iov[i], &cargs->args.setup.regions[i-1], sizeof(SharedRegion_Region) );
			//}

//			SETIOV( &sharedregion_getregconfig_iov[1], cargs->args.setup.regions, (sizeof(SharedRegion_Region) * cargs->args.getConfig.config->numEntries));

			//osStatus = devctlv( IpcDrv_handle, DCMD_SHAREDREGION_GETREGIONINFO, 1, cargs->args.getConfig.config->numEntries + 1, sharedregion_getregconfig_iov, sharedregion_getregconfig_iov, NULL);
			osStatus = devctlv( IpcDrv_handle, DCMD_SHAREDREGION_GETREGIONINFO, 2, 2, sharedregion_getregconfig_iov, sharedregion_getregconfig_iov, NULL);
        }
        break;

        case CMD_SHAREDREGION_DESTROY:
        {
			osStatus = devctl( IpcDrv_handle, DCMD_SHAREDREGION_DESTROY, cargs, sizeof(SharedRegionDrv_CmdArgs), NULL);
        }
        break;

        case CMD_SHAREDREGION_START:
        {
			osStatus = devctl( IpcDrv_handle, DCMD_SHAREDREGION_START, cargs, sizeof(SharedRegionDrv_CmdArgs), NULL);
        }
        break;

        case CMD_SHAREDREGION_STOP:
        {
			osStatus = devctl( IpcDrv_handle, DCMD_SHAREDREGION_STOP, cargs, sizeof(SharedRegionDrv_CmdArgs), NULL);
        }
        break;

        case CMD_SHAREDREGION_ATTACH:
        {
			osStatus = devctl( IpcDrv_handle, DCMD_SHAREDREGION_ATTACH, cargs, sizeof(SharedRegionDrv_CmdArgs), NULL);
        }
        break;

        case CMD_SHAREDREGION_DETACH:
        {
			osStatus = devctl( IpcDrv_handle, DCMD_SHAREDREGION_DETACH, cargs, sizeof(SharedRegionDrv_CmdArgs), NULL);
        }
        break;

        case CMD_SHAREDREGION_SETENTRY:
        {

			SharedRegionDrv_CmdArgs *cargs = (SharedRegionDrv_CmdArgs *)args;

			iov_t sharedregion_getregsetentry_iov[2];

			SETIOV( &sharedregion_getregsetentry_iov[0], cargs, sizeof(SharedRegionDrv_CmdArgs) );
			SETIOV( &sharedregion_getregsetentry_iov[1], &cargs->args.setEntry.entry, sizeof(SharedRegion_Entry) );

			osStatus = devctlv( IpcDrv_handle, DCMD_SHAREDREGION_SETENTRY, 2, 1, sharedregion_getregsetentry_iov, sharedregion_getregsetentry_iov, NULL);
		}
        break;

        case CMD_SHAREDREGION_CLEARENTRY:
        {
			osStatus = devctl( IpcDrv_handle, DCMD_SHAREDREGION_CLEARENTRY, cargs, sizeof(SharedRegionDrv_CmdArgs), NULL);
        }
        break;

        case CMD_SHAREDREGION_GETHEAP:
        {

			osStatus = devctl( IpcDrv_handle, DCMD_SHAREDREGION_GETHEAP, cargs, sizeof(SharedRegionDrv_CmdArgs), NULL);
        }
        break;

        case CMD_SHAREDREGION_RESERVEMEMORY:
        {
			osStatus = devctl( IpcDrv_handle, DCMD_SHAREDREGION_RESERVEMEMORY, cargs, sizeof(SharedRegionDrv_CmdArgs), NULL);
        }
        break;

        case CMD_SHAREDREGION_CLEARRESERVEDMEMORY:
        {
			osStatus = devctl( IpcDrv_handle, DCMD_SHAREDREGION_CLEARRESERVEDMEMORY, cargs, sizeof(SharedRegionDrv_CmdArgs), NULL);
        }
        break;

        default:
        {
            /* This does not impact return status of this function, so retVal
             * comment is not used.
             */
            status = SharedRegion_E_INVALIDARG;
            GT_setFailureReason (curTrace,
                                 GT_4CLASS,
                                 "SharedRegionDrv_ioctl",
                                 status,
                                 "Unsupported ioctl command specified");
        }
        break;
    }

    if (osStatus != 0) {
        /*! @retval SharedRegion_E_OSFAILURE Driver ioctl failed */
        status = SharedRegion_E_OSFAILURE;
        GT_setFailureReason (curTrace,
                             GT_4CLASS,
                             "SharedRegionDrv_ioctl",
                             status,
                             "Driver ioctl failed!");
    }
    else {
        /* First field in the structure is the API status. */
        status = ((SharedRegionDrv_CmdArgs *) cargs)->apiStatus;

        /* Convert the base address to user virtual address */
        if (cmd == CMD_SHAREDREGION_SETUP) {
            config = cargs->args.setup.config;
            for (i = 0u; (   (i < config->numEntries) && (status >= 0)); i++) {
                regions = &(cargs->args.setup.regions [i]);
                if (regions->entry.isValid == TRUE) {
                    mapInfo.src  = (UInt32) regions->entry.base;
                    mapInfo.size = regions->entry.len;
                    status = Memory_map (&mapInfo);
                    if (status < 0) {
                        GT_setFailureReason (curTrace,
                                             GT_4CLASS,
                                             "SharedRegionDrv_ioctl",
                                             status,
                                             "Memory_map failed!");
                    }
                    else {
                        regions->entry.base = (Ptr) mapInfo.dst;
                    }
                }
            }
        }
        else {
            /* TBD: Need to do Memory_unmap in destroy. */
        }
    }

    GT_1trace (curTrace, GT_LEAVE, "SharedRegionDrv_ioctl", status);

/*! @retval SharedRegion_S_SUCCESS Operation successfully completed. */
    return status;
}
/*!
 *  @brief      Function to get tyhe default values for confiurations.
 *
 *  @param      config   Configuration values.
 */
Void
Ipc_getConfig (Ipc_Config * config)
{
    GT_1trace (curTrace, GT_ENTER, "Ipc_getConfig", config);

    GT_assert (curTrace, (config != NULL));

#if !defined(SYSLINK_BUILD_OPTIMIZE)
    if (config == NULL) {
        GT_setFailureReason (curTrace,
                             GT_4CLASS,
                             "Ipc_getConfig",
                             Ipc_E_INVALIDARG,
                             "Argument of type (Ipc_getConfig *) passed "
                             "is null!");
    }
    else {
#endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
        /* Initialize Utils as the get config functions expects
         * this module to be initialized
         */
        UsrUtilsDrv_setup();

#if 0 /* TBD:Temporarily comment. */
        /* Get the SysMemMgr default config */
        SysMemMgr_getConfig (&config->sysMemMgrConfig);
#endif /* TBD: Temporarily comment. */

        /* Get the MultiProc default config */
        MultiProc_getConfig (&config->multiProcConfig);

        /* Get the SharedRegion default config */
        SharedRegion_getConfig (&config->sharedRegionConfig);

        /* Get the GateMP default config */
        GateMP_getConfig (&config->gateMPConfig);

        /* Get the MESSAGEQ default config */
        MessageQ_getConfig (&config->messageQConfig);

        /* Get the NOTIFY default config */
        Notify_getConfig (&config->notifyConfig);

        /* Get the PROCMGR default config */
        ProcMgr_getConfig (&config->procMgrConfig);

        /* Get the HeapBufMP default config */
        HeapBufMP_getConfig (&config->heapBufMPConfig);

        /* Get the HeapMemMP default config */
        HeapMemMP_getConfig (&config->heapMemMPConfig);

        /* Get the LISTMP default config */
        ListMP_getConfig (&config->listMPConfig);

#if 0 /* TBD:Temporarily comment. */
        /* Get the HeapMultiBuf default config */
        HeapMultiBuf_getConfig (&config->heapMultiBufConfig);

        /* Get the ClientNotifyMgr default config */
        ClientNotifyMgr_getConfig (&config->cliNotifyMgrCfgParams) ;

        /*  Get the FrameQBufMgr default config */
        FrameQBufMgr_getConfig (&config->frameQBufMgrCfgParams) ;

        /*  Get the FrameQ default config */
        FrameQ_getConfig (&config->frameQCfgParams) ;
#endif /* TBD: Temporarily comment. */

        UsrUtilsDrv_destroy();

#if !defined(SYSLINK_BUILD_OPTIMIZE)
    }
#endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */

    GT_0trace (curTrace, GT_LEAVE, "Ipc_getConfig");
}