#ifndef __SEP_DRIVER_API_H__
#define __SEP_DRIVER_API_H__



/*----------------------------------------------------------------
  IOCTL command defines
  -----------------------------------------------------------------*/

/* magic number 1 of the sep IOCTL command */
#define SEP_IOC_MAGIC_NUMBER                           's'

/* sends interrupt to sep that message is ready */
#define SEP_IOCSENDSEPCOMMAND                          _IO(SEP_IOC_MAGIC_NUMBER , 0)

/* sends interrupt to sep that message is ready */
#define SEP_IOCSENDSEPRPLYCOMMAND                      _IO(SEP_IOC_MAGIC_NUMBER , 1)

/* allocate memory in data pool */
#define SEP_IOCALLOCDATAPOLL                          _IO(SEP_IOC_MAGIC_NUMBER , 2)

/* write to pre-allocated  memory in data pool */
#define SEP_IOCWRITEDATAPOLL                          _IO(SEP_IOC_MAGIC_NUMBER , 3)

/* read from  pre-allocated  memory in data pool */
#define SEP_IOCREADDATAPOLL                           _IO(SEP_IOC_MAGIC_NUMBER , 4)

/* create sym dma lli tables */
#define SEP_IOCCREATESYMDMATABLE                      _IO(SEP_IOC_MAGIC_NUMBER , 5)

/* create flow dma lli tables */
#define SEP_IOCCREATEFLOWDMATABLE                     _IO(SEP_IOC_MAGIC_NUMBER , 6)

/* free dynamic data aalocated during table creation */
#define SEP_IOCFREEDMATABLEDATA                       _IO(SEP_IOC_MAGIC_NUMBER , 7)

/* get the static pool area addersses (physical and virtual) */
#define SEP_IOCGETSTATICPOOLADDR                      _IO(SEP_IOC_MAGIC_NUMBER , 8)

/* set flow id command */
#define SEP_IOCSETFLOWID                              _IO(SEP_IOC_MAGIC_NUMBER , 9)

/* add tables to the dynamic flow */
#define SEP_IOCADDFLOWTABLE                           _IO(SEP_IOC_MAGIC_NUMBER , 10)

/* add flow add tables message */
#define SEP_IOCADDFLOWMESSAGE                         _IO(SEP_IOC_MAGIC_NUMBER , 11)

/* start sep command */
#define SEP_IOCSEPSTART                               _IO(SEP_IOC_MAGIC_NUMBER , 12)

/* init sep command */
#define SEP_IOCSEPINIT                                _IO(SEP_IOC_MAGIC_NUMBER , 13)

/* set non blocking mode */
#define SEP_IOCSETAPIMODE                             _IO(SEP_IOC_MAGIC_NUMBER , 14)  

/* end transaction command */
#define SEP_IOCENDTRANSACTION                         _IO(SEP_IOC_MAGIC_NUMBER , 15)

/* reallocate cache and resident */
#define SEP_IOCREALLOCCACHERES                        _IO(SEP_IOC_MAGIC_NUMBER , 16)

/* get the offset of the address starting from the beginnnig of the map area */
#define SEP_IOCGETMAPPEDADDROFFSET                    _IO(SEP_IOC_MAGIC_NUMBER , 17)

/* reallocate cache and resident */
#define SEP_IOCREALLOCEXTCACHE                        _IO(SEP_IOC_MAGIC_NUMBER , 18)

/* get time address and value */
#define SEP_IOCGETIME                                 _IO(SEP_IOC_MAGIC_NUMBER , 19)


#define SEP_IOCTLSINGLETONLOCK                        _IO(SEP_IOC_MAGIC_NUMBER , 32)

#define SEP_IOCTLSETCALLERID                          _IO(SEP_IOC_MAGIC_NUMBER , 33)

/*-------------------------------------------
    TYPEDEFS
----------------------------------------------*/

