/*
 * Copyright 2004 Freescale Semiconductor, Inc. All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

/*!
 * @defgroup IPC InterProcessor Communication (IPC)
 */

/*!
 * @file mxc_ipc.h
 *
 * @brief This file contains the IPC API configuration details and
 * public API declarations.
 *
 * @ingroup IPC
 */
#ifndef MXC_IPC_H
#define MXC_IPC_H

/*!
 * This enum defines the different status of an IPC link
 */
typedef enum{
        HW_CTRL_IPC_STATUS_OK = 0,
        HW_CTRL_IPC_STATUS_CHANNEL_ALREADY_OPEN,
        HW_CTRL_IPC_STATUS_CHANNEL_UNAVAILABLE,
        HW_CTRL_IPC_STATUS_IPC_SUSPENDED,
        HW_CTRL_IPC_STATUS_READ_ON_GOING,
        HW_CTRL_IPC_STATUS_WRITE_ON_GOING,
        HW_CTRL_IPC_STATUS_INIT_ALREADY_CALLED,
        HW_CTRL_IPC_STATUS_ERROR
}HW_CTRL_IPC_STATUS_T;

/*!
 * This typedef defines the ioctls available
 * for kernel modules using IPC. 
 */
typedef enum{
        HW_CTRL_IPC_SET_READ_CALLBACK = 0,
        HW_CTRL_IPC_SET_WRITE_CALLBACK,
        HW_CTRL_IPC_SET_NOTIFY_CALLBACK
}HW_CTRL_IPC_IOCTL_ACTION_T;

/*!
 * Definition of IPC channel types
 *
 * There are currently three types of channels:
 *
 * - Short Message channels. Used to transfer 32-bits
 *   messages from MCU to DSP and vice versa
 *
 * - Packet Data channels. Useful to transfer data between
 *   the two cores.
 *
 * - Logging channel. This type of channel is read-only from
 *   the MCU. It is used to report log events to the MCU.
 *   
 */
typedef enum{
        HW_CTRL_IPC_PACKET_DATA = 0,
        HW_CTRL_IPC_CHANNEL_LOG,
        HW_CTRL_IPC_SHORT_MSG
}HW_CTRL_IPC_CHANNEL_TYPE_T;

/*!
 * This enum defines the write modes IPC can support.
 *
 * - Contigous mode: All data is stored in a contigous
 *   memory zone.
 *
 * - LinkedList mode: Data can be presented in chunks of 
 *   non-contiguous memory. Up to 11 chunks can be processed
 *   by this mode.
 *
 *  Note that only Packet Data channels can support LinkedList mode.
 */
typedef enum{
        HW_CTRL_IPC_MODE_CONTIGUOUS = 0,
        HW_CTRL_IPC_MODE_LINKED_LIST
}HW_CTRL_IPC_MODE_T;

typedef struct{
}HW_CTRL_IPC_INIT_T;

/*!
 * A structure of this type is passed as parameter when a read
 * callback is invoked. This normally happens when a read transfer has been
 * completed.
 */
typedef struct{
        /*!
         * the channel from which data was read
         */
        int channel_nb;
        
        /*!
         * number of bytes read.
         */
        int nb_bytes;
}HW_CTRL_IPC_READ_STATUS_T;

/*!
 * A structure of this type is passed as parameter when a write
 * callback is invoked. This normally happens when a write transfer has been
 * completed.
 */
#define HW_CTRL_IPC_WRITE_STATUS_T     HW_CTRL_IPC_READ_STATUS_T

/*!
 * A structure of this type is passed as parameter when a notify
 * callback is invoked. This happens only when a transfer has been 
 * abnormally terminated.
 */
typedef struct{
        /*!
         * number of channel where transfer has failed
         */
        int channel_nb;
        
        /*!
         * status code
         */
        HW_CTRL_IPC_STATUS_T status;
}HW_CTRL_IPC_NOTIFY_STATUS_T;

/*
 * This struct defines parameters needed to 
 * execute a write using the linked list mode
 */
typedef struct HW_CTRL_IPC_LINKED_LIST_T{
	/*!
	 * pointer to data to be transfered
	 */
        unsigned char* data_ptr;
        
        /*!
         * Lenght of data
         */
        unsigned int  length;
        
        /*!
         * Pointer to the next chunk of memory containing data
         * to be transferred
         */
        struct HW_CTRL_IPC_LINKED_LIST_T* next;
}HW_CTRL_IPC_LINKED_LIST_T;

/*
 * This struct defines parameters needed to 
 * execute a write using the normal mode
 */
typedef struct{
	/*!
	 * pointer to data to be transfered
	 */
        unsigned char* data_ptr;
        
        /*!
         * Lenght of data
         */
        unsigned int  length;
}HW_CTRL_IPC_CONTIGUOUS_T;

/*
 * This structure is used by the write_ex function
 * which is in charge of execute the LinkedList mode
 * transfer.
 */