/*
  init command struct 
*/
typedef struct _sep_driver_init_t
{
  /* start of the 1G of the host memory address that SEP can access */
  unsigned long   message_addr;
  
  /* start address of resident */
  unsigned long   message_size_in_words;
  
  /* offset of the init message in the sep sram */
  unsigned long   sep_sram_addr;
  
}sep_driver_init_t;


/*
  realloc cache resident command 
*/
typedef struct _sep_driver_realloc_cache_resident_t
{
  /* base address */
  unsigned long   base_addr;
  
  /* current cache address */
  unsigned long   cache_addr;
  
  /* cache size in bytes*/
  unsigned long   cache_size_in_bytes;
  
  /* current resident address */
  unsigned long   resident_addr;
  
  /* resident size in bytes*/
  unsigned long   resident_size_in_bytes;
  
  /* current dcache address */
  unsigned long   dcache_addr;
  
  /* dcache size in bytes*/
  unsigned long   dcache_size_in_bytes;
  
  /* ext cache current address */
  unsigned long   extcache_addr;
      
  /* ext cache size in bytes*/
  unsigned long   extcache_size_in_bytes;
  
  /* new cache address */
  unsigned long   new_cache_addr;
  
  /* new resident address */
  unsigned long   new_resident_addr;
  
  /* new dcache address */
  unsigned long   new_dcache_addr;
  
  /* new resident address */
  unsigned long   new_shared_area_addr;
  
  /* new base address */
  unsigned long   new_base_addr;
  
}sep_driver_realloc_cache_resident_t;

typedef struct _sep_driver_realloc_ext_cache_t
{
  /* current external cache address */
  unsigned long   ext_cache_addr;
  
  /* external cache size in bytes*/
  unsigned long   ext_cache_size_in_bytes;
  
  /* new external cache address */
  unsigned long   new_ext_cache_addr;
  
}sep_driver_realloc_ext_cache_t;

/*
  set api mode command struct
*/
typedef struct _sep_driver_set_api_mode_t
{
  /* mode to set - 1 - blocking, 0 - non-blocking */
  unsigned long   mode;
  
}sep_driver_set_api_mode_t;

/*
 */
typedef struct _sep_driver_alloc_t
{
  /* virtual address of allocated space */
  unsigned long offset;

  /* physical address of allocated space */
  unsigned long phys_address;

  /* number of bytes to allocate */
  unsigned long num_bytes;
}sep_driver_alloc_t;

/* 
 */
typedef struct _sep_driver_write_t
{
  /* application space address */
  unsigned long app_address;

  /* address of the data pool */
  unsigned long datapool_address;

  /* number of bytes to write */
  unsigned long num_bytes;
}sep_driver_write_t;

/*
 */
typedef struct _sep_driver_read_t
{
  /* application space address */
  unsigned long app_address;

  /* address of the data pool */
  unsigned long datapool_address;

  /* number of bytes to read */
  unsigned long num_bytes;
}sep_driver_read_t;

/*
*/
typedef struct _sep_driver_build_sync_table_t
{
  /* address value of the data in */ 
  unsigned long  app_in_address;
      
  /* size of data in */
  unsigned long  data_in_size;
      
  /* address of the data out */
  unsigned long  app_out_address;
      
  /* the size of the block of the operation - if needed, every table will be modulo this parameter */
  unsigned long  block_size;
      
  /* the physical address of the first input DMA table */
  unsigned long  in_table_address;
      
  /* number of entries in the first input DMA table */
  unsigned long  in_table_num_entries;
  
  /* the physical address of the first output DMA table */
  unsigned long  out_table_address;
  
  /* number of entries in the first output DMA table */
  unsigned long  out_table_num_entries;
      
  /* data in the first input table */
  unsigned long  table_data_size;
  
}sep_driver_build_sync_table_t;

/*
*/
typedef struct _sep_driver_build_flow_table_t
{
  /* flow type */
  unsigned long  flow_type;
  
  /* flag for input output */
  unsigned long  input_output_flag;
      
  /* address value of the data in */ 
  unsigned long  virt_buff_data_addr;
      
  /* size of data in */
  unsigned long  num_virtual_buffers;
      
  /* the physical address of the first input DMA table */
  unsigned long  first_table_addr;
      
  /* number of entries in the first input DMA table */
  unsigned long  first_table_num_entries;
      
  /* data in the first input table */
  unsigned long  first_table_data_size;
  
}sep_driver_build_flow_table_t;

/* 
*/
typedef struct _sep_driver_add_flow_table_t
{
  /* flow id  */
  unsigned long  flow_id;
      
  /* flag for input output */
  unsigned long  inputOutputFlag;
      
  /* address value of the data in */ 
  unsigned long  virt_buff_data_addr;
      
  /* size of data in */
  unsigned long  num_virtual_buffers;
      
  /* address of the first table */
  unsigned long  first_table_addr;
      
  /* number of entries in the first table */
  unsigned long  first_table_num_entries;
      
  /* data size of the first table */
  unsigned long  first_table_data_size;
      
}sep_driver_add_flow_table_t;

/* 
  command struct for set flow id 
*/
typedef struct _sep_driver_set_flow_id_t
{
  /* flow id to set */
  unsigned long  flow_id;
  
}sep_driver_set_flow_id_t;


/* command struct for add tables message  */
typedef struct _sep_driver_add_message_t
{
  /* flow id to set */
  unsigned long   flow_id;
  
  /* message size in bytes */
  unsigned long   message_size_in_bytes;
  
  /* address of the message */
  unsigned long   message_address;
  
}sep_driver_add_message_t;

/* command struct for static pool addresses  */
typedef struct _sep_driver_static_pool_addr_t
{
  /* physical address of the static pool */
  unsigned long   physical_static_address;

  /* virtual address of the static pool */
  unsigned long   virtual_static_address;
  
}sep_driver_static_pool_addr_t;

/* command struct for getting offset of the physical address from the start of the mapped area  */
typedef struct _sep_driver_get_mapped_offset_t
{
  /* physical address of the static pool */
  unsigned long   physical_address;

  /* virtual address of the static pool */
  unsigned long   offset;
  
}sep_driver_get_mapped_offset_t;

/* command struct for getting time value and address */
typedef struct _sep_driver_get_time_t
{
  /* physical address of stored time */
  unsigned long   time_physical_address;

  /* value of the stored time */
  unsigned long   time_value;
  
}sep_driver_get_time_t;

/* command struct for getting time value and address */
typedef struct _sep_driver_set_caller_id_t
{
  /* pid of the process */
  unsigned long   pid;

  /* virtual address of the caller id hash */
  unsigned long   callerIdAddress;
  
  /* caller id hash size in bytes */
  unsigned long   callerIdSizeInBytes;
  
}sep_driver_set_caller_id_t;


/* 
  structure that represent one entry in the DMA LLI table
*/
typedef struct _sep_lli_entry_t
{
  /* physical address */
  unsigned long  physical_address;
  
  /* block size */
  unsigned long  block_size;
  
}sep_lli_entry_t;

/*
  structure that reperesents data needed for lli table construction
*/
typedef struct _sep_lli_prepare_table_data_t
{
  /* pointer to the memory where the first lli entry to be built */
  sep_lli_entry_t*  lli_entry_ptr;
  
  /* pointer to the array of lli entries from which the table is to be built */
  sep_lli_entry_t*  lli_array_ptr;
  
  /* number of elements in lli array */
  int               lli_array_size;
  
  /* number of entries in the created table */
  int               num_table_entries;
  
  /* number of array entries processed during table creation */ 
  int               num_array_entries_processed; 
  
  /* the totatl data size in the created table */
  int               lli_table_total_data_size;   

}sep_lli_prepare_table_data_t;

/* 
  structure that represent tone table - it is not used in code, jkust to show what table looks like
*/
typedef struct _sep_lli_table_t
{
  /* number of pages mapped in this tables. If 0 -  means that the table is not defined (used as a valid flag)*/
  unsigned long num_pages;
  /* 
    pointer to array of page pointers that represent the mapping of the virtual buffer defined by the table to the 
    physical memory. If this pointer is NULL, it means that the table is not defined (used as a valid flag)
  */
  struct page**  table_page_array_ptr;
  
  /* maximum flow entries in table */
  sep_lli_entry_t lli_entries[SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE];
  
}sep_lli_table_t;