typedef struct{
	/*!
	 * Type of transfer to execute
	 */
        HW_CTRL_IPC_MODE_T ipc_memory_read_mode;
        
        /*!
         * Pointer to a buffer holding all data to
         * transfer orpointer to a buffer holding
         * first chunk of data to transfer
         */
        union{
                HW_CTRL_IPC_CONTIGUOUS_T* cont_ptr;
                HW_CTRL_IPC_LINKED_LIST_T* list_ptr;
        }read;
}HW_CTRL_IPC_WRITE_PARAMS_T;

/*
 * Structure used to pass configuration parameters needed
 * to open an IPC channel.
 */
typedef struct{
	/*!
	 * type of IPC channel to open
	 */
        HW_CTRL_IPC_CHANNEL_TYPE_T type;
        
        /*!
         * index defining the physical channel
         * that will be used for this IPC channel
         */
        int index;
        
        /*!
         * read callback provided by the user, called when a read 
         * transfer has been finished
         */
        void (*read_callback) (HW_CTRL_IPC_READ_STATUS_T *status);
        
        /*!
         * write callback provided by the user, called when a write 
         * transfer has been finished
         */
        void (*write_callback)(HW_CTRL_IPC_WRITE_STATUS_T *status);
        
        /*!
         * notify callback provided by the user, called when an error 
         * occurs during a transfer.
         */
        void (*notify_callback)(HW_CTRL_IPC_NOTIFY_STATUS_T *status);
} HW_CTRL_IPC_OPEN_T;

/*!
 * This function is called when kernel is loading the module. 
 * It initializes all low-level resources needed by the POSIX
 * layer in order to make SDMA/MU transfers.
 * 
 * @param init_params	Pointer to a struct containing global 
 * 			initialization parameters.
 *
 * @return		returns HW_CTRL_IPC_STATUS_OK on success, an error code
 *			otherwise.
 */
HW_CTRL_IPC_STATUS_T hw_ctrl_ipc_init(const HW_CTRL_IPC_INIT_T* init_params);

/*!
 * Opens an IPC link. This functions can be called directly by kernel
 * modules. POSIX implementation of the IPC Driver also calls it.
 * 
 * @param channel_nb	virtual channel requested. It can go from 0 to 31
 * @param config	Pointer to a struct containing configuration para
 * 			meters for the channel to open (type of channel, 
 *			callbacks, etc) 
 *
 * @return		returns HW_CTRL_IPC_STATUS_OK on success, an error code
 *			otherwise.
 */
HW_CTRL_IPC_STATUS_T hw_ctrl_ipc_open(unsigned short channel_nb, 
                                         const HW_CTRL_IPC_OPEN_T* config);

/*!
 * Close an IPC link. This functions can be called directly by kernel
 * modules. POSIX implementation of the IPC Driver also calls it.
 * 
 * @param channel_nb	virtual channel to close. It can go from 0 to 31
 *
 * @return		returns HW_CTRL_IPC_STATUS_OK on success, an error code
 *			otherwise.
 */
HW_CTRL_IPC_STATUS_T hw_ctrl_ipc_close(unsigned short channel_nb);

/*!
 * Reads data from an IPC link. This functions can be called directly by kernel
 * modules. POSIX implementation of the IPC Driver also calls it.
 * 
 * @param channel_nb	virtual channel where read has been requested. It can go from 0 to 31
 * @param buf		buffer to store data read from the channel.
 * @param buffer_size	size of the buffer
 *
 * @return		returns HW_CTRL_IPC_STATUS_OK on success, an error code
 *			otherwise.
 */
HW_CTRL_IPC_STATUS_T hw_ctrl_ipc_read(unsigned short channel_nb, 
                                        unsigned char* buf, 
                                        unsigned short buffer_size);

/*!
 * Writes data to an IPC link. This functions can be called directly by kernel
 * modules. POSIX implementation of the IPC Driver also calls it.
 * 
 * @param channel_nb	virtual channel where read has been requested. It can go from 0 to 31
 * @param buf		buffer containing data t be written on the channel.
 * @param buffer_size	size of the buffer
 *
 * @return		returns HW_CTRL_IPC_STATUS_OK on success, an error code
 *			otherwise.
 */
HW_CTRL_IPC_STATUS_T hw_ctrl_ipc_write(unsigned short channel_nb, 
                                         unsigned char* buf,
                                         unsigned short nb_bytes);

/*!
 * Executes custom actions on the IPC links. This functions can be called directly by kernel
 * modules. POSIX implementation of the IPC Driver also calls it.
 * 
 * @param action	Action (command) to execute
 * @param param		Parameter specific to the action requested. 
 *
 * @return		returns HW_CTRL_IPC_STATUS_OK on success, an error code
 *			otherwise.
 */
HW_CTRL_IPC_STATUS_T hw_ctrl_ipc_ioctl(HW_CTRL_IPC_IOCTL_ACTION_T action,
                                         void* param);
#endif //MXC_IPC_H