typedef struct _sep_caller_id_entry
{
  int pid;
  
  unsigned char callerIdHash[SEP_CALLER_ID_HASH_SIZE_IN_BYTES];
  
}sep_caller_id_entry;


/* 
  structure for keeping the mapping of the virtual buffer into physical pages 
*/
typedef struct _sep_flow_buffer_data
{
  /* pointer to the array of page structs pointers to the pages of the virtual buffer */
  struct page**   page_array_ptr;
  
  /* number of pages taken by the virtual buffer */
  unsigned long   num_pages;
  
  /* this flag signals if this page_array is the last one among many that were sent in one setting to SEP */
  unsigned long   last_page_array_flag;
  
}sep_flow_buffer_data;

/*
  struct that keeps all the data for one flow
*/
typedef struct _sep_flow_context_t
{
  /* 
     work struct for handling the flow done interrupt in the workqueue
     this structure must be in the first place, since it will be used forcasting to the containing flow context
  */
  struct work_struct      flow_wq;

  /* flow id */
  unsigned long           flow_id;
  
  /* additional input tables exists */
  unsigned long           input_tables_flag;
  
  /* additional output tables exists */
  unsigned long           output_tables_flag;
  
  /*  data of the first input file */
  sep_lli_entry_t         first_input_table;
  
  /* data of the first output table */
  sep_lli_entry_t         first_output_table;
  
  /* last input table data */
  sep_lli_entry_t         last_input_table;
  
  /* last output table data */
  sep_lli_entry_t         last_output_table;
  
  /* first list of table */
  sep_lli_entry_t         input_tables_in_process;
  
  /* output table in process (in sep) */
  sep_lli_entry_t         output_tables_in_process;
  
  /* size of messages in bytes */
  unsigned long           message_size_in_bytes;
  
  /* message */
  unsigned char           message[SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES];
  
}sep_flow_context_t;



/*
  this function locks SEP by locking the semaphore
*/
int sep_lock(void);

/*
  this function unlocks SEP
*/
void sep_unlock(void);

/* 
  this function returns the address of the message shared area 
*/
void sep_map_shared_area(unsigned long* mappedAddr_ptr);


/* 
  this function returns the address of the message shared area 
*/
void sep_send_msg_rdy_cmd(void);


/*
  This function locks all the physical pages of the application virtual buffer
  and construct a basic lli  array, where each entry holds the physical page address and the size that application data
  holds in this physical pages
*/
int sep_lock_user_pages(unsigned long       app_virt_addr,
                        unsigned long       data_size,
                        unsigned long*      num_pages_ptr,
                        sep_lli_entry_t**   lli_array_ptr,
                        struct page***      page_array_ptr);
                        
/*
  This function releases all the application virtual buffer physical pages, that were previously locked
*/
int sep_free_dma_pages(struct page** page_array_ptr,
                       unsigned long num_pages,
                       unsigned long dirtyFlag);

/* 
 This function creates the input and output dma tables for symmetric operations (AES/DES) according to the block size from LLI arays 
*/
int sep_construct_dma_tables_from_lli(sep_lli_entry_t* lli_in_array,
                                      unsigned long     sep_in_lli_entries,
                                      sep_lli_entry_t* lli_out_array,
                                      unsigned long     sep_out_lli_entries,
                                      unsigned long     block_size,
                                      unsigned long*    lli_table_in_ptr,
                                      unsigned long*    lli_table_out_ptr,
                                      unsigned long*    in_num_entries_ptr,
                                      unsigned long*    out_num_entries_ptr,
                                      unsigned long*    table_data_size_ptr);

/* this functions frees all the resources that were allocated for the building of the LLI DMA tables */                                      
void sep_free_dma_resources(void);


/* poll(suspend) , until reply from sep */
void sep_driver_poll(void);



#endif
