diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 979de8fb32cd..2860bd5704fc 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -135,5 +135,7 @@ source "drivers/staging/hv/Kconfig"
 
 source "drivers/staging/vme/Kconfig"
 
+source "drivers/staging/sep/Kconfig"
+
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index c80d05006dc6..ce6523c02f98 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_USB_CPC)		+= cpc-usb/
 obj-$(CONFIG_FB_UDL)		+= udlfb/
 obj-$(CONFIG_HYPERV)		+= hv/
 obj-$(CONFIG_VME_BUS)		+= vme/
+obj-$(CONFIG_DX_SEP)		+= sep/
diff --git a/drivers/staging/sep/Kconfig b/drivers/staging/sep/Kconfig
new file mode 100644
index 000000000000..1a4514d3a7ac
--- /dev/null
+++ b/drivers/staging/sep/Kconfig
@@ -0,0 +1,9 @@
+config DX_SEP
+	tristate "Discretix SEP driver"
+	depends on MRST
+	default y
+	help
+	  Discretix SEP driver
+
+	  If unsure say M. The compiled module will be
+	  called sep_driver.ko
diff --git a/drivers/staging/sep/Makefile b/drivers/staging/sep/Makefile
new file mode 100644
index 000000000000..e2528e80e284
--- /dev/null
+++ b/drivers/staging/sep/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS += -DLITTLE__ENDIAN -DDX_CC5_SEP_PLAT -DCRYS_NO_EXT_IF_MODE_SUPPORT
+obj-$(CONFIG_DX_SEP) := sep_driver.o
+sep_driver-objs := sep_main_mod.o sep_ext_with_pci_driver.o
diff --git a/drivers/staging/sep/TODO b/drivers/staging/sep/TODO
new file mode 100644
index 000000000000..ff0e931dab64
--- /dev/null
+++ b/drivers/staging/sep/TODO
@@ -0,0 +1,8 @@
+Todo's so far (from Alan Cox)
+- Fix firmware loading
+- Get firmware into firmware git tree
+- Review and tidy each algorithm function
+- Check whether it can be plugged into any of the kernel crypto API
+  interfaces
+- Do something about the magic shared memory interface and replace it
+  with something saner (in Linux terms)
diff --git a/drivers/staging/sep/sep_driver_api.h b/drivers/staging/sep/sep_driver_api.h
new file mode 100644
index 000000000000..6a3be5dbfffd
--- /dev/null
+++ b/drivers/staging/sep/sep_driver_api.h
@@ -0,0 +1,545 @@
+/*
+ *
+ *  sep_driver_api.h - Security Processor Driver api definitions
+ *
+ *  Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *  Copyright(c) 2009 Discretix. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc., 59
+ *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *  CONTACTS:
+ *
+ *  Mark Allyn		mark.a.allyn@intel.com
+ *
+ *  CHANGES:
+ *
+ *  2009.06.26	Initial publish
+ *
+ */
+
+#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)
+
+/* get time address and value */
+#define SEP_IOCGETIME                          _IO(SEP_IOC_MAGIC_NUMBER , 19)
+
+/*-------------------------------------------
+    TYPEDEFS
+----------------------------------------------*/
+
+/*
+  init command struct
+*/
+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;
+
+};
+
+
+/*
+  realloc cache resident command
+*/
+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;
+
+  /* new cache address */
+  unsigned long   new_cache_addr;
+
+  /* new resident address */
+  unsigned long   new_resident_addr;
+
+  /* new resident address */
+  unsigned long   new_shared_area_addr;
+
+  /* new base address */
+  unsigned long   new_base_addr;
+};
+
+/*
+  set api mode command struct
+*/
+struct sep_driver_set_api_mode_t {
+  /* mode to set - 1 - blocking, 0 - non-blocking */
+  unsigned long   mode;
+};
+
+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;
+};
+
+/*
+ */
+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;
+};
+
+/*
+ */
+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;
+};
+
+/*
+*/
+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;
+
+  /* distinct user/kernel layout */
+  bool isKernelVirtualAddress;
+
+};
+
+/*
+*/
+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;
+
+  /* distinct user/kernel layout */
+  bool isKernelVirtualAddress;
+};
+
+
+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;
+
+  /* distinct user/kernel layout */
+  bool isKernelVirtualAddress;
+
+};
+
+/*
+  command struct for set flow id
+*/
+struct sep_driver_set_flow_id_t {
+  /* flow id to set */
+  unsigned long  flow_id;
+};
+
+
+/* command struct for add tables message */
+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;
+};
+
+/* command struct for static pool addresses  */
+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;
+};
+
+/* command struct for getiing offset of the physical address from
+	the start of the mapped area  */
+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;
+};
+
+/* command struct for getting time value and address */
+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;
+};
+
+
+/*
+  structure that represent one entry in the DMA LLI table
+*/
+struct sep_lli_entry_t {
+  /* physical address */
+  unsigned long  physical_address;
+
+  /* block size */
+  unsigned long  block_size;
+};
+
+/*
+  structure that reperesents data needed for lli table construction
+*/
+struct sep_lli_prepare_table_data_t {
+  /* pointer to the memory where the first lli entry to be built */
+  struct sep_lli_entry_t  *lli_entry_ptr;
+
+  /* pointer to the array of lli entries from which the table is to be built */
+  struct 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;
+};
+
+/*
+  structure that represent tone table - it is not used in code, jkust
+  to show what table looks like
+*/
+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 */
+  struct sep_lli_entry_t lli_entries[SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE];
+};
+
+
+/*
+  structure for keeping the mapping of the virtual buffer into physical pages
+*/
+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;
+};
+
+/*
+  struct that keeps all the data for one flow
+*/
+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 */
+  struct sep_lli_entry_t         first_input_table;
+
+  /* data of the first output table */
+  struct sep_lli_entry_t         first_output_table;
+
+  /* last input table data */
+  struct sep_lli_entry_t         last_input_table;
+
+  /* last output table data */
+  struct sep_lli_entry_t         last_output_table;
+
+  /* first list of table */
+  struct sep_lli_entry_t         input_tables_in_process;
+
+  /* output table in process (in sep) */
+  struct 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];
+};
+
+
+
+/*
+  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 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(
+					struct sep_lli_entry_t *lli_in_array,
+					unsigned long     sep_in_lli_entries,
+					struct 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 function builds input and output DMA tables for synhronic symmetric
+	operations (AES, DES) It also checks that each table is of the modular
+	block size
+*/
+int sep_prepare_input_output_dma_table(unsigned long   app_virt_in_addr,
+				unsigned long   app_virt_out_addr,
+				unsigned long   data_size,
+				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,
+				bool            isKernelVirtualAddress);
+
+/*
+	This function prepares only input DMA table for synhronic symmetric
+	operations (HASH)
+*/
+int sep_prepare_input_dma_table(unsigned long   app_virt_addr,
+				unsigned long   data_size,
+				unsigned long   block_size,
+				unsigned long  *lli_table_ptr,
+				unsigned long  *num_entries_ptr,
+				unsigned long  *table_data_size_ptr,
+				bool            isKernelVirtualAddress);
+
+/* 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);
+
+/*
+	this function handles the request for freeing dma table for
+	synhronic actions
+*/
+int sep_free_dma_table_data_handler(void);
+
+
+#endif
diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h
new file mode 100644
index 000000000000..a796c4970a06
--- /dev/null
+++ b/drivers/staging/sep/sep_driver_config.h
@@ -0,0 +1,305 @@
+/*
+ *
+ *  sep_driver_config.h - Security Processor Driver configuration
+ *
+ *  Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *  Copyright(c) 2009 Discretix. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc., 59
+ *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *  CONTACTS:
+ *
+ *  Mark Allyn		mark.a.allyn@intel.com
+ *
+ *  CHANGES:
+ *
+ *  2009.06.26	Initial publish
+ *
+ */
+
+#ifndef __SEP_DRIVER_CONFIG_H__
+#define __SEP_DRIVER_CONFIG_H__
+
+
+/*--------------------------------------
+  DRIVER CONFIGURATION FLAGS
+  -------------------------------------*/
+
+/* if flag is on , then the driver is running in polling and
+	not interrupt mode */
+#define SEP_DRIVER_POLLING_MODE                         1
+
+/* flag which defines if the shared area address should be
+	reconfiged (send to SEP anew) during init of the driver */
+#define SEP_DRIVER_RECONFIG_MESSAGE_AREA                0
+
+/* the mode for running on the ARM1172 Evaluation platform (flag is 1) */
+#define SEP_DRIVER_ARM_DEBUG_MODE                       0
+
+/*-------------------------------------------
+	INTERNAL DATA CONFIGURATION
+	-------------------------------------------*/
+
+/* flag for the input array */
+#define SEP_DRIVER_IN_FLAG                              0
+
+/* flag for output array */
+#define SEP_DRIVER_OUT_FLAG                             1
+
+/* maximum number of entries in one LLI tables */
+#define SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP             8
+
+
+/*--------------------------------------------------------
+	SHARED AREA  memory total size is 36K
+	it is divided is following:
+
+	SHARED_MESSAGE_AREA                     8K         }
+									}
+	STATIC_POOL_AREA                        4K         } MAPPED AREA ( 24 K)
+									}
+	DATA_POOL_AREA                          12K        }
+
+	SYNCHRONIC_DMA_TABLES_AREA              5K
+
+	FLOW_DMA_TABLES_AREA                    4K
+
+	SYSTEM_MEMORY_AREA                      3k
+
+	SYSTEM_MEMORY total size is 3k
+	it is divided as following:
+
+	TIME_MEMORY_AREA                     8B
+-----------------------------------------------------------*/
+
+
+
+/*
+	the maximum length of the message - the rest of the message shared
+	area will be dedicated to the dma lli tables
+*/
+#define SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES                  (8 * 1024)
+
+/* the size of the message shared area in pages */
+#define SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES          (8 * 1024)
+
+/* the size of the data pool static area in pages */
+#define SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES                  (4 * 1024)
+
+/* the size of the data pool shared area size in pages */
+#define SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES        (12 * 1024)
+
+/* the size of the message shared area in pages */
+#define SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES   (1024 * 5)
+
+
+/* the size of the data pool shared area size in pages */
+#define SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES         (1024 * 4)
+
+/* system data (time, caller id etc') pool */
+#define SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES           100
+
+
+/* area size that is mapped  - we map the MESSAGE AREA, STATIC POOL and
+	DATA POOL areas. area must be module 4k */
+#define SEP_DRIVER_MMMAP_AREA_SIZE                            (1024 * 24)
+
+
+/*-----------------------------------------------
+	offsets of the areas starting from the shared area start address
+*/
+
+/* message area offset */
+#define SEP_DRIVER_MESSAGE_AREA_OFFSET_IN_BYTES               0
+
+/* static pool area offset */
+#define SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES \
+		(SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES)
+
+/* data pool area offset */
+#define SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES \
+	(SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES + \
+	SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES)
+
+/* synhronic dma tables area offset */
+#define SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES \
+	(SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + \
+	SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES)
+
+/* sep driver flow dma tables area offset */
+#define SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES \
+	(SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES + \
+	SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES)
+
+/* system memory offset in bytes */
+#define SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES \
+	(SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES + \
+	SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES)
+
+/* offset of the time area */
+#define SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES \
+	(SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES)
+
+
+
+/* start physical address of the SEP registers memory in HOST */
+#define SEP_IO_MEM_REGION_START_ADDRESS                       0x80000000
+
+/* size of the SEP registers memory region  in HOST (for now 100 registers) */
+#define SEP_IO_MEM_REGION_SIZE                                (2 * 0x100000)
+
+/* define the number of IRQ for SEP interrupts */
+#define SEP_DIRVER_IRQ_NUM                                    1
+
+/* maximum number of add buffers */
+#define SEP_MAX_NUM_ADD_BUFFERS                               100
+
+/* number of flows */
+#define SEP_DRIVER_NUM_FLOWS                                  4
+
+/* maximum number of entries in flow table */
+#define SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE              25
+
+/* offset of the num entries in the block length entry of the LLI */
+#define SEP_NUM_ENTRIES_OFFSET_IN_BITS                        24
+
+/* offset of the interrupt flag in the block length entry of the LLI */
+#define SEP_INT_FLAG_OFFSET_IN_BITS                           31
+
+/* mask for extracting data size from LLI */
+#define SEP_TABLE_DATA_SIZE_MASK                              0xFFFFFF
+
+/* mask for entries after being shifted left */
+#define SEP_NUM_ENTRIES_MASK                                  0x7F
+
+/* default flow id */
+#define SEP_FREE_FLOW_ID                                      0xFFFFFFFF
+
+/* temp flow id used during cretiong of new flow until receiving
+	real flow id from sep */
+#define SEP_TEMP_FLOW_ID                   (SEP_DRIVER_NUM_FLOWS + 1)
+
+/* maximum add buffers message length in bytes */
+#define SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES                   (7 * 4)
+
+/* maximum number of concurrent virtual buffers */
+#define SEP_MAX_VIRT_BUFFERS_CONCURRENT                       100
+
+/* the token that defines the start of time address */
+#define SEP_TIME_VAL_TOKEN                                    0x12345678
+/* DEBUG LEVEL MASKS */
+#define SEP_DEBUG_LEVEL_BASIC       0x1
+
+#define SEP_DEBUG_LEVEL_REGISTERS   0x2
+
+#define SEP_DEBUG_LEVEL_EXTENDED    0x4
+
+
+/* FUNCTIONAL MACROS */
+
+/* debug macro without paramaters */
+#define DEBUG_PRINT_0(DEBUG_LEVEL , info) \
+do { \
+	if (DEBUG_LEVEL & sepDebug) \
+		printk(KERN_WARNING info); \
+} while (0)
+
+/* debug macro with 1 paramater */
+#define DEBUG_PRINT_1(DEBUG_LEVEL , info , param1) \
+do { \
+	if (DEBUG_LEVEL & sepDebug) \
+		printk(KERN_WARNING info, param1); \
+} while (0)
+
+/* debug macro with 2 paramaters */
+#define DEBUG_PRINT_2(DEBUG_LEVEL, info, param1, param2) \
+do { \
+	if (DEBUG_LEVEL & sepDebug) \
+		printk(KERN_WARNING info , param1, param2); \
+} while (0)
+
+/* debug macro with 3 paramaters */
+#define DEBUG_PRINT_3(DEBUG_LEVEL, info, param1, param2, param3) \
+do { \
+	if (DEBUG_LEVEL & sepDebug) \
+		printk(KERN_WARNING info , param1, param2 , param3); \
+} while (0)
+
+/* debug macro with 4 paramaters */
+#define DEBUG_PRINT_4(DEBUG_LEVEL, info, param1, param2, param3, param4) \
+do { \
+	if (DEBUG_LEVEL & sepDebug) \
+		printk(KERN_WARNING info, param1, param2, param3, param4); \
+} while (0)
+
+#if 0
+/* write register macro with option for debug print */
+#define SEP_WRITE_REGISTER(address, value) \
+do { \
+	if (sepDebug & SEP_DEBUG_LEVEL_REGISTERS) \
+		printk(KERN_WARNING "Write Register: address %lu value %lu\n", \
+		(unsigned long)(address), (unsigned long)(value)); \
+	writel((value), (void *)(address)); \
+} while (0)
+
+/* read register macro with option for debug print */
+#define SEP_READ_REGISTER(address , value) \
+do { \
+	(value) = readl((void *)(address)); \
+	if (sepDebug & SEP_DEBUG_LEVEL_REGISTERS) \
+		printk(KERN_WARNING "Read Register: address %lu value %lu\n", \
+		(address), (value)); \
+} while (0)
+#else
+
+#if 1
+
+#define SEP_WRITE_REGISTER(address, value)  writel((value), (void *)(address))
+#define SEP_READ_REGISTER(address, value)  (value) = readl((void *)(address))
+#endif
+
+#endif
+
+#if 0
+#define SEP_WRITE_ROM(address, value)  writel((value), (void *)(address))
+
+#define SEP_WRITE_REGISTER(address, value) \
+do { \
+	unsigned long i; \
+	for (i = 0; i < 1000; i++); \
+		writel((value), (void *)(address)); \
+} while (0)
+
+
+#define SEP_READ_REGISTER(address , value) \
+do { \
+	unsigned long i; \
+	for (i = 0; i < 1000; i++); \
+		(value) = readl((void *) (address)); \
+} while (0)
+
+#endif
+
+/* wait for SRAM write complete(indirect write */
+#define SEP_WAIT_SRAM_WRITE_COMPLETE() \
+do { \
+	unsigned long  reg_val; \
+	do { \
+		SEP_READ_REGISTER(g_sep_reg_base_address + \
+		HW_SRAM_DATA_READY_REG_ADDR, (reg_val)); \
+	} while (!(reg_val & 0x1)); \
+} while (0)
+
+#endif
diff --git a/drivers/staging/sep/sep_driver_ext_api.h b/drivers/staging/sep/sep_driver_ext_api.h
new file mode 100644
index 000000000000..3bc3b4de99c0
--- /dev/null
+++ b/drivers/staging/sep/sep_driver_ext_api.h
@@ -0,0 +1,106 @@
+/*
+ *
+ *  sep_driver_ext_api.h - Security Processor Driver external api definitions
+ *
+ *  Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *  Copyright(c) 2009 Discretix. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc., 59
+ *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *  CONTACTS:
+ *
+ *  Mark Allyn		mark.a.allyn@intel.com
+ *
+ *  CHANGES:
+ *
+ *  2009.06.26	Initial publish
+ *
+ */
+
+#ifndef __SEP_DRIVER_EXT_API_H__
+#define __SEP_DRIVER_EXT_API_H__
+
+
+/* shared variables */
+extern int sepDebug;
+
+extern unsigned long g_sep_reg_base_address;
+
+/*
+this function loads the ROM code in SEP (needed only in the debug mode on FPGA)
+*/
+void sep_load_rom_code(void);
+
+/*
+This functions locks the area of the resident and cache sep code (if possible)
+*/
+void sep_lock_cache_resident_area(void);
+
+/*
+This functions copies the cache and resident from their source location into
+destination memory, which is external to Linux VM and is given as physical
+address
+*/
+int sep_copy_cache_resident_to_area(unsigned long   src_cache_addr,
+				unsigned long   cache_size_in_bytes,
+				unsigned long   src_resident_addr,
+				unsigned long   resident_size_in_bytes,
+				unsigned long  *dst_new_cache_addr_ptr,
+				unsigned long  *dst_new_resident_addr_ptr);
+
+/*
+This functions maps and allocates the shared area on the external
+RAM (device) The input is shared_area_size - the size of the memory
+to allocate. The outputs are kernel_shared_area_addr_ptr - the kerenl
+address of the mapped and allocated shared area, and
+phys_shared_area_addr_ptr - the physical address of the shared area
+*/
+int sep_map_and_alloc_shared_area(unsigned long   shared_area_size,
+				unsigned long  *kernel_shared_area_addr_ptr,
+				unsigned long  *phys_shared_area_addr_ptr);
+
+/*
+This functions unmaps and deallocates the shared area on the  external
+RAM (device) The input is shared_area_size - the size of the memory to
+deallocate,kernel_shared_area_addr_ptr - the kernel address of the
+mapped and allocated shared area,phys_shared_area_addr_ptr - the physical
+address of the shared area
+*/
+void sep_unmap_and_free_shared_area(unsigned long   shared_area_size,
+				unsigned long   kernel_shared_area_addr,
+				unsigned long   phys_shared_area_addr);
+
+
+/*
+This functions returns the physical address inside shared area according
+to the virtual address. It can be either on the externa RAM device
+(ioremapped), or on the system RAM
+*/
+unsigned long sep_shared_area_virt_to_phys(unsigned long virt_address);
+
+/*
+This functions returns the vitrual address inside shared area according
+to the physical address. It can be either on the externa RAM device
+(ioremapped), or on the system RAM This implementation is for the external RAM
+*/
+unsigned long sep_shared_area_phys_to_virt(unsigned long phys_address);
+
+/*
+This function registers th driver to the device
+subsystem (either PCI, USB, etc)
+*/
+int sep_register_driver_to_device(void);
+
+#endif /*__SEP_DRIVER_EXT_API_H__*/
diff --git a/drivers/staging/sep/sep_driver_hw_defs.h b/drivers/staging/sep/sep_driver_hw_defs.h
new file mode 100644
index 000000000000..df831be2645e
--- /dev/null
+++ b/drivers/staging/sep/sep_driver_hw_defs.h
@@ -0,0 +1,240 @@
+/*
+ *
+ *  sep_driver_hw_defs.h - Security Processor Driver hardware definitions
+ *
+ *  Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *  Copyright(c) 2009 Discretix. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc., 59
+ *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *  CONTACTS:
+ *
+ *  Mark Allyn		mark.a.allyn@intel.com
+ *
+ *  CHANGES:
+ *
+ *  2009.06.26	Initial publish
+ *
+ */
+
+#ifndef SEP_DRIVER_HW_DEFS__H
+#define SEP_DRIVER_HW_DEFS__H
+
+/*--------------------------------------------------------------------------*/
+/* Abstract: HW Registers Defines.                                          */
+/*                                                                          */
+/* Note: This file was automatically created !!!                            */
+/*       DO NOT EDIT THIS FILE !!!                                          */
+/*--------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* cf registers */
+#define 	 HW_R0B_ADDR_0_REG_ADDR 		 0x0000UL
+#define 	 HW_R0B_ADDR_1_REG_ADDR 		 0x0004UL
+#define 	 HW_R0B_ADDR_2_REG_ADDR 		 0x0008UL
+#define 	 HW_R0B_ADDR_3_REG_ADDR 		 0x000cUL
+#define 	 HW_R0B_ADDR_4_REG_ADDR 		 0x0010UL
+#define 	 HW_R0B_ADDR_5_REG_ADDR 		 0x0014UL
+#define 	 HW_R0B_ADDR_6_REG_ADDR 		 0x0018UL
+#define 	 HW_R0B_ADDR_7_REG_ADDR 		 0x001cUL
+#define 	 HW_R0B_ADDR_8_REG_ADDR 		 0x0020UL
+#define 	 HW_R2B_ADDR_0_REG_ADDR 		 0x0080UL
+#define 	 HW_R2B_ADDR_1_REG_ADDR 		 0x0084UL
+#define 	 HW_R2B_ADDR_2_REG_ADDR 		 0x0088UL
+#define 	 HW_R2B_ADDR_3_REG_ADDR 		 0x008cUL
+#define 	 HW_R2B_ADDR_4_REG_ADDR 		 0x0090UL
+#define 	 HW_R2B_ADDR_5_REG_ADDR 		 0x0094UL
+#define 	 HW_R2B_ADDR_6_REG_ADDR 		 0x0098UL
+#define 	 HW_R2B_ADDR_7_REG_ADDR 		 0x009cUL
+#define 	 HW_R2B_ADDR_8_REG_ADDR 		 0x00a0UL
+#define 	 HW_R3B_REG_ADDR 		         0x00C0UL
+#define 	 HW_R4B_REG_ADDR 		         0x0100UL
+#define 	 HW_CSA_ADDR_0_REG_ADDR 		 0x0140UL
+#define 	 HW_CSA_ADDR_1_REG_ADDR 		 0x0144UL
+#define 	 HW_CSA_ADDR_2_REG_ADDR 		 0x0148UL
+#define 	 HW_CSA_ADDR_3_REG_ADDR 		 0x014cUL
+#define 	 HW_CSA_ADDR_4_REG_ADDR 		 0x0150UL
+#define 	 HW_CSA_ADDR_5_REG_ADDR 		 0x0154UL
+#define 	 HW_CSA_ADDR_6_REG_ADDR 		 0x0158UL
+#define 	 HW_CSA_ADDR_7_REG_ADDR 		 0x015cUL
+#define 	 HW_CSA_ADDR_8_REG_ADDR 		 0x0160UL
+#define 	 HW_CSA_REG_ADDR 		         0x0140UL
+#define 	 HW_SINB_REG_ADDR 		         0x0180UL
+#define 	 HW_SOUTB_REG_ADDR 		         0x0184UL
+#define 	 HW_PKI_CONTROL_REG_ADDR 		 0x01C0UL
+#define 	 HW_PKI_STATUS_REG_ADDR 		 0x01C4UL
+#define 	 HW_PKI_BUSY_REG_ADDR 		     0x01C8UL
+#define 	 HW_PKI_A_1025_REG_ADDR 		 0x01CCUL
+#define 	 HW_PKI_SDMA_CTL_REG_ADDR 		 0x01D0UL
+#define 	 HW_PKI_SDMA_OFFSET_REG_ADDR 	 0x01D4UL
+#define 	 HW_PKI_SDMA_POINTERS_REG_ADDR 	 0x01D8UL
+#define 	 HW_PKI_SDMA_DLENG_REG_ADDR 		 0x01DCUL
+#define 	 HW_PKI_SDMA_EXP_POINTERS_REG_ADDR 	 0x01E0UL
+#define 	 HW_PKI_SDMA_RES_POINTERS_REG_ADDR 	 0x01E4UL
+#define 	 HW_PKI_CLR_REG_ADDR 		         0x01E8UL
+#define 	 HW_PKI_SDMA_BUSY_REG_ADDR 		     0x01E8UL
+#define 	 HW_PKI_SDMA_FIRST_EXP_N_REG_ADDR 	 0x01ECUL
+#define 	 HW_PKI_SDMA_MUL_BY1_REG_ADDR 		 0x01F0UL
+#define 	 HW_PKI_SDMA_RMUL_SEL_REG_ADDR 		 0x01F4UL
+#define 	 HW_DES_KEY_0_REG_ADDR 		         0x0208UL
+#define 	 HW_DES_KEY_1_REG_ADDR 		         0x020CUL
+#define 	 HW_DES_KEY_2_REG_ADDR 		         0x0210UL
+#define 	 HW_DES_KEY_3_REG_ADDR 		         0x0214UL
+#define 	 HW_DES_KEY_4_REG_ADDR 		         0x0218UL
+#define 	 HW_DES_KEY_5_REG_ADDR 		         0x021CUL
+#define 	 HW_DES_CONTROL_0_REG_ADDR 	         0x0220UL
+#define 	 HW_DES_CONTROL_1_REG_ADDR 	         0x0224UL
+#define 	 HW_DES_IV_0_REG_ADDR 		         0x0228UL
+#define 	 HW_DES_IV_1_REG_ADDR 		         0x022CUL
+#define 	 HW_AES_KEY_0_ADDR_0_REG_ADDR 		 0x0400UL
+#define 	 HW_AES_KEY_0_ADDR_1_REG_ADDR 		 0x0404UL
+#define 	 HW_AES_KEY_0_ADDR_2_REG_ADDR 		 0x0408UL
+#define 	 HW_AES_KEY_0_ADDR_3_REG_ADDR 		 0x040cUL
+#define 	 HW_AES_KEY_0_ADDR_4_REG_ADDR 		 0x0410UL
+#define 	 HW_AES_KEY_0_ADDR_5_REG_ADDR 		 0x0414UL
+#define 	 HW_AES_KEY_0_ADDR_6_REG_ADDR 		 0x0418UL
+#define 	 HW_AES_KEY_0_ADDR_7_REG_ADDR 		 0x041cUL
+#define 	 HW_AES_KEY_0_REG_ADDR 		         0x0400UL
+#define 	 HW_AES_IV_0_ADDR_0_REG_ADDR 		 0x0440UL
+#define 	 HW_AES_IV_0_ADDR_1_REG_ADDR 		 0x0444UL
+#define 	 HW_AES_IV_0_ADDR_2_REG_ADDR 		 0x0448UL
+#define 	 HW_AES_IV_0_ADDR_3_REG_ADDR 		 0x044cUL
+#define 	 HW_AES_IV_0_REG_ADDR 		         0x0440UL
+#define 	 HW_AES_CTR1_ADDR_0_REG_ADDR 		 0x0460UL
+#define 	 HW_AES_CTR1_ADDR_1_REG_ADDR 		 0x0464UL
+#define 	 HW_AES_CTR1_ADDR_2_REG_ADDR 		 0x0468UL
+#define 	 HW_AES_CTR1_ADDR_3_REG_ADDR 		 0x046cUL
+#define 	 HW_AES_CTR1_REG_ADDR 		         0x0460UL
+#define 	 HW_AES_SK_REG_ADDR 		         0x0478UL
+#define 	 HW_AES_MAC_OK_REG_ADDR 		     0x0480UL
+#define 	 HW_AES_PREV_IV_0_ADDR_0_REG_ADDR 	 0x0490UL
+#define 	 HW_AES_PREV_IV_0_ADDR_1_REG_ADDR 	 0x0494UL
+#define 	 HW_AES_PREV_IV_0_ADDR_2_REG_ADDR 	 0x0498UL
+#define 	 HW_AES_PREV_IV_0_ADDR_3_REG_ADDR 	 0x049cUL
+#define 	 HW_AES_PREV_IV_0_REG_ADDR 		     0x0490UL
+#define 	 HW_AES_CONTROL_REG_ADDR 		     0x04C0UL
+#define 	 HW_HASH_H0_REG_ADDR 		     0x0640UL
+#define 	 HW_HASH_H1_REG_ADDR 		     0x0644UL
+#define 	 HW_HASH_H2_REG_ADDR 		     0x0648UL
+#define 	 HW_HASH_H3_REG_ADDR 		     0x064CUL
+#define 	 HW_HASH_H4_REG_ADDR 		     0x0650UL
+#define 	 HW_HASH_H5_REG_ADDR 		     0x0654UL
+#define 	 HW_HASH_H6_REG_ADDR 		     0x0658UL
+#define 	 HW_HASH_H7_REG_ADDR 		     0x065CUL
+#define 	 HW_HASH_H8_REG_ADDR 		     0x0660UL
+#define 	 HW_HASH_H9_REG_ADDR 		     0x0664UL
+#define 	 HW_HASH_H10_REG_ADDR 		     0x0668UL
+#define 	 HW_HASH_H11_REG_ADDR 		     0x066CUL
+#define 	 HW_HASH_H12_REG_ADDR 		     0x0670UL
+#define 	 HW_HASH_H13_REG_ADDR 		     0x0674UL
+#define 	 HW_HASH_H14_REG_ADDR 		     0x0678UL
+#define 	 HW_HASH_H15_REG_ADDR 		     0x067CUL
+#define 	 HW_HASH_CONTROL_REG_ADDR 		 0x07C0UL
+#define 	 HW_HASH_PAD_EN_REG_ADDR 		 0x07C4UL
+#define 	 HW_HASH_PAD_CFG_REG_ADDR 		 0x07C8UL
+#define 	 HW_HASH_CUR_LEN_0_REG_ADDR 	 0x07CCUL
+#define 	 HW_HASH_CUR_LEN_1_REG_ADDR 	 0x07D0UL
+#define 	 HW_HASH_CUR_LEN_2_REG_ADDR 	 0x07D4UL
+#define 	 HW_HASH_CUR_LEN_3_REG_ADDR 	 0x07D8UL
+#define 	 HW_HASH_PARAM_REG_ADDR 		 0x07DCUL
+#define 	 HW_HASH_INT_BUSY_REG_ADDR 		 0x07E0UL
+#define 	 HW_HASH_SW_RESET_REG_ADDR 		 0x07E4UL
+#define 	 HW_HASH_ENDIANESS_REG_ADDR 	 0x07E8UL
+#define 	 HW_HASH_DATA_REG_ADDR 		     0x07ECUL
+#define 	 HW_DRNG_CONTROL_REG_ADDR 		 0x0800UL
+#define 	 HW_DRNG_VALID_REG_ADDR 		 0x0804UL
+#define 	 HW_DRNG_DATA_REG_ADDR 		     0x0808UL
+#define 	 HW_RND_SRC_EN_REG_ADDR 		 0x080CUL
+#define 	 HW_AES_CLK_ENABLE_REG_ADDR 	 0x0810UL
+#define 	 HW_DES_CLK_ENABLE_REG_ADDR 	 0x0814UL
+#define 	 HW_HASH_CLK_ENABLE_REG_ADDR 	 0x0818UL
+#define 	 HW_PKI_CLK_ENABLE_REG_ADDR 	 0x081CUL
+#define 	 HW_CLK_STATUS_REG_ADDR 		 0x0824UL
+#define 	 HW_CLK_ENABLE_REG_ADDR 		 0x0828UL
+#define 	 HW_DRNG_SAMPLE_REG_ADDR 		 0x0850UL
+#define 	 HW_RND_SRC_CTL_REG_ADDR 		 0x0858UL
+#define 	 HW_CRYPTO_CTL_REG_ADDR 		 0x0900UL
+#define 	 HW_CRYPTO_STATUS_REG_ADDR 		 0x090CUL
+#define 	 HW_CRYPTO_BUSY_REG_ADDR 		 0x0910UL
+#define 	 HW_AES_BUSY_REG_ADDR 		     0x0914UL
+#define 	 HW_DES_BUSY_REG_ADDR 		     0x0918UL
+#define 	 HW_HASH_BUSY_REG_ADDR 		     0x091CUL
+#define 	 HW_CONTENT_REG_ADDR 		     0x0924UL
+#define 	 HW_VERSION_REG_ADDR 		     0x0928UL
+#define 	 HW_CONTEXT_ID_REG_ADDR 		 0x0930UL
+#define 	 HW_DIN_BUFFER_REG_ADDR 		 0x0C00UL
+#define 	 HW_DIN_MEM_DMA_BUSY_REG_ADDR 	 0x0c20UL
+#define 	 HW_SRC_LLI_MEM_ADDR_REG_ADDR 	 0x0c24UL
+#define 	 HW_SRC_LLI_WORD0_REG_ADDR 		 0x0C28UL
+#define 	 HW_SRC_LLI_WORD1_REG_ADDR 		 0x0C2CUL
+#define 	 HW_SRAM_SRC_ADDR_REG_ADDR 		 0x0c30UL
+#define 	 HW_DIN_SRAM_BYTES_LEN_REG_ADDR  0x0c34UL
+#define 	 HW_DIN_SRAM_DMA_BUSY_REG_ADDR 	 0x0C38UL
+#define 	 HW_WRITE_ALIGN_REG_ADDR 		 0x0C3CUL
+#define 	 HW_OLD_DATA_REG_ADDR 		     0x0C48UL
+#define 	 HW_WRITE_ALIGN_LAST_REG_ADDR 	 0x0C4CUL
+#define 	 HW_DOUT_BUFFER_REG_ADDR 		 0x0C00UL
+#define 	 HW_DST_LLI_WORD0_REG_ADDR 		 0x0D28UL
+#define 	 HW_DST_LLI_WORD1_REG_ADDR 		 0x0D2CUL
+#define 	 HW_DST_LLI_MEM_ADDR_REG_ADDR 	 0x0D24UL
+#define 	 HW_DOUT_MEM_DMA_BUSY_REG_ADDR 	 0x0D20UL
+#define 	 HW_SRAM_DEST_ADDR_REG_ADDR 	 0x0D30UL
+#define 	 HW_DOUT_SRAM_BYTES_LEN_REG_ADDR 0x0D34UL
+#define 	 HW_DOUT_SRAM_DMA_BUSY_REG_ADDR  0x0D38UL
+#define 	 HW_READ_ALIGN_REG_ADDR 		 0x0D3CUL
+#define 	 HW_READ_LAST_DATA_REG_ADDR 	 0x0D44UL
+#define 	 HW_RC4_THRU_CPU_REG_ADDR 		 0x0D4CUL
+#define 	 HW_AHB_SINGLE_REG_ADDR 		 0x0E00UL
+#define 	 HW_SRAM_DATA_REG_ADDR 		     0x0F00UL
+#define 	 HW_SRAM_ADDR_REG_ADDR 		     0x0F04UL
+#define 	 HW_SRAM_DATA_READY_REG_ADDR 	 0x0F08UL
+#define 	 HW_HOST_IRR_REG_ADDR 		          0x0A00UL
+#define 	 HW_HOST_IMR_REG_ADDR 		          0x0A04UL
+#define 	 HW_HOST_ICR_REG_ADDR 		          0x0A08UL
+#define 	 HW_HOST_SEP_SRAM_THRESHOLD_REG_ADDR  0x0A10UL
+#define 	 HW_HOST_SEP_BUSY_REG_ADDR 		      0x0A14UL
+#define 	 HW_HOST_SEP_LCS_REG_ADDR 		      0x0A18UL
+#define 	 HW_HOST_CC_SW_RST_REG_ADDR 		  0x0A40UL
+#define 	 HW_HOST_SEP_SW_RST_REG_ADDR 		  0x0A44UL
+#define 	 HW_HOST_FLOW_DMA_SW_INT0_REG_ADDR 	  0x0A80UL
+#define 	 HW_HOST_FLOW_DMA_SW_INT1_REG_ADDR 	  0x0A84UL
+#define 	 HW_HOST_FLOW_DMA_SW_INT2_REG_ADDR 	  0x0A88UL
+#define 	 HW_HOST_FLOW_DMA_SW_INT3_REG_ADDR 	  0x0A8cUL
+#define 	 HW_HOST_FLOW_DMA_SW_INT4_REG_ADDR 	  0x0A90UL
+#define 	 HW_HOST_FLOW_DMA_SW_INT5_REG_ADDR 	  0x0A94UL
+#define 	 HW_HOST_FLOW_DMA_SW_INT6_REG_ADDR    0x0A98UL
+#define 	 HW_HOST_FLOW_DMA_SW_INT7_REG_ADDR 	  0x0A9cUL
+#define 	 HW_HOST_SEP_HOST_GPR0_REG_ADDR 	  0x0B00UL
+#define 	 HW_HOST_SEP_HOST_GPR1_REG_ADDR 	  0x0B04UL
+#define 	 HW_HOST_SEP_HOST_GPR2_REG_ADDR 	  0x0B08UL
+#define 	 HW_HOST_SEP_HOST_GPR3_REG_ADDR       0x0B0CUL
+#define 	 HW_HOST_HOST_SEP_GPR0_REG_ADDR       0x0B80UL
+#define 	 HW_HOST_HOST_SEP_GPR1_REG_ADDR       0x0B84UL
+#define 	 HW_HOST_HOST_SEP_GPR2_REG_ADDR       0x0B88UL
+#define 	 HW_HOST_HOST_SEP_GPR3_REG_ADDR       0x0B8CUL
+#define 	 HW_HOST_HOST_ENDIAN_REG_ADDR 	      0x0B90UL
+#define 	 HW_HOST_HOST_COMM_CLK_EN_REG_ADDR 	  0x0B94UL
+#define 	 HW_CLR_SRAM_BUSY_REG_REG_ADDR 	      0x0F0CUL
+#define    HW_CC_SRAM_BASE_ADDRESS              0x5800UL
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef HW_DEFS */
diff --git a/drivers/staging/sep/sep_ext_with_pci_driver.c b/drivers/staging/sep/sep_ext_with_pci_driver.c
new file mode 100644
index 000000000000..9fb1dd0129af
--- /dev/null
+++ b/drivers/staging/sep/sep_ext_with_pci_driver.c
@@ -0,0 +1,631 @@
+/*
+ *
+ *  sep_ext_with_pci_driver.c - Security Processor Driver
+ *  pci initialization functions
+ *
+ *  Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *  Copyright(c) 2009 Discretix. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc., 59
+ *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *  CONTACTS:
+ *
+ *  Mark Allyn		mark.a.allyn@intel.com
+ *
+ *  CHANGES:
+ *
+ *  2009.06.26	Initial publish
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/kdev_t.h>
+#include <linux/semaphore.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/ioctl.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/pagemap.h>
+#include <linux/pci.h>
+#include <linux/firmware.h>
+#include <linux/sched.h>
+#include "sep_driver_hw_defs.h"
+#include "sep_driver_config.h"
+#include "sep_driver_api.h"
+#include "sep_driver_ext_api.h"
+
+#if SEP_DRIVER_ARM_DEBUG_MODE
+
+#define  CRYS_SEP_ROM_length                  0x4000
+
+#define  CRYS_SEP_ROM_start_address           0x8000C000UL
+
+#define  CRYS_SEP_ROM_start_address_offset    0xC000UL
+
+#define  SEP_ROM_BANK_register                0x80008420UL
+
+#define  SEP_ROM_BANK_register_offset         0x8420UL
+
+#define SEP_RAR_IO_MEM_REGION_START_ADDRESS   0x82000000
+
+/* 2M size */
+/* #define SEP_RAR_IO_MEM_REGION_SIZE            (1024*1024*2)
+
+static unsigned long CRYS_SEP_ROM[] = {
+	#include "SEP_ROM_image.h"
+};
+
+#else
+*/
+
+/*-------------
+ THOSE 2 definitions are specific to the board - must be
+ defined during integration
+---------------*/
+#define SEP_RAR_IO_MEM_REGION_START_ADDRESS   0xFF0D0000
+
+/* 2M size */
+
+#endif /* SEP_DRIVER_ARM_DEBUG_MODE */
+
+#define BASE_ADDRESS_FOR_SYSTEM 0xfffc0000
+#define SEP_RAR_IO_MEM_REGION_SIZE 0x40000
+
+irqreturn_t sep_inthandler(int irq , void* dev_id);
+
+/* NOTE - must be defined specific to the board */
+#define VENDOR_ID                             0x8086
+
+/* io memory (register area) */
+static unsigned long io_memory_start_physical_address;
+static unsigned long io_memory_end_physical_address;
+static unsigned long io_memory_size;
+void *io_memory_start_virtual_address;
+
+/* restricted access region */
+static unsigned long rar_physical_address;
+static void *rar_virtual_address;
+
+/* shared memory region */
+static unsigned long shared_physical_address;
+static void *shared_virtual_address;
+
+/* firmware regions */
+static unsigned long cache_physical_address;
+static unsigned long cache_size;
+static void *cache_virtual_address;
+
+static unsigned long resident_physical_address;
+static unsigned long resident_size;
+static void *resident_virtual_address;
+
+/* device interrupt (as retrieved from PCI) */
+int sep_irq;
+
+/* temporary */
+unsigned long jiffies_future;
+
+/*-----------------------------
+    private functions
+--------------------------------*/
+
+/*
+  function that is activated on the succesfull probe of the SEP device
+*/
+static int __devinit sep_probe(struct pci_dev *pdev,
+  const struct pci_device_id *ent);
+
+static struct pci_device_id sep_pci_id_tbl[] = {
+	{ PCI_DEVICE(VENDOR_ID, 0x080c) },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, sep_pci_id_tbl);
+
+static unsigned long    rar_region_addr;
+
+
+/* field for registering driver to PCI device */
+static struct pci_driver sep_pci_driver = {
+	.name = "sep_sec_driver",
+	.id_table = sep_pci_id_tbl,
+	.probe = sep_probe
+};
+
+/* pointer to pci dev received during probe */
+struct pci_dev *sep_pci_dev_ptr;
+
+/*
+  This functions locks the area of the resisnd and cache sep code
+*/
+void sep_lock_cache_resident_area(void)
+{
+	return;
+}
+
+
+/*
+  This functions copies the cache and resident from their source location into
+  destination memory, which is external to Linux VM and is given as
+   physical address
+*/
+int sep_copy_cache_resident_to_area(unsigned long   src_cache_addr,
+				unsigned long   cache_size_in_bytes,
+				unsigned long   src_resident_addr,
+				unsigned long   resident_size_in_bytes,
+				unsigned long *dst_new_cache_addr_ptr,
+				unsigned long *dst_new_resident_addr_ptr)
+{
+	/* resident address in user space */
+	unsigned long resident_addr;
+
+	/* cahce address in user space */
+	unsigned long cache_addr;
+
+	const struct firmware *fw;
+
+	char *cache_name = "cache.image.bin";
+	char *res_name =  "resident.image.bin";
+
+	/* error */
+	int error;
+
+	/*--------------------------------
+	    CODE
+	-------------------------------------*/
+	error = 0;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:rar_virtual is %p\n",
+	  rar_virtual_address);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:rar_physical is %08lx\n",
+	  rar_physical_address);
+
+	rar_region_addr = (unsigned long)rar_virtual_address;
+
+	cache_physical_address = rar_physical_address;
+	cache_virtual_address = rar_virtual_address;
+
+	/* load cache */
+	error = request_firmware(&fw, cache_name, &sep_pci_dev_ptr->dev);
+	if (error) {
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver:cant request cache fw\n");
+		goto end_function;
+	}
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:cache data loc is %p\n",
+	  (void *)fw->data);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:cache data size is %08x\n",
+	  fw->size);
+
+	memcpy((void *)cache_virtual_address, (void *)fw->data, fw->size);
+
+	cache_size = fw->size;
+
+	cache_addr = (unsigned long)cache_virtual_address;
+
+	release_firmware(fw);
+
+	resident_physical_address = cache_physical_address+cache_size;
+	resident_virtual_address = cache_virtual_address+cache_size;
+
+	/* load resident */
+	error = request_firmware(&fw, res_name, &sep_pci_dev_ptr->dev);
+	if (error) {
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver:cant request res fw\n");
+		goto end_function;
+	}
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:res data loc is %p\n",
+	  (void *)fw->data);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:res data size is %08x\n",
+	  fw->size);
+
+	memcpy((void *)resident_virtual_address, (void *)fw->data, fw->size);
+
+	resident_size = fw->size;
+
+	release_firmware(fw);
+
+	resident_addr = (unsigned long)resident_virtual_address;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:resident_addr (physical )is %08lx\n",
+	  resident_physical_address);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:cache_addr (physical) is %08lx\n",
+	  cache_physical_address);
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:resident_addr (logical )is %08lx\n",
+	  resident_addr);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:cache_addr (logical) is %08lx\n",
+	  cache_addr);
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:resident_size is %08lx\n", resident_size);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:cache_size is %08lx\n", cache_size);
+
+
+
+	/* physical addresses */
+	*dst_new_cache_addr_ptr = cache_physical_address;
+	*dst_new_resident_addr_ptr = resident_physical_address;
+
+end_function:
+
+	return error;
+}
+
+/*
+  This functions maps and allocates the
+  shared area on the  external RAM (device)
+  The input is shared_area_size - the size of the memory to
+  allocate. The outputs
+  are kernel_shared_area_addr_ptr - the kerenl
+  address of the mapped and allocated
+  shared area, and phys_shared_area_addr_ptr
+  - the physical address of the shared area
+*/
+int sep_map_and_alloc_shared_area(unsigned long shared_area_size,
+				unsigned long *kernel_shared_area_addr_ptr,
+				unsigned long *phys_shared_area_addr_ptr)
+{
+	// shared_virtual_address = ioremap_nocache(0xda00000,shared_area_size);
+	shared_virtual_address = kmalloc(shared_area_size, GFP_KERNEL);
+	if (!shared_virtual_address) {
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "sep_driver:shared memory kmalloc failed\n");
+		return -1;
+	}
+
+	shared_physical_address = __pa(shared_virtual_address);
+	// shared_physical_address = 0xda00000;
+
+	*kernel_shared_area_addr_ptr = (unsigned long)shared_virtual_address;
+	/* set the physical address of the shared area */
+	*phys_shared_area_addr_ptr = shared_physical_address;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:shared_virtual_address is %p\n",
+	shared_virtual_address);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:shared_region_size is %08lx\n",
+	shared_area_size);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:shared_physical_addr is %08lx\n",
+	*phys_shared_area_addr_ptr);
+
+	return 0;
+}
+
+/*
+  This functions unmaps and deallocates the shared area
+  on the  external RAM (device)
+  The input is shared_area_size - the size of the memory to deallocate,kernel_
+  shared_area_addr_ptr - the kernel address of the mapped and allocated
+  shared area,phys_shared_area_addr_ptr - the physical address of
+  the shared area
+*/
+void sep_unmap_and_free_shared_area(unsigned long   shared_area_size,
+					unsigned long   kernel_shared_area_addr,
+					unsigned long   phys_shared_area_addr)
+{
+	kfree((void *)kernel_shared_area_addr);
+	return;
+}
+
+/*
+  This functions returns the physical address inside shared area according
+  to the virtual address. It can be either on the externa RAM device
+  (ioremapped), or on the system RAM
+  This implementation is for the external RAM
+*/
+unsigned long sep_shared_area_virt_to_phys(unsigned long virt_address)
+{
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:sh virt to phys v %08lx\n",
+	  virt_address);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:sh virt to phys p %08lx\n",
+	  shared_physical_address
+	  + (virt_address - (unsigned long)shared_virtual_address));
+
+	return (unsigned long)shared_physical_address +
+	  (virt_address - (unsigned long)shared_virtual_address);
+}
+
+/*
+  This functions returns the virtual address inside shared area
+  according to the physical address. It can be either on the
+  externa RAM device (ioremapped), or on the system RAM This implementation
+  is for the external RAM
+*/
+unsigned long sep_shared_area_phys_to_virt(unsigned long phys_address)
+{
+	return (unsigned long)shared_virtual_address
+	  + (phys_address - shared_physical_address);
+}
+
+
+/*
+  function that is activaed on the succesfull probe of the SEP device
+*/
+static int __devinit sep_probe(struct pci_dev *pdev,
+			const struct pci_device_id *ent)
+{
+	/* error */
+	int error;
+
+	/*------------------------
+	CODE
+	---------------------------*/
+
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	  "Sep pci probe starting\n");
+	error = 0;
+
+	/* enable the device */
+	error = pci_enable_device(pdev);
+	if (error) {
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "error enabling pci device\n");
+		goto end_function;
+	}
+
+	/* set the pci dev pointer */
+	sep_pci_dev_ptr = pdev;
+
+	/* get the io memory start address */
+	io_memory_start_physical_address = pci_resource_start(pdev, 0);
+	if (!io_memory_start_physical_address) {
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver error pci resource start\n");
+		goto end_function;
+	}
+
+	/* get the io memory end address */
+	io_memory_end_physical_address = pci_resource_end(pdev, 0);
+	if (!io_memory_end_physical_address) {
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver error pci resource end\n");
+		goto end_function;
+	}
+
+	io_memory_size = io_memory_end_physical_address -
+	  io_memory_start_physical_address + 1;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:io_memory_start_physical_address is %08lx\n",
+	io_memory_start_physical_address);
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:io_memory_end_phyaical_address is %08lx\n",
+	io_memory_end_physical_address);
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:io_memory_size is %08lx\n",
+	io_memory_size);
+
+	io_memory_start_virtual_address =
+	  ioremap_nocache(io_memory_start_physical_address,
+	  io_memory_size);
+	if (!io_memory_start_virtual_address) {
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver error ioremap of io memory\n");
+		goto end_function;
+	}
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:io_memory_start_virtual_address is %p\n",
+	io_memory_start_virtual_address);
+
+	g_sep_reg_base_address = (unsigned long)io_memory_start_virtual_address;
+
+
+	/* set up system base address and shared memory location */
+
+	rar_virtual_address = kmalloc(2 * SEP_RAR_IO_MEM_REGION_SIZE,
+	  GFP_KERNEL);
+
+	if (!rar_virtual_address) {
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver:cant kmalloc rar\n");
+		goto end_function;
+		}
+
+	rar_physical_address = __pa(rar_virtual_address);
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:rar_physical is %08lx\n",
+	rar_physical_address);
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver:rar_virtual is %p\n",
+	rar_virtual_address);
+
+
+#if !SEP_DRIVER_POLLING_MODE
+
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver: about to write IMR and ICR REG_ADDR\n");
+
+	/* clear ICR register */
+	SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_ICR_REG_ADDR,
+	  0xFFFFFFFF);
+
+	/* set the IMR register - open only GPR 2 */
+	SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_IMR_REG_ADDR,
+	  (~(0x1 << 13)));
+
+	/* figure out our irq */
+	error = pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, (u8 *)&sep_irq);
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver: my irq is %d\n", sep_irq);
+
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver: about to call request_irq\n");
+	/* get the interrupt line */
+	error = request_irq(sep_irq, sep_inthandler, IRQF_SHARED,
+	  "sep_driver", &g_sep_reg_base_address);
+	if (error)
+		goto end_function;
+
+	goto end_function;
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver: about to write IMR REG_ADDR");
+
+	/* set the IMR register - open only GPR 2 */
+	SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_IMR_REG_ADDR,
+	  (~(0x1 << 13)));
+
+#endif /* SEP_DRIVER_POLLING_MODE */
+
+end_function:
+
+	return error;
+}
+
+/*
+  this function registers th driver to
+  the device subsystem( either PCI, USB, etc)
+*/
+int sep_register_driver_to_device(void)
+{
+	return pci_register_driver(&sep_pci_driver);
+}
+
+
+
+void sep_load_rom_code()
+{
+#if SEP_DRIVER_ARM_DEBUG_MODE
+	/* Index variables */
+	unsigned long i, k, j;
+	unsigned long regVal;
+	unsigned long Error;
+	unsigned long warning;
+
+	/* Loading ROM from SEP_ROM_image.h file */
+	k = sizeof(CRYS_SEP_ROM);
+
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver: DX_CC_TST_SepRomLoader start\n");
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver: k is %lu\n", k);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver: g_sep_reg_base_address is %p\n",
+	  g_sep_reg_base_address);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver: CRYS_SEP_ROM_start_address_offset is %p\n",
+	  CRYS_SEP_ROM_start_address_offset);
+
+	for (i = 0; i < 4; i++) {
+		/* write bank */
+		SEP_WRITE_REGISTER(g_sep_reg_base_address
+		  + SEP_ROM_BANK_register_offset, i);
+
+		for (j = 0; j < CRYS_SEP_ROM_length / 4; j++) {
+			SEP_WRITE_REGISTER(g_sep_reg_base_address +
+			  CRYS_SEP_ROM_start_address_offset + 4*j,
+			  CRYS_SEP_ROM[i * 0x1000 + j]);
+
+			k = k - 4;
+
+			if (k == 0) {
+				j = CRYS_SEP_ROM_length;
+				i = 4;
+			}
+		}
+	}
+
+	/* reset the SEP*/
+	SEP_WRITE_REGISTER(g_sep_reg_base_address
+	  + HW_HOST_SEP_SW_RST_REG_ADDR, 0x1);
+
+	/* poll for SEP ROM boot finish */
+	do {
+		SEP_READ_REGISTER(g_sep_reg_base_address
+		  + HW_HOST_SEP_HOST_GPR3_REG_ADDR, regVal);
+	} while (!regVal);
+
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	  "SEP Driver: ROM polling ended\n");
+
+	switch (regVal) {
+	case 0x1:
+		/* fatal error - read erro status from GPRO */
+		SEP_READ_REGISTER(g_sep_reg_base_address
+		  + HW_HOST_SEP_HOST_GPR0_REG_ADDR, Error);
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver: ROM polling case 1\n");
+		break;
+	case 0x2:
+		/* Boot First Phase ended  */
+		SEP_READ_REGISTER(g_sep_reg_base_address
+		  + HW_HOST_SEP_HOST_GPR0_REG_ADDR, warning);
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver: ROM polling case 2\n");
+		break;
+	case 0x4:
+		/* Cold boot ended successfully  */
+		SEP_READ_REGISTER(g_sep_reg_base_address
+		  + HW_HOST_SEP_HOST_GPR0_REG_ADDR, warning);
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver: ROM polling case 4\n");
+		Error = 0;
+		break;
+	case 0x8:
+		/* Warmboot ended successfully */
+		SEP_READ_REGISTER(g_sep_reg_base_address
+		  + HW_HOST_SEP_HOST_GPR0_REG_ADDR, warning);
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver: ROM polling case 8\n");
+		Error = 0;
+		break;
+	case 0x10:
+		/* ColdWarm boot ended successfully */
+		SEP_READ_REGISTER(g_sep_reg_base_address
+		  + HW_HOST_SEP_HOST_GPR0_REG_ADDR, warning);
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver: ROM polling case 16\n");
+		Error = 0;
+		break;
+	case 0x20:
+		DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		  "SEP Driver: ROM polling case 32\n");
+		break;
+	}
+
+#endif
+}
+
diff --git a/drivers/staging/sep/sep_main_mod.c b/drivers/staging/sep/sep_main_mod.c
new file mode 100644
index 000000000000..158c462135ba
--- /dev/null
+++ b/drivers/staging/sep/sep_main_mod.c
@@ -0,0 +1,3919 @@
+/*
+ *
+ *  sep_main_mod.c - Security Processor Driver main group of functions
+ *
+ *  Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *  Copyright(c) 2009 Discretix. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc., 59
+ *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *  CONTACTS:
+ *
+ *  Mark Allyn		mark.a.allyn@intel.com
+ *
+ *  CHANGES:
+ *
+ *  2009.06.26	Initial publish
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/kdev_t.h>
+#include <linux/mutex.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <asm/ioctl.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <linux/interrupt.h>
+#include <linux/pagemap.h>
+#include <asm/cacheflush.h>
+#include "sep_driver_hw_defs.h"
+#include "sep_driver_config.h"
+#include "sep_driver_api.h"
+#include "sep_driver_ext_api.h"
+
+/*----------------------------------------
+	DEFINES
+-----------------------------------------*/
+
+
+#define INT_MODULE_PARM(n, v) int n = v; module_param(n, int, 0)
+
+/*--------------------------------------
+  TYPEDEFS
+  -----------------------------------------*/
+
+
+
+/*--------------------------------------------
+	GLOBAL variables
+--------------------------------------------*/
+
+/* debug messages level */
+INT_MODULE_PARM(sepDebug, 0x0);
+MODULE_PARM_DESC(sepDebug, "Flag to enable SEP debug messages");
+
+/* address of the shared memory allocated during init for SEP driver */
+static unsigned long			g_sep_shared_area_addr;
+
+/* the physical address of the shared area */
+static unsigned long			g_sep_phys_shared_area_addr;
+
+/* Message Shared Area start address - will be allocated during init */
+static unsigned long			g_message_shared_area_addr;
+
+/* major and minor device numbers */
+static dev_t					g_sep_device_number;
+
+/* the files operations structure of the driver */
+static struct file_operations  g_sep_fops;
+
+/* cdev struct of the driver */
+static struct cdev			g_sep_cdev;
+
+/*
+  mutex for the access to the internals of the sep driver
+*/
+static DEFINE_MUTEX(sep_mutex);
+
+
+/* wait queue head (event) of the driver */
+DECLARE_WAIT_QUEUE_HEAD(g_sep_event);
+
+
+/* start address of the access to the SEP registers from driver */
+unsigned long					g_sep_reg_base_address;
+
+/* transaction counter that coordinates the transactions between SEP and HOST */
+static unsigned long			sep_host_to_sep_send_counter;
+
+/* counter for the messages from sep */
+static unsigned long			sep_sep_to_host_reply_counter;
+
+/* counter for the number of bytes allocated in the pool for the current
+transaction */
+static unsigned long			sep_data_pool_bytes_allocated;
+
+/* array of pointers to the pages that represent input data for the synchronic
+DMA action */
+struct page		**sep_in_page_array;
+
+/* array of pointers to the pages that represent out data for the synchronic
+DMA action */
+struct page		**sep_out_page_array;
+
+/* number of pages in the sep_in_page_array */
+unsigned long					sep_in_num_pages;
+
+/* number of pages in the sep_out_page_array */
+unsigned long					sep_out_num_pages;
+
+/* global data for every flow */
+static struct sep_flow_context_t g_sep_flows_data_array[SEP_DRIVER_NUM_FLOWS];
+
+/* flag for API mode - 1 -is blocking, 0 is non-blocking */
+static unsigned long			g_sep_block_mode_flag;
+
+/* pointer to the workqueue that handles the flow done interrupts */
+static struct workqueue_struct		*g_sep_flow_wq_ptr;
+
+/*------------------------------------------------
+  PROTOTYPES
+---------------------------------------------------*/
+
+/*
+  interrupt handler function
+*/
+irqreturn_t sep_inthandler(int irq, void *dev_id);
+
+/*
+  this function registers the driver to the file system
+*/
+static int  sep_register_driver_to_fs(void);
+
+/*
+  this function unregisters driver from fs
+*/
+static void sep_unregister_driver_from_fs(void);
+
+/*
+  this function calculates the size of data that can be inserted into the lli
+  table from this array the condition is that either the table is full
+  (all etnries are entered), or there are no more entries in the lli array
+*/
+static unsigned long sep_calculate_lli_table_max_size(
+			struct sep_lli_entry_t	*lli_in_array_ptr,
+			unsigned long	num_array_entries);
+/*
+  this functions builds ont lli table from the lli_array according to the
+  given size of data
+*/
+static void sep_build_lli_table(struct sep_lli_entry_t	*lli_array_ptr,
+			struct sep_lli_entry_t		*lli_table_ptr,
+			unsigned long		*num_processed_entries_ptr,
+			unsigned long		*num_table_entries_ptr,
+			unsigned long	table_data_size);
+
+/*
+  this function goes over the list of the print created tables and prints
+  all the data
+*/
+static void sep_debug_print_lli_tables(struct sep_lli_entry_t	*lli_table_ptr,
+					unsigned long	num_table_entries,
+					unsigned long	table_data_size);
+
+
+
+/*
+  This function raises interrupt to SEPm that signals that is has a new
+  command from HOST
+*/
+static void sep_send_command_handler(void);
+
+
+/*
+  This function raises interrupt to SEP that signals that is has a
+  new reply from HOST
+*/
+static void sep_send_reply_command_handler(void);
+
+/*
+  This function handles the allocate data pool memory request
+  This function returns calculates the physical address of the allocated memory
+  and the offset of this area from the mapped address. Therefore, the FVOs in
+  user space can calculate the exact virtual address of this allocated memory
+*/
+static int sep_allocate_data_pool_memory_handler(unsigned long arg);
+
+
+/*
+  This function  handles write into allocated data pool command
+*/
+static int sep_write_into_data_pool_handler(unsigned long arg);
+
+/*
+  this function handles the read from data pool command
+*/
+static int sep_read_from_data_pool_handler(unsigned long arg);
+
+/*
+  this function handles tha request for creation of the DMA table
+  for the synchronic symmetric operations (AES,DES)
+*/
+static int sep_create_sync_dma_tables_handler(unsigned long arg);
+
+/*
+  this function handles the request to create the DMA tables for flow
+*/
+static int sep_create_flow_dma_tables_handler(unsigned long arg);
+
+/*
+  This API handles the end transaction request
+*/
+static int sep_end_transaction_handler(unsigned long arg);
+
+
+/*
+  this function handles add tables to flow
+*/
+static int sep_add_flow_tables_handler(unsigned long arg);
+
+/*
+  this function add the flow add message to the specific flow
+*/
+static int sep_add_flow_tables_message_handler(unsigned long arg);
+
+/*
+  this function handles the request for SEP start
+*/
+static int sep_start_handler(void);
+
+/*
+  this function handles the request for SEP initialization
+*/
+static int sep_init_handler(unsigned long arg);
+
+/*
+  this function handles the request cache and resident reallocation
+*/
+static int sep_realloc_cache_resident_handler(unsigned long arg);
+
+
+/*
+  This api handles the setting of API mode to blocking or non-blocking
+*/
+static int sep_set_api_mode_handler(unsigned long arg);
+
+/* handler for flow done interrupt */
+static void sep_flow_done_handler(struct work_struct		*work);
+
+/*
+  This function locks all the physical pages of the kernel 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
+*/
+static int sep_lock_kernel_pages(unsigned long	kernel_virt_addr,
+				unsigned long	data_size,
+				unsigned long	*num_pages_ptr,
+				struct sep_lli_entry_t	**lli_array_ptr,
+				struct page	***page_array_ptr);
+
+/*
+  This function creates one DMA table for flow and returns its data,
+  and pointer to its info entry
+*/
+static int sep_prepare_one_flow_dma_table(unsigned long	 virt_buff_addr,
+			unsigned long	 virt_buff_size,
+			struct sep_lli_entry_t		*table_data,
+			struct sep_lli_entry_t		**info_entry_ptr,
+			struct sep_flow_context_t	*flow_data_ptr,
+			bool			isKernelVirtualAddress);
+
+/*
+  This function creates a list of tables for flow and returns the data for the
+  first and last tables of the list
+*/
+static int sep_prepare_flow_dma_tables(unsigned long	num_virtual_buffers,
+		unsigned long		first_buff_addr,
+		struct sep_flow_context_t	*flow_data_ptr,
+		struct sep_lli_entry_t		*first_table_data_ptr,
+		struct sep_lli_entry_t		*last_table_data_ptr,
+		bool			isKernelVirtualAddress);
+
+/*
+  this function find a space for the new flow dma table
+*/
+static int sep_find_free_flow_dma_table_space(
+	unsigned long		**table_address_ptr);
+
+/*
+  this function goes over all the flow tables connected to the given table and
+  deallocate them
+*/
+static void sep_deallocated_flow_tables(
+		struct sep_lli_entry_t *first_table_ptr);
+
+/*
+  This function handler the set flow id command
+*/
+static int sep_set_flow_id_handler(unsigned long arg);
+
+/*
+  This function returns pointer to the  flow data structure
+  that conatins the given id
+*/
+static int sep_find_flow_context(unsigned long flow_id,
+				struct sep_flow_context_t **flow_data_ptr);
+
+
+/*
+  this function returns the physical and virtual addresses of the static pool
+*/
+static int sep_get_static_pool_addr_handler(unsigned long arg);
+
+/*
+  this address gets the offset of the physical address from the start of
+  the mapped area
+*/
+static int sep_get_physical_mapped_offset_handler(unsigned long arg);
+
+
+/*
+  this function handles the request for get time
+*/
+static int sep_get_time_handler(unsigned long arg);
+
+/*
+  calculates time and sets it at the predefined address
+*/
+static int sep_set_time(unsigned long	*address_ptr,
+			unsigned long	*time_in_sec_ptr);
+
+/*
+  PATCH for configuring the DMA to single burst instead of multi-burst
+*/
+static void sep_configure_dma_burst(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
+*/
+static int sep_lock_user_pages(unsigned long  app_virt_addr,
+				unsigned long       data_size,
+				unsigned long      *num_pages_ptr,
+				struct sep_lli_entry_t   **lli_array_ptr,
+				struct page      ***page_array_ptr);
+
+/*---------------------------------------------
+	FUNCTIONS
+-----------------------------------------------*/
+
+/*
+  this function locks SEP by locking the semaphore
+*/
+int sep_lock()
+{
+  mutex_lock(&sep_mutex);
+
+  return 0;
+}
+
+/*
+  this function unlocks SEP
+*/
+void sep_unlock()
+{
+  /* release mutex */
+  mutex_unlock(&sep_mutex);
+}
+
+/*
+  this function returns the address of the message shared area
+*/
+void sep_map_shared_area(unsigned long		*mappedAddr_ptr)
+{
+  *mappedAddr_ptr = g_sep_shared_area_addr;
+}
+
+/*
+  this function returns the address of the message shared area
+*/
+void sep_send_msg_rdy_cmd()
+{
+  sep_send_command_handler();
+}
+
+/* this functions frees all the resources that were allocated for the building
+of the LLI DMA tables */
+void sep_free_dma_resources()
+{
+  sep_free_dma_table_data_handler();
+}
+
+/* poll(suspend), until reply from sep */
+void sep_driver_poll()
+{
+  unsigned long	retVal = 0;
+
+#ifdef SEP_DRIVER_POLLING_MODE
+
+  while (sep_host_to_sep_send_counter != (retVal & 0x7FFFFFFF))
+	SEP_READ_REGISTER(g_sep_reg_base_address +
+			HW_HOST_SEP_HOST_GPR2_REG_ADDR,
+			retVal);
+
+  sep_sep_to_host_reply_counter++;
+#else
+  /* poll, until reply from sep */
+  wait_event(g_sep_event,
+  (sep_host_to_sep_send_counter == sep_sep_to_host_reply_counter));
+
+#endif
+}
+
+/*----------------------------------------------------------------------
+  open function of the character driver - must only lock the mutex
+	must also release the memory data pool allocations
+------------------------------------------------------------------------*/
+static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
+{
+  /* return value */
+  int			error;
+
+  /*-----------------
+	CODE
+  ---------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> open start\n");
+
+  error = 0;
+
+  /* check the blocking mode */
+  if (g_sep_block_mode_flag)
+	/* lock mutex */
+	mutex_lock(&sep_mutex);
+  else
+	error = mutex_trylock(&sep_mutex);
+
+  /* check the error */
+  if (error) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver: down_interruptible failed\n");
+
+	goto end_function;
+  }
+
+  /* release data pool allocations */
+  sep_data_pool_bytes_allocated = 0;
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- open end\n");
+
+  return error;
+}
+
+
+
+
+/*------------------------------------------------------------
+	release function
+-------------------------------------------------------------*/
+static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
+{
+  /*-----------------
+	CODE
+  ---------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"----------->SEP Driver: sep_release start\n");
+
+#if 0/*!SEP_DRIVER_POLLING_MODE*/
+  /* close IMR */
+  SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_IMR_REG_ADDR, 0x7FFF);
+
+  /* release IRQ line */
+  free_irq(SEP_DIRVER_IRQ_NUM, &g_sep_reg_base_address);
+
+#endif
+
+  /* unlock the sep mutex */
+  mutex_unlock(&sep_mutex);
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_release end\n");
+
+  return 0;
+}
+
+
+
+
+/*---------------------------------------------------------------
+  map function - this functions maps the message shared area
+-----------------------------------------------------------------*/
+static int sep_mmap(struct file  *filp, struct vm_area_struct  *vma)
+{
+  /* physical addr */
+  unsigned long phys_addr;
+
+  /*-----------------------
+	CODE
+  -------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "-------->SEP Driver: mmap start\n");
+
+  /* check that the size of the mapped range is as the size of the message
+  shared area */
+  if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver mmap requested size is more than allowed\n");
+	printk(KERN_WARNING "SEP Driver mmap requested size is more \
+			than allowed\n");
+	printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
+	vma->vm_end);
+	printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
+	vma->vm_start);
+	return -EAGAIN;
+  }
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+  "SEP Driver:g_message_shared_area_addr is %08lx\n",
+  g_message_shared_area_addr);
+
+  /* get physical address */
+  phys_addr  = g_sep_phys_shared_area_addr;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: phys_addr is %08lx\n",
+phys_addr);
+
+  if (remap_pfn_range(vma,
+	 vma->vm_start,
+	 phys_addr >> PAGE_SHIFT,
+	 vma->vm_end - vma->vm_start,
+	 vma->vm_page_prot)) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver remap_page_range failed\n");
+	printk(KERN_WARNING  "SEP Driver remap_page_range failed\n");
+	return -EAGAIN;
+  }
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- mmap end\n");
+
+  return 0;
+}
+
+
+/*-----------------------------------------------
+  poll function
+*----------------------------------------------*/
+static unsigned int sep_poll(struct file  *filp, poll_table  *wait)
+{
+  unsigned long count;
+
+  unsigned int	mask = 0;
+
+  /* flow id */
+  unsigned long	retVal = 0;
+
+  /*----------------------------------------------
+	CODE
+  -------------------------------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "---------->SEP Driver poll: start\n");
+
+
+#if SEP_DRIVER_POLLING_MODE
+
+  while (sep_host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
+	SEP_READ_REGISTER(g_sep_reg_base_address +
+	HW_HOST_SEP_HOST_GPR2_REG_ADDR,
+	retVal);
+
+	for (count = 0; count < 10 * 4; count += 4)
+	DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+	"Poll Debug Word %lu of the message is %lu\n",
+	count,
+	*((unsigned long *)(g_sep_shared_area_addr +
+	SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
+  }
+
+  sep_sep_to_host_reply_counter++;
+#else
+  /* add the event to the polling wait table */
+  poll_wait(filp, &g_sep_event, wait);
+
+#endif
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"sep_host_to_sep_send_counter is %lu\n",
+		sep_host_to_sep_send_counter);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"sep_sep_to_host_reply_counter is %lu\n",
+	sep_sep_to_host_reply_counter);
+
+  /* check if the data is ready */
+  if (sep_host_to_sep_send_counter ==  sep_sep_to_host_reply_counter) {
+	for (count = 0; count < 12 * 4; count += 4)
+	DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+	"Sep Mesg Word %lu of the message is %lu\n",
+	count, *((unsigned long *)(g_sep_shared_area_addr + count)));
+
+	for (count = 0; count < 10 * 4; count += 4)
+	DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+	"Debug Data Word %lu of the message is %lu\n",
+	count,
+	*((unsigned long *)(g_sep_shared_area_addr + 0x1800 + count)));
+
+	SEP_READ_REGISTER(g_sep_reg_base_address +
+		HW_HOST_SEP_HOST_GPR2_REG_ADDR,
+		retVal);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "retVal is %lu\n", retVal);
+	/* check if the this is sep reply or request */
+	if (retVal >> 31) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: sep request in\n");
+	  /* request */
+	  mask |= POLLOUT | POLLWRNORM;
+	} else {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: sep reply in\n");
+	  mask |= POLLIN | POLLRDNORM;
+	}
+  }
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- poll exit\n");
+  return mask;
+}
+
+
+static int sep_ioctl(struct inode		*inode,
+					struct file		*filp,
+					unsigned int		cmd,
+					unsigned long		arg)
+{
+
+  /* error */
+  int			error;
+
+  /*------------------------
+	CODE
+  ------------------------*/
+  error = 0;
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"------------>SEP Driver: ioctl start\n");
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: cmd is %x\n", cmd);
+
+  /* check that the command is for sep device */
+  if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
+	error = -ENOTTY;
+
+	switch (cmd) {
+	case SEP_IOCSENDSEPCOMMAND:
+
+	  /* send command to SEP */
+	sep_send_command_handler();
+
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver: after sep_send_command_handler\n");
+
+	  break;
+
+	case SEP_IOCSENDSEPRPLYCOMMAND:
+
+	  /* send reply command to SEP */
+	sep_send_reply_command_handler();
+
+	  break;
+
+	case SEP_IOCALLOCDATAPOLL:
+
+	  /* allocate data pool */
+	error = sep_allocate_data_pool_memory_handler(arg);
+
+	  break;
+
+	case SEP_IOCWRITEDATAPOLL:
+
+	  /* write data into memory pool */
+	error = sep_write_into_data_pool_handler(arg);
+
+	  break;
+
+	case SEP_IOCREADDATAPOLL:
+
+	  /* read data from data pool into application memory */
+	error = sep_read_from_data_pool_handler(arg);
+
+	  break;
+
+	case SEP_IOCCREATESYMDMATABLE:
+
+	  /* create dma table for synhronic operation */
+	error = sep_create_sync_dma_tables_handler(arg);
+
+	  break;
+
+	case SEP_IOCCREATEFLOWDMATABLE:
+
+	  /* create flow dma tables */
+	error = sep_create_flow_dma_tables_handler(arg);
+
+	  break;
+
+	case SEP_IOCFREEDMATABLEDATA:
+
+	  /* free the pages */
+	error = sep_free_dma_table_data_handler();
+
+	  break;
+
+	case SEP_IOCSETFLOWID:
+
+	  /* set flow id */
+	error = sep_set_flow_id_handler(arg);
+
+	  break;
+
+	case SEP_IOCADDFLOWTABLE:
+
+	  /* add tables to the dynamic flow */
+	error = sep_add_flow_tables_handler(arg);
+
+	  break;
+
+	case SEP_IOCADDFLOWMESSAGE:
+
+	  /* add message of add tables to flow */
+	error = sep_add_flow_tables_message_handler(arg);
+
+	  break;
+
+	case SEP_IOCSEPSTART:
+
+	  /* start command to sep */
+	error = sep_start_handler();
+	  break;
+
+	case SEP_IOCSEPINIT:
+
+	  /* init command to sep */
+	error = sep_init_handler(arg);
+	  break;
+
+	case SEP_IOCSETAPIMODE:
+
+	  /* set non- blocking mode */
+	error = sep_set_api_mode_handler(arg);
+
+	  break;
+
+	case SEP_IOCGETSTATICPOOLADDR:
+
+		/* get the physical and virtual addresses of the static pool */
+		error = sep_get_static_pool_addr_handler(arg);
+
+		break;
+
+	case SEP_IOCENDTRANSACTION:
+
+	error = sep_end_transaction_handler(arg);
+
+		break;
+
+	case SEP_IOCREALLOCCACHERES:
+
+	error = sep_realloc_cache_resident_handler(arg);
+
+	  break;
+
+	case SEP_IOCGETMAPPEDADDROFFSET:
+
+	error = sep_get_physical_mapped_offset_handler(arg);
+
+	  break;
+	case SEP_IOCGETIME:
+
+	error = sep_get_time_handler(arg);
+
+	  break;
+
+	default:
+	error = -ENOTTY;
+	  break;
+  }
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- ioctl end\n");
+
+  return error;
+}
+
+
+/*
+  this function registers the driver to the file system
+*/
+static int  sep_register_driver_to_fs(void)
+{
+  /* return value */
+  int			ret_val;
+
+  /*---------------------
+	CODE
+  -----------------------*/
+
+  ret_val = alloc_chrdev_region(&g_sep_device_number, 0, 1, "sep_sec_driver");
+  if (ret_val) {
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"sep_driver:major number allocation failed, retval is %d\n", ret_val);
+	goto end_function;
+  }
+
+  /* set the files operations structure */
+  g_sep_fops.owner = THIS_MODULE;
+  g_sep_fops.ioctl = sep_ioctl;
+  g_sep_fops.poll = sep_poll;
+  g_sep_fops.open = sep_open;
+  g_sep_fops.release = sep_release;
+  g_sep_fops.mmap = sep_mmap;
+
+  /* init cdev */
+  cdev_init(&g_sep_cdev, &g_sep_fops);
+  g_sep_cdev.owner = THIS_MODULE;
+
+  /* register the driver with the kernel */
+  ret_val = cdev_add(&g_sep_cdev, g_sep_device_number, 1);
+
+  if (ret_val) {
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"sep_driver:cdev_add failed, retval is %d\n",
+	ret_val);
+	goto end_function_unregister_devnum;
+  }
+
+  goto end_function;
+
+end_function_unregister_devnum:
+
+  /* unregister dev numbers */
+  unregister_chrdev_region(g_sep_device_number, 1);
+
+end_function:
+
+  return ret_val;
+}
+
+/*
+  this function unregisters driver from fs
+*/
+static void sep_unregister_driver_from_fs(void)
+{
+  /*-------------------
+	CODE
+  ---------------------*/
+
+  cdev_del(&g_sep_cdev);
+
+  /* unregister dev numbers */
+  unregister_chrdev_region(g_sep_device_number, 1);
+}
+
+/*--------------------------------------------------------------
+  init function
+----------------------------------------------------------------*/
+static int __init sep_init(void)
+{
+  /* return value */
+  int			ret_val;
+
+  /* counter */
+  int			counter;
+
+  /* size to of memory for allocation */
+  int			size;
+
+  /*------------------------
+	CODE
+  ------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:-------->Init start\n");
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
+	"g_sep_shared_area_addr = %lx\n",
+	(unsigned long)&g_sep_shared_area_addr);
+
+  ret_val = 0;
+
+/* transaction counter that coordinates the transactions between SEP
+	and HOST */
+  sep_host_to_sep_send_counter = 0;
+
+/* counter for the messages from sep */
+  sep_sep_to_host_reply_counter = 0;
+
+/* counter for the number of bytes allocated in the pool
+for the current transaction */
+  sep_data_pool_bytes_allocated = 0;
+
+  /* set the starting mode to blocking */
+  g_sep_block_mode_flag = 1;
+
+
+  ret_val = sep_register_driver_to_device();
+  if (ret_val) {
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"sep_driver:sep_driver_to_device failed, ret_val is %d\n",
+	ret_val);
+	goto end_function_unregister_from_fs;
+  }
+
+  /* calculate the total size for allocation */
+  size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
+		SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
+		SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
+		SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
+		SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
+		SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
+
+
+
+  /* allocate the shared area */
+  if (sep_map_and_alloc_shared_area(size,
+				&g_sep_shared_area_addr,
+				&g_sep_phys_shared_area_addr)) {
+	ret_val = -ENOMEM;
+	/* allocation failed */
+	goto end_function_unmap_io_memory;
+  }
+
+  /* now set the memory regions */
+  g_message_shared_area_addr = g_sep_shared_area_addr;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: g_message_shared_area_addr is %08lx\n",
+	g_message_shared_area_addr);
+
+#if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
+
+  /* send the new SHARED MESSAGE AREA to the SEP */
+  SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_HOST_SEP_GPR1_REG_ADDR,
+			g_sep_phys_shared_area_addr);
+
+  /* poll for SEP response */
+  SEP_READ_REGISTER(g_sep_reg_base_address + HW_HOST_SEP_HOST_GPR1_REG_ADDR,
+			retVal);
+  while (retVal != 0xffffffff && retVal != g_sep_phys_shared_area_addr)
+	SEP_READ_REGISTER(g_sep_reg_base_address +
+			HW_HOST_SEP_HOST_GPR1_REG_ADDR,
+			retVal);
+
+  /* check the return value (register) */
+  if (retVal != g_sep_phys_shared_area_addr) {
+	ret_val = -ENOMEM;
+	goto end_function_deallocate_message_area;
+  }
+
+#endif
+
+  /* init the flow contextes */
+  for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
+	g_sep_flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
+
+  g_sep_flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
+  if (g_sep_flow_wq_ptr == 0) {
+	ret_val = -ENOMEM;
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"sep_driver:flow queue creation failed\n");
+	goto end_function_deallocate_sep_shared_area;
+  }
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver: create flow workqueue \n");
+
+  /* register driver to fs */
+  ret_val = sep_register_driver_to_fs();
+  if (ret_val)
+	goto end_function_deallocate_sep_shared_area;
+
+  /* load the rom code */
+  sep_load_rom_code();
+
+  goto end_function;
+
+end_function_unregister_from_fs:
+
+  /* unregister from fs */
+  sep_unregister_driver_from_fs();
+
+end_function_deallocate_sep_shared_area:
+
+  /* de-allocate shared area */
+  sep_unmap_and_free_shared_area(size,
+				g_sep_shared_area_addr,
+				g_sep_phys_shared_area_addr);
+
+end_function_unmap_io_memory:
+
+  iounmap((void *)g_sep_reg_base_address);
+
+  /* release io memory region */
+  release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,  "SEP Driver:<-------- Init end\n");
+
+  return ret_val;
+}
+
+
+
+
+/*-------------------------------------------------------------
+  exit function
+--------------------------------------------------------------*/
+static void __exit sep_exit(void)
+{
+  /* size */
+  int			size;
+
+  /*-----------------------------
+	CODE
+  --------------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> Exit start\n");
+
+  /* unregister from fs */
+  sep_unregister_driver_from_fs();
+
+  /* calculate the total size for de-allocation */
+  size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
+		SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
+		SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
+		SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
+		SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
+		SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
+
+
+  /* free shared area  */
+  sep_unmap_and_free_shared_area(size,
+				g_sep_shared_area_addr,
+				g_sep_phys_shared_area_addr);
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver: free pages SEP SHARED AREA \n");
+
+  iounmap((void *)g_sep_reg_base_address);
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: iounmap \n");
+
+  /* release io memory region */
+  release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: release_mem_region \n");
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,  "SEP Driver:<-------- Exit end\n");
+}
+
+
+/*
+  interrupt handler function
+*/
+irqreturn_t sep_inthandler(int irq, void *dev_id)
+{
+  /* int error */
+  irqreturn_t			int_error;
+
+  /* error */
+  unsigned long		error;
+
+  /* reg value */
+  unsigned long		reg_val;
+
+  /* flow id */
+  unsigned long		 flow_id;
+
+  /* flow context */
+  struct sep_flow_context_t		*flow_context_ptr;
+
+  /*-----------------------------
+	CODE
+  -----------------------------*/
+
+  int_error = IRQ_HANDLED;
+
+  /* read the IRR register to check if this is SEP interrupt */
+  SEP_READ_REGISTER(g_sep_reg_base_address + HW_HOST_IRR_REG_ADDR, reg_val);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Interrupt - reg is %08lx\n",
+			reg_val);
+
+  /* check if this is the flow interrupt */
+  if (0/*reg_val & (0x1 << 11)*/) {
+	/* read GPRO to find out the which flow is done */
+	SEP_READ_REGISTER(g_sep_reg_base_address + HW_HOST_IRR_REG_ADDR,
+	flow_id);
+
+	/* find the contex of the flow */
+	error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
+	if (error)
+		goto end_function_with_error;
+
+	INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
+
+	/* queue the work */
+	queue_work(g_sep_flow_wq_ptr, &flow_context_ptr->flow_wq);
+
+  } else {
+	/* check if this is reply interrupt from SEP */
+	if (reg_val & (0x1 << 13)) {
+		/* update the counter of reply messages */
+		sep_sep_to_host_reply_counter++;
+
+		/* wake up the waiting process */
+		wake_up(&g_sep_event);
+	} else {
+		int_error = IRQ_NONE;
+		goto end_function;
+	}
+  }
+
+end_function_with_error:
+
+  /* clear the interrupt */
+  SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_ICR_REG_ADDR, reg_val);
+
+end_function:
+
+  return int_error;
+}
+
+
+/*
+  This function prepares only input DMA table for synhronic symmetric
+  operations (HASH)
+*/
+int sep_prepare_input_dma_table(unsigned long	app_virt_addr,
+				unsigned long	data_size,
+				unsigned long	block_size,
+				unsigned long	*lli_table_ptr,
+				unsigned long	*num_entries_ptr,
+				unsigned long	*table_data_size_ptr,
+				bool			isKernelVirtualAddress)
+
+{
+  /* pointer to the info entry of the table - the last entry */
+  struct sep_lli_entry_t		*info_entry_ptr;
+
+  /* array of pointers ot page */
+  struct sep_lli_entry_t		*lli_array_ptr;
+
+  /* points to the first entry to be processed in the lli_in_array */
+  unsigned long		current_entry;
+
+  /* num entries in the virtual buffer */
+  unsigned long		sep_lli_entries;
+
+  /* lli table pointer */
+  struct sep_lli_entry_t		*in_lli_table_ptr;
+
+  /* the total data in one table */
+  unsigned long		table_data_size;
+
+  /* number of entries in lli table */
+  unsigned long		num_entries_in_table;
+
+  /* next table address */
+  unsigned long		lli_table_alloc_addr;
+
+  /* result */
+  unsigned long		result;
+
+  /*------------------------
+	CODE
+  --------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_prepare_input_dma_table start\n");
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:data_size is %lu\n",
+		data_size);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:block_size is %lu\n",
+		block_size);
+
+  /* initialize the pages pointers */
+  sep_in_page_array = 0;
+  sep_in_num_pages = 0;
+
+  if (data_size == 0) {
+	/* special case  - created 2 entries table with zero data */
+	in_lli_table_ptr = (struct sep_lli_entry_t *)(g_sep_shared_area_addr +
+			SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
+	in_lli_table_ptr->physical_address = g_sep_shared_area_addr +
+			SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
+	in_lli_table_ptr->block_size = 0;
+
+	in_lli_table_ptr++;
+	in_lli_table_ptr->physical_address = 0xFFFFFFFF;
+	in_lli_table_ptr->block_size = 0;
+
+	*lli_table_ptr = g_sep_phys_shared_area_addr +
+			SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
+	*num_entries_ptr = 2;
+	*table_data_size_ptr = 0;
+
+	goto end_function;
+  }
+
+  /* check if the pages are in Kernel Virtual Address layout */
+  if (isKernelVirtualAddress == true)
+	/* lock the pages of the kernel buffer and translate them to pages */
+	result = sep_lock_kernel_pages(app_virt_addr,
+					data_size,
+					&sep_in_num_pages,
+					&lli_array_ptr,
+					&sep_in_page_array);
+  else
+	/* lock the pages of the user buffer and translate them to pages */
+	result = sep_lock_user_pages(app_virt_addr,
+				data_size,
+				&sep_in_num_pages,
+				&lli_array_ptr,
+				&sep_in_page_array);
+
+  if (result)
+	return result;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+  "SEP Driver:output sep_in_num_pages is %lu\n",
+  sep_in_num_pages);
+
+  current_entry = 0;
+  info_entry_ptr = 0;
+  sep_lli_entries = sep_in_num_pages;
+
+  /* initiate to point after the message area */
+  lli_table_alloc_addr = g_sep_shared_area_addr +
+		SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
+
+  /* loop till all the entries in in array are not processed */
+  while (current_entry < sep_lli_entries) {
+	/* set the new input and output tables */
+	in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
+
+	lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
+				SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
+
+	/* calculate the maximum size of data for input table */
+	table_data_size = sep_calculate_lli_table_max_size(
+		&lli_array_ptr[current_entry],
+		(sep_lli_entries - current_entry));
+
+	/* now calculate the table size so that it will be module block size */
+	table_data_size = (table_data_size / block_size) * block_size;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:output table_data_size is %lu\n",
+	table_data_size);
+
+	/* construct input lli table */
+	sep_build_lli_table(&lli_array_ptr[current_entry],
+						in_lli_table_ptr,
+						&current_entry,
+						&num_entries_in_table,
+						table_data_size);
+
+	if (info_entry_ptr == 0) {
+	  /* set the output parameters to physical addresses */
+	  *lli_table_ptr = sep_shared_area_virt_to_phys(
+		  (unsigned long)in_lli_table_ptr);
+	  *num_entries_ptr = num_entries_in_table;
+	  *table_data_size_ptr = table_data_size;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:output lli_table_in_ptr is %08lx\n",
+	*lli_table_ptr);
+	} else {
+	  /* update the info entry of the previous in table */
+	info_entry_ptr->physical_address = sep_shared_area_virt_to_phys(
+				(unsigned long)in_lli_table_ptr);
+	info_entry_ptr->block_size = ((num_entries_in_table) << 24) |
+				(table_data_size);
+	}
+
+	/* save the pointer to the info entry of the current tables */
+	info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
+  }
+
+  /* print input tables */
+  sep_debug_print_lli_tables((struct sep_lli_entry_t *)
+			sep_shared_area_phys_to_virt(*lli_table_ptr),
+			*num_entries_ptr,
+			*table_data_size_ptr);
+
+  /* the array of the pages */
+  kfree(lli_array_ptr);
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_prepare_input_dma_table end\n");
+
+  return 0;
+
+}
+
+/*
+  This function builds input and output DMA tables for synhronic
+  symmetric operations (AES, DES). It also checks that each table
+  is of the modular block size
+*/
+int sep_prepare_input_output_dma_table(unsigned long	app_virt_in_addr,
+					unsigned long	app_virt_out_addr,
+					unsigned long	data_size,
+					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,
+					bool 		isKernelVirtualAddress)
+
+{
+  /* array of pointers of page */
+  struct sep_lli_entry_t		*lli_in_array;
+
+  /* array of pointers of page */
+  struct sep_lli_entry_t		*lli_out_array;
+
+  /* result */
+  int				result;
+
+
+  /*------------------------
+	CODE
+  --------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
+
+  result = 0;
+
+  /* initialize the pages pointers */
+  sep_in_page_array = 0;
+  sep_out_page_array = 0;
+
+  /* check if the pages are in Kernel Virtual Address layout */
+  if (isKernelVirtualAddress == true) {
+	/* lock the pages of the kernel buffer and translate them to pages */
+	result = sep_lock_kernel_pages(app_virt_in_addr,
+				data_size,
+				&sep_in_num_pages,
+				&lli_in_array,
+				&sep_in_page_array);
+	if (result) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
+	goto end_function;
+	}
+  } else {
+	/* lock the pages of the user buffer and translate them to pages */
+	result = sep_lock_user_pages(app_virt_in_addr,
+					data_size,
+					&sep_in_num_pages,
+					&lli_in_array,
+					&sep_in_page_array);
+	if (result) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
+	goto end_function;
+	}
+  }
+
+  if (isKernelVirtualAddress == true) {
+	result = sep_lock_kernel_pages(app_virt_out_addr,
+				data_size,
+				&sep_out_num_pages,
+				&lli_out_array,
+				&sep_out_page_array);
+	if (result) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
+	goto end_function_with_error1;
+	}
+  } else {
+	result = sep_lock_user_pages(app_virt_out_addr,
+					data_size,
+					&sep_out_num_pages,
+					&lli_out_array,
+					&sep_out_page_array);
+	if (result) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
+	goto end_function_with_error1;
+	}
+  }
+
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"sep_in_num_pages is %lu\n", sep_in_num_pages);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"sep_out_num_pages is %lu\n", sep_out_num_pages);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n",
+	SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
+
+
+  /* call the fucntion that creates table from the lli arrays */
+  result = sep_construct_dma_tables_from_lli(lli_in_array,
+					sep_in_num_pages,
+					lli_out_array,
+					sep_out_num_pages,
+					 block_size,
+					lli_table_in_ptr,
+					lli_table_out_ptr,
+					in_num_entries_ptr,
+					out_num_entries_ptr,
+					table_data_size_ptr);
+  if (result) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver: sep_construct_dma_tables_from_lli failed\n");
+	goto end_function_with_error2;
+  }
+
+  /* fall through - free the lli entry arrays */
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "in_num_entries_ptr is %08lx\n",
+	*in_num_entries_ptr);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "out_num_entries_ptr is %08lx\n",
+	*out_num_entries_ptr);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "table_data_size_ptr is %08lx\n",
+	*table_data_size_ptr);
+
+
+end_function_with_error2:
+
+  kfree(lli_out_array);
+
+end_function_with_error1:
+
+  kfree(lli_in_array);
+
+end_function:
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
+"SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n",
+(int)result);
+
+  return result;
+
+}
+
+
+/*
+ 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(struct sep_lli_entry_t	*lli_in_array,
+					unsigned long	sep_in_lli_entries,
+					struct 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)
+{
+  /* points to the area where next lli table can be allocated */
+  unsigned long	lli_table_alloc_addr;
+
+  /* input lli table */
+  struct sep_lli_entry_t		*in_lli_table_ptr;
+
+  /* output lli table */
+  struct sep_lli_entry_t		*out_lli_table_ptr;
+
+  /* pointer to the info entry of the table - the last entry */
+  struct sep_lli_entry_t		*info_in_entry_ptr;
+
+  /* pointer to the info entry of the table - the last entry */
+  struct sep_lli_entry_t		*info_out_entry_ptr;
+
+  /* points to the first entry to be processed in the lli_in_array */
+  unsigned long	current_in_entry;
+
+  /* points to the first entry to be processed in the lli_out_array */
+  unsigned long	current_out_entry;
+
+  /* max size of the input table */
+  unsigned long	in_table_data_size;
+
+  /* max size of the output table */
+  unsigned long	out_table_data_size;
+
+  /* flag te signifies if this is the first tables build from the arrays */
+  unsigned long	  first_table_flag;
+
+  /* the data size that should be in table */
+  unsigned long	table_data_size;
+
+  /* number of etnries in the input table */
+  unsigned long	num_entries_in_table;
+
+  /* number of etnries in the output table */
+  unsigned long	num_entries_out_table;
+
+  /*---------------------
+	CODE
+  ------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
+
+  /* initiate to pint after the message area */
+  lli_table_alloc_addr = g_sep_shared_area_addr +
+	SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
+
+  current_in_entry = 0;
+  current_out_entry = 0;
+  first_table_flag = 1;
+  info_in_entry_ptr = 0;
+  info_out_entry_ptr = 0;
+
+  /* loop till all the entries in in array are not processed */
+  while (current_in_entry < sep_in_lli_entries) {
+	/* set the new input and output tables */
+	in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
+
+	lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
+			SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
+
+	/* set the first output tables */
+	out_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
+
+	lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
+				SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
+
+	/* calculate the maximum size of data for input table */
+	in_table_data_size =
+			sep_calculate_lli_table_max_size(
+			&lli_in_array[current_in_entry],
+			(sep_in_lli_entries - current_in_entry));
+
+	/* calculate the maximum size of data for output table */
+	out_table_data_size =
+			sep_calculate_lli_table_max_size(
+			&lli_out_array[current_out_entry],
+			(sep_out_lli_entries - current_out_entry));
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
+
+	/* check where the data is smallest */
+	table_data_size = in_table_data_size;
+	if (table_data_size > out_table_data_size)
+	table_data_size = out_table_data_size;
+
+	/* now calculate the table size so that it will be module block size */
+	table_data_size = (table_data_size / block_size) * block_size;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:table_data_size is %lu\n",
+		table_data_size);
+
+	/* construct input lli table */
+	sep_build_lli_table(&lli_in_array[current_in_entry],
+						in_lli_table_ptr,
+						&current_in_entry,
+						&num_entries_in_table,
+						table_data_size);
+
+	/* construct output lli table */
+	sep_build_lli_table(&lli_out_array[current_out_entry],
+						out_lli_table_ptr,
+						&current_out_entry,
+						&num_entries_out_table,
+						table_data_size);
+
+	/* if info entry is null - this is the first table built */
+	if (info_in_entry_ptr == 0) {
+	  /* set the output parameters to physical addresses */
+	  *lli_table_in_ptr =
+		sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
+	  *in_num_entries_ptr = num_entries_in_table;
+	  *lli_table_out_ptr =
+		sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
+	  *out_num_entries_ptr = num_entries_out_table;
+	  *table_data_size_ptr = table_data_size;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
+	} else {
+	  /* update the info entry of the previous in table */
+	info_in_entry_ptr->physical_address =
+		sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
+	info_in_entry_ptr->block_size =
+		((num_entries_in_table) << 24) | (table_data_size);
+
+	  /* update the info entry of the previous in table */
+	info_out_entry_ptr->physical_address =
+		sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
+	info_out_entry_ptr->block_size =
+		((num_entries_out_table) << 24) | (table_data_size);
+	}
+
+	/* save the pointer to the info entry of the current tables */
+	info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
+	info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver:output num_entries_out_table is %lu\n",
+		(unsigned long)num_entries_out_table);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver:output info_in_entry_ptr is %lu\n",
+		(unsigned long)info_in_entry_ptr);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver:output info_out_entry_ptr is %lu\n",
+		(unsigned long)info_out_entry_ptr);
+  }
+
+  /* print input tables */
+  sep_debug_print_lli_tables(
+	(struct sep_lli_entry_t *)
+	sep_shared_area_phys_to_virt(*lli_table_in_ptr),
+	*in_num_entries_ptr,
+	*table_data_size_ptr);
+
+  /* print output tables */
+  sep_debug_print_lli_tables(
+	(struct sep_lli_entry_t *)
+	sep_shared_area_phys_to_virt(*lli_table_out_ptr),
+	*out_num_entries_ptr,
+	*table_data_size_ptr);
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
+
+  return 0;
+}
+
+/*
+  this function calculates the size of data that can be inserted into the lli
+  table from this array the condition is that either the table is full
+  (all etnries are entered), or there are no more entries in the lli array
+*/
+unsigned long sep_calculate_lli_table_max_size(
+			struct sep_lli_entry_t	*lli_in_array_ptr,
+			unsigned long	num_array_entries)
+{
+  /* table data size */
+  unsigned long table_data_size;
+
+  /* counter */
+  unsigned long counter;
+
+  /*---------------------
+	CODE
+  ----------------------*/
+
+  table_data_size = 0;
+
+  /* calculate the data in the out lli table if till we fill the whole
+  table or till the data has ended */
+  for (counter = 0;
+	(counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) &&
+	(counter < num_array_entries); counter++)
+	table_data_size += lli_in_array_ptr[counter].block_size;
+
+  return table_data_size;
+}
+
+/*
+  this functions builds ont lli table from the lli_array according to
+  the given size of data
+*/
+static void sep_build_lli_table(struct sep_lli_entry_t	*lli_array_ptr,
+				struct sep_lli_entry_t	*lli_table_ptr,
+				unsigned long	*num_processed_entries_ptr,
+				unsigned long	*num_table_entries_ptr,
+				unsigned long	table_data_size)
+{
+  /* current table data size */
+  unsigned long curr_table_data_size;
+
+  /* counter of lli array entry */
+  unsigned long array_counter;
+
+  /*-----------------------
+	CODE
+  ---------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_build_lli_table start\n");
+
+  /* init currrent table data size and lli array entry counter */
+  curr_table_data_size = 0;
+  array_counter = 0;
+  *num_table_entries_ptr = 1;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+  "SEP Driver:table_data_size is %lu\n",
+	table_data_size);
+
+  /* fill the table till table size reaches the needed amount */
+  while (curr_table_data_size < table_data_size) {
+	/* update the number of entries in table */
+	(*num_table_entries_ptr)++;
+
+	lli_table_ptr->physical_address =
+		lli_array_ptr[array_counter].physical_address;
+	lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
+	curr_table_data_size += lli_table_ptr->block_size;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:lli_table_ptr is %08lx\n",
+	(unsigned long)lli_table_ptr);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:lli_table_ptr->physical_address is %08lx\n",
+	lli_table_ptr->physical_address);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:lli_table_ptr->block_size is %lu\n",
+	lli_table_ptr->block_size);
+
+	/* check for overflow of the table data */
+	if (curr_table_data_size > table_data_size) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver:curr_table_data_size > table_data_size\n");
+
+	  /* update the size of block in the table */
+	lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
+
+	  /* update the physical address in the lli array */
+	lli_array_ptr[array_counter].physical_address +=
+			lli_table_ptr->block_size;
+
+	  /* update the block size left in the lli array */
+	lli_array_ptr[array_counter].block_size =
+			(curr_table_data_size - table_data_size);
+	} else
+	  /* advance to the next entry in the lli_array */
+	  array_counter++;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:lli_table_ptr->physical_address is %08lx\n",
+	lli_table_ptr->physical_address);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:lli_table_ptr->block_size is %lu\n",
+	lli_table_ptr->block_size);
+
+	/* move to the next entry in table */
+	lli_table_ptr++;
+  }
+
+  /* set the info entry to default */
+  lli_table_ptr->physical_address = 0xffffffff;
+  lli_table_ptr->block_size = 0;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:lli_table_ptr is %08lx\n",
+	(unsigned long)lli_table_ptr);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:lli_table_ptr->physical_address is %08lx\n",
+	lli_table_ptr->physical_address);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:lli_table_ptr->block_size is %lu\n",
+	lli_table_ptr->block_size);
+
+
+  /* set the output parameter */
+  *num_processed_entries_ptr += array_counter;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:*num_processed_entries_ptr is %lu\n",
+	*num_processed_entries_ptr);
+
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_build_lli_table end\n");
+
+  return;
+}
+
+/*
+  this function goes over the list of the print created tables and
+  prints all the data
+*/
+static void sep_debug_print_lli_tables(struct sep_lli_entry_t	*lli_table_ptr,
+					unsigned long	num_table_entries,
+					unsigned long	table_data_size)
+{
+  unsigned long table_count;
+
+  unsigned long entries_count;
+  /*-----------------------------
+	CODE
+  -------------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_debug_print_lli_tables start\n");
+
+  table_count = 1;
+  while ((unsigned long)lli_table_ptr != 0xffffffff) {
+	DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: lli table %08lx, table_data_size is %lu\n",
+	table_count,
+	table_data_size);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: num_table_entries is %lu\n", num_table_entries);
+
+	/* print entries of the table (without info entry) */
+	for (entries_count = 0;
+		entries_count < num_table_entries;
+		entries_count++, lli_table_ptr++) {
+		DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver:lli_table_ptr address is %08lx\n",
+		(unsigned long)lli_table_ptr);
+		DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver:phys address is %08lx block size is %lu\n",
+		lli_table_ptr->physical_address, lli_table_ptr->block_size);
+	}
+
+	/* point to the info entry */
+	lli_table_ptr--;
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:phys lli_table_ptr->block_size is %lu\n",
+	lli_table_ptr->block_size);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:phys lli_table_ptr->physical_address is %08lx\n",
+	lli_table_ptr->physical_address);
+
+
+	table_data_size = lli_table_ptr->block_size & 0xffffff;
+	num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
+	lli_table_ptr = (struct sep_lli_entry_t *)
+				(lli_table_ptr->physical_address);
+
+	DEBUG_PRINT_3(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:phys table_data_size is %lu num_table_entries is \
+	%lu lli_table_ptr is%lu\n",
+	table_data_size, num_table_entries, (unsigned long)lli_table_ptr);
+
+	if ((unsigned long)lli_table_ptr != 0xffffffff)
+	lli_table_ptr = (struct sep_lli_entry_t *)sep_shared_area_phys_to_virt(
+					(unsigned long)lli_table_ptr);
+
+	table_count++;
+  }
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_debug_print_lli_tables end\n");
+}
+
+
+/*
+  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,
+			struct sep_lli_entry_t		**lli_array_ptr,
+			struct page		***page_array_ptr)
+
+{
+  /* error */
+  int				error;
+
+  /* the the page of the end address of the user space buffer */
+  unsigned long		end_page;
+
+  /* the page of the start address of the user space buffer */
+  unsigned long		start_page;
+
+  /* the range in pages */
+  unsigned long		num_pages;
+
+  /* array of pointers ot page */
+  struct page		**page_array;
+
+  /* array of lli */
+  struct sep_lli_entry_t		*lli_array;
+
+  /* count */
+  unsigned long		count;
+
+  /* result */
+  int				result;
+
+  /*------------------------
+	CODE
+  --------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_lock_user_pages start\n");
+
+  error = 0;
+
+  /* set start and end pages  and num pages */
+  end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
+  start_page = app_virt_addr >> PAGE_SHIFT;
+  num_pages = end_page - start_page + 1;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: app_virt_addr is %08lx\n",
+	app_virt_addr);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: data_size is %lu\n",
+	data_size);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: start_page is %lu\n",
+	start_page);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: end_page is %lu\n",
+	end_page);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: num_pages is %lu\n",
+	num_pages);
+
+  /* allocate array of pages structure pointers */
+  page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
+  if (!page_array) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver: kmalloc for page_array failed\n");
+
+	error = -ENOMEM;
+	goto end_function;
+  }
+
+  lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
+  if (!lli_array) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver: kmalloc for lli_array failed\n");
+
+	error = -ENOMEM;
+	goto end_function_with_error1;
+  }
+
+  /* convert the application virtual address into a set of physical */
+  down_read(&current->mm->mmap_sem);
+  result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0,
+	page_array,
+	0);
+  up_read(&current->mm->mmap_sem);
+
+  /* check the number of pages locked - if not all then exit with error */
+  if (result != num_pages) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver: not all pages locked by get_user_pages\n");
+
+	error = -ENOMEM;
+	goto end_function_with_error2;
+  }
+
+  /* flush the cache */
+  for (count = 0; count < num_pages; count++)
+	flush_dcache_page(page_array[count]);
+
+  /* set the start address of the first page - app data may start not at
+	the beginning of the page */
+  lli_array[0].physical_address = (
+			(unsigned long)page_to_phys(page_array[0])) +
+			(app_virt_addr & (~PAGE_MASK)) ;
+
+  /* check that not all the data is in the first page only */
+  if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
+	lli_array[0].block_size = data_size;
+  else
+	lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
+
+  /* debug print */
+  DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+  "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
+	lli_array[0].physical_address,
+	lli_array[0].block_size);
+
+  /* go from the second page to the prev before last */
+  for (count = 1; count < (num_pages - 1); count++) {
+	lli_array[count].physical_address =
+		(unsigned long)page_to_phys(page_array[count]);
+	lli_array[count].block_size = PAGE_SIZE;
+
+	DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
+	"lli_array[%lu].physical_address is %08lx, \
+	lli_array[%lu].block_size is %lu\n",
+	count, lli_array[count].physical_address,
+	count,
+	lli_array[count].block_size);
+  }
+
+  /* if more then 1 pages locked - then update for the last page size needed */
+  if (num_pages > 1) {
+	/* update the address of the last page */
+	lli_array[count].physical_address =
+		(unsigned long)page_to_phys(page_array[count]);
+
+	/* set the size of the last page */
+	lli_array[count].block_size = (app_virt_addr + data_size) &
+					(~PAGE_MASK);
+
+	if (lli_array[count].block_size == 0) {
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
+	"app_virt_addr is %08lx\n",
+	app_virt_addr);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
+	  while (1);
+	}
+	DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
+	"lli_array[%lu].physical_address is %08lx, \
+		lli_array[%lu].block_size is %lu\n",
+	count, lli_array[count].physical_address,
+	count,
+	lli_array[count].block_size);
+  }
+
+  /* set output params */
+  *lli_array_ptr = lli_array;
+  *num_pages_ptr = num_pages;
+  *page_array_ptr = page_array;
+
+  goto end_function;
+
+end_function_with_error2:
+
+  /* release the cache */
+  for (count = 0; count < num_pages; count++)
+	page_cache_release(page_array[count]);
+
+  /* free lli array */
+  kfree(lli_array);
+
+end_function_with_error1:
+
+  /* free page array */
+  kfree(page_array);
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_lock_user_pages end\n");
+
+  return 0;
+}
+
+/*
+  This function locks all the physical pages of the kernel 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_kernel_pages(unsigned long		kernel_virt_addr,
+			unsigned long		data_size,
+			unsigned long		*num_pages_ptr,
+			struct sep_lli_entry_t		**lli_array_ptr,
+			struct page		***page_array_ptr)
+
+{
+  /* error */
+  int				error;
+
+  /* the the page of the end address of the user space buffer */
+  unsigned long		end_page;
+
+  /* the page of the start address of the user space buffer */
+  unsigned long		start_page;
+
+  /* the range in pages */
+  unsigned long		num_pages;
+
+  /* array of lli */
+  struct sep_lli_entry_t		*lli_array;
+
+  /* next kernel address to map */
+  unsigned long		next_kernel_address;
+
+  /* count */
+  unsigned long		count;
+
+
+  /*------------------------
+	CODE
+  --------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_lock_kernel_pages start\n");
+
+  error = 0;
+
+  /* set start and end pages  and num pages */
+  end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
+  start_page = kernel_virt_addr >> PAGE_SHIFT;
+  num_pages = end_page - start_page + 1;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: kernel_virt_addr is %08lx\n",
+	kernel_virt_addr);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: data_size is %lu\n",
+	data_size);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: start_page is %lx\n",
+	start_page);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: end_page is %lx\n",
+	end_page);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver: num_pages is %lu\n",
+	num_pages);
+
+  lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
+  if (!lli_array) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver: kmalloc for lli_array failed\n");
+
+	error = -ENOMEM;
+	goto end_function;
+  }
+
+  /* set the start address of the first page - app data may start not at
+  the beginning of the page */
+  lli_array[0].physical_address =
+	(unsigned long)virt_to_phys((unsigned long *)kernel_virt_addr);
+
+  /* check that not all the data is in the first page only */
+  if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
+	lli_array[0].block_size = data_size;
+  else
+	lli_array[0].block_size =
+		PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
+
+  /* debug print */
+  DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+  "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
+	lli_array[0].physical_address,
+	lli_array[0].block_size);
+
+  /* advance the address to the start of the next page */
+  next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
+
+  /* go from the second page to the prev before last */
+  for (count = 1; count < (num_pages - 1); count++) {
+	lli_array[count].physical_address =
+	(unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
+	lli_array[count].block_size = PAGE_SIZE;
+
+	DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
+	"lli_array[%lu].physical_address is %08lx, \
+	lli_array[%lu].block_size is %lu\n",
+	count, lli_array[count].physical_address, count,
+	lli_array[count].block_size);
+
+	next_kernel_address += PAGE_SIZE;
+  }
+
+  /* if more then 1 pages locked - then update for the last page size needed */
+  if (num_pages > 1) {
+	/* update the address of the last page */
+	lli_array[count].physical_address =
+	(unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
+
+	/* set the size of the last page */
+	lli_array[count].block_size =
+		(kernel_virt_addr + data_size) & (~PAGE_MASK);
+
+	if (lli_array[count].block_size == 0) {
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
+	"app_virt_addr is %08lx\n",
+	kernel_virt_addr);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
+	  while (1);
+	}
+
+	DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
+	"lli_array[%lu].physical_address is %08lx, \
+	lli_array[%lu].block_size is %lu\n",
+	count, lli_array[count].physical_address,
+	count,
+	lli_array[count].block_size);
+  }
+
+  /* set output params */
+  *lli_array_ptr = lli_array;
+  *num_pages_ptr = num_pages;
+  *page_array_ptr = 0;
+
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_lock_kernel_pages end\n");
+
+  return 0;
+}
+
+/*
+  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)
+{
+  /* count */
+  unsigned long count;
+
+  /*-------------------
+	CODE
+  ---------------------*/
+
+  if (dirtyFlag) {
+	for (count = 0; count < num_pages; count++) {
+	  /* the out array was written, therefore the data was changed */
+	if (!PageReserved(page_array_ptr[count]))
+		SetPageDirty(page_array_ptr[count]);
+	  page_cache_release(page_array_ptr[count]);
+	}
+  } else {
+	/* free in pages - the data was only read, therefore no update was done
+		on those pages */
+	for (count = 0; count < num_pages; count++)
+	  page_cache_release(page_array_ptr[count]);
+  }
+
+  if (page_array_ptr)
+	/* free the array */
+	kfree(page_array_ptr);
+
+  return 0;
+}
+
+/*
+  This function raises interrupt to SEP that signals that is has a new
+	command from HOST
+*/
+static void sep_send_command_handler()
+{
+
+  unsigned long count;
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_send_command_handler start\n");
+
+  sep_set_time(0, 0);
+
+  /* flash cache */
+  flush_cache_all();
+
+  for (count = 0; count < 12 * 4; count += 4)
+	DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+	"Word %lu of the message is %lu\n",
+	count,
+	*((unsigned long *)(g_sep_shared_area_addr + count)));
+
+  /* update counter */
+  sep_host_to_sep_send_counter++;
+
+  /* send interrupt to SEP */
+  SEP_WRITE_REGISTER(g_sep_reg_base_address +
+			HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_send_command_handler end\n");
+
+  return;
+}
+
+/*
+  This function raises interrupt to SEPm that signals that is has a
+  new command from HOST
+*/
+static void sep_send_reply_command_handler()
+{
+  unsigned long count;
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_send_reply_command_handler start\n");
+
+  /* flash cache */
+  flush_cache_all();
+
+  for (count = 0; count < 12 * 4; count += 4)
+	DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+	"Word %lu of the message is %lu\n",
+	count,
+	*((unsigned long *)(g_sep_shared_area_addr + count)));
+
+
+  /* update counter */
+  sep_host_to_sep_send_counter++;
+
+  /* send the interrupt to SEP */
+  SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_HOST_SEP_GPR2_REG_ADDR,
+				sep_host_to_sep_send_counter);
+
+  /* update both counters */
+  sep_host_to_sep_send_counter++;
+
+  sep_sep_to_host_reply_counter++;
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_send_reply_command_handler end\n");
+
+  return;
+}
+
+
+
+/*
+  This function handles the allocate data pool memory request
+  This function returns calculates the physical address of the
+  allocated memory, and the offset of this area from the mapped address.
+  Therefore, the FVOs in user space can calculate the exact virtual
+  address of this allocated memory
+*/
+static int sep_allocate_data_pool_memory_handler(unsigned long arg)
+{
+  /* error */
+  int				error;
+
+  /* command paramaters */
+  struct sep_driver_alloc_t  command_args;
+
+  /*-------------------------
+	CODE
+  ----------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
+
+
+  error = copy_from_user(&command_args,
+	(void *)arg,
+	sizeof(struct sep_driver_alloc_t));
+  if (error)
+	goto end_function;
+
+  /* allocate memory */
+  if (
+	(sep_data_pool_bytes_allocated + command_args.num_bytes) >
+	SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
+	error = -ENOTTY;
+	goto end_function;
+  }
+
+  /* set the virtual and physical address */
+  command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
+			sep_data_pool_bytes_allocated;
+  command_args.phys_address = g_sep_phys_shared_area_addr +
+			SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
+			sep_data_pool_bytes_allocated;
+
+  /* write the memory back to the user space */
+  error = copy_to_user((void *)arg,
+	(void *)&command_args,
+	sizeof(struct sep_driver_alloc_t));
+  if (error)
+	goto end_function;
+
+  /* set the allocation */
+  sep_data_pool_bytes_allocated += command_args.num_bytes;
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
+
+  return error;
+}
+
+/*
+  This function  handles write into allocated data pool command
+*/
+static int sep_write_into_data_pool_handler(unsigned long arg)
+{
+  /* error */
+  int			error;
+
+  /* virtual address */
+  unsigned long	virt_address;
+
+  /* application in address */
+  unsigned long	app_in_address;
+
+  /* number of bytes */
+  unsigned long	num_bytes;
+
+  /* address of the data pool */
+  unsigned long	data_pool_area_addr;
+
+  /*--------------------------
+	CODE
+  -----------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_write_into_data_pool_handler start\n");
+
+  /* get the application address */
+  error = get_user(app_in_address,
+		&(((struct sep_driver_write_t *)arg)->app_address));
+  if (error)
+	goto end_function;
+
+  /* get the virtual kernel address address */
+  error = get_user(virt_address,
+		&(((struct sep_driver_write_t *)arg)->datapool_address));
+  if (error)
+	goto end_function;
+
+  /* get the number of bytes */
+  error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
+  if (error)
+	goto end_function;
+
+  /* calculate the start of the data pool */
+  data_pool_area_addr = g_sep_shared_area_addr +
+			SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
+
+
+  /* check that the range of the virtual kernel address is correct */
+  if ((virt_address < data_pool_area_addr) ||
+	  (virt_address > (data_pool_area_addr +
+	  SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
+	error = -ENOTTY;
+	goto end_function;
+  }
+
+  /* copy the application data */
+  error = copy_from_user((void *)virt_address,
+	(void *)app_in_address,
+	num_bytes);
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
+
+  return error;
+}
+
+/*
+  this function handles the read from data pool command
+*/
+static int sep_read_from_data_pool_handler(unsigned long arg)
+{
+  /* error */
+  int			error;
+
+  /* virtual address of dest application buffer */
+  unsigned long	app_out_address;
+
+  /* virtual address of the data pool */
+  unsigned long	virt_address;
+
+  /* number bytes */
+  unsigned long	num_bytes;
+
+  /* address of the data pool */
+  unsigned long	data_pool_area_addr;
+
+  /*------------------------
+	CODE
+  -----------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_read_from_data_pool_handler start\n");
+
+  /* get the application address */
+  error = get_user(app_out_address,
+		&(((struct sep_driver_write_t *)arg)->app_address));
+  if (error)
+	goto end_function;
+
+  /* get the virtual kernel address address */
+  error = get_user(virt_address,
+	&(((struct sep_driver_write_t *)arg)->datapool_address));
+  if (error)
+	goto end_function;
+
+  /* get the number of bytes */
+  error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
+  if (error)
+	goto end_function;
+
+  /* calculate the start of the data pool */
+  data_pool_area_addr = g_sep_shared_area_addr +
+			SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
+
+  /* check that the range of the virtual kernel address is correct */
+  if ((virt_address < data_pool_area_addr) ||
+	  (virt_address > (data_pool_area_addr +
+	  SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
+	error = -ENOTTY;
+	goto end_function;
+  }
+
+  /* copy the application data */
+  error = copy_to_user((void *)app_out_address, (void *)virt_address,
+  num_bytes);
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
+
+  return error;
+}
+
+
+/*
+  this function handles tha request for creation of the DMA table
+  for the synchronic symmetric operations (AES,DES)
+*/
+static int sep_create_sync_dma_tables_handler(unsigned long arg)
+{
+  /* error */
+  int							error;
+
+  /* command arguments */
+  struct sep_driver_build_sync_table_t command_args;
+
+  /*------------------------
+	CODE
+  --------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
+
+  error = copy_from_user(&command_args,
+	(void *)arg,
+	sizeof(struct sep_driver_build_sync_table_t));
+  if (error)
+	goto end_function;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"app_in_address is %08lx\n",
+	command_args.app_in_address);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"app_out_address is %08lx\n",
+	command_args.app_out_address);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"data_size is %lu\n",
+	command_args.data_in_size);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"block_size is %lu\n",
+	command_args.block_size);
+
+
+  /* check if we need to build only input table or input/output */
+  if (command_args.app_out_address)
+	/* prepare input and output tables */
+	error = sep_prepare_input_output_dma_table(command_args.app_in_address,
+					command_args.app_out_address,
+					command_args.data_in_size,
+					command_args.block_size,
+					&command_args.in_table_address,
+					&command_args.out_table_address,
+					&command_args.in_table_num_entries,
+					&command_args.out_table_num_entries,
+					&command_args.table_data_size,
+					command_args.isKernelVirtualAddress);
+  else
+	/* prepare input tables */
+	error = sep_prepare_input_dma_table(command_args.app_in_address,
+					command_args.data_in_size,
+					command_args.block_size,
+					&command_args.in_table_address,
+					&command_args.in_table_num_entries,
+					&command_args.table_data_size,
+					command_args.isKernelVirtualAddress);
+
+  if (error)
+	goto end_function;
+
+  /* copy to user */
+  error = copy_to_user((void *)arg,
+	(void *)&command_args,
+	sizeof(struct sep_driver_build_sync_table_t));
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
+
+  return error;
+}
+
+/*
+  this function handles the request for freeing dma table for synhronic actions
+*/
+int sep_free_dma_table_data_handler()
+{
+  /*-------------------------
+	CODE
+  -----------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_free_dma_table_data_handler start\n");
+
+  /* free input pages array */
+  sep_free_dma_pages(sep_in_page_array,
+					sep_in_num_pages,
+					 0);
+
+  /* free output pages array if needed */
+  if (sep_out_page_array)
+	sep_free_dma_pages(sep_out_page_array,
+						sep_out_num_pages,
+						1);
+
+  /* reset all the values */
+  sep_in_page_array = 0;
+  sep_out_page_array = 0;
+  sep_in_num_pages = 0;
+  sep_out_num_pages = 0;
+
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
+
+  return 0;
+}
+
+/*
+  this function handles the request to create the DMA tables for flow
+*/
+static int sep_create_flow_dma_tables_handler(unsigned long arg)
+{
+  /* error */
+  int							error;
+
+  /* command arguments */
+  struct sep_driver_build_flow_table_t	command_args;
+
+  /* first table - output */
+  struct sep_lli_entry_t				 first_table_data;
+
+  /* dma table data */
+  struct sep_lli_entry_t				last_table_data;
+
+  /* pointer to the info entry of the previuos DMA table */
+  struct sep_lli_entry_t		*prev_info_entry_ptr;
+
+  /* pointer to the flow data strucutre */
+  struct sep_flow_context_t		*flow_context_ptr;
+
+  /*------------------------
+	CODE
+  --------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
+
+  /* init variables */
+  prev_info_entry_ptr = 0;
+  first_table_data.physical_address = 0xffffffff;
+
+  /* find the free structure for flow data */
+  error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
+  if (error)
+	goto end_function;
+
+  error = copy_from_user(&command_args,
+	(void *)arg,
+	sizeof(struct sep_driver_build_flow_table_t));
+  if (error)
+	goto end_function;
+
+  /* create flow tables */
+  error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
+					command_args.virt_buff_data_addr,
+					flow_context_ptr,
+					&first_table_data,
+					&last_table_data,
+					command_args.isKernelVirtualAddress);
+  if (error)
+	goto end_function_with_error;
+
+  /* check if flow is static */
+  if (!command_args.flow_type)
+	/* point the info entry of the last to the info entry of the first */
+	last_table_data = first_table_data;
+
+  /* set output params */
+  command_args.first_table_addr = first_table_data.physical_address;
+  command_args.first_table_num_entries =
+	((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) &
+	SEP_NUM_ENTRIES_MASK);
+  command_args.first_table_data_size =
+	(first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
+
+  /* send the parameters to user application */
+  error = copy_to_user((void *)arg,
+	&command_args,
+	sizeof(struct sep_driver_build_flow_table_t));
+  if (error)
+	goto end_function_with_error;
+
+  /* all the flow created  - update the flow entry with temp id */
+  flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
+
+  /* set the processing tables data in the context */
+  if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
+	flow_context_ptr->input_tables_in_process = first_table_data;
+  else
+	flow_context_ptr->output_tables_in_process = first_table_data;
+
+  goto end_function;
+
+end_function_with_error:
+
+  /* free the allocated tables */
+  sep_deallocated_flow_tables(&first_table_data);
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
+
+  return error;
+
+}
+
+/*
+  this functio n handles add tables to flow
+*/
+static int sep_add_flow_tables_handler(unsigned long arg)
+{
+  /* error */
+  int							error;
+
+  /* number of entries */
+  unsigned long				num_entries;
+
+  /* command arguments */
+  struct sep_driver_add_flow_table_t	command_args;
+
+  /* pointer to the flow data strucutre */
+  struct sep_flow_context_t		*flow_context_ptr;
+
+  /* first dma table data */
+  struct sep_lli_entry_t		first_table_data;
+
+  /* last dma table data */
+  struct sep_lli_entry_t		last_table_data;
+
+  /* pointer to the info entry of the current DMA table */
+  struct sep_lli_entry_t		*info_entry_ptr;
+
+  /*--------------------------
+	CODE
+  ----------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_add_flow_tables_handler start\n");
+
+  /* get input parameters */
+  error = copy_from_user(&command_args,
+	(void *)arg,
+	sizeof(struct sep_driver_add_flow_table_t));
+  if (error)
+	goto end_function;
+
+  /* find the flow structure for the flow id */
+  error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
+  if (error)
+	goto end_function;
+
+  /* prepare the flow dma tables */
+  error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
+					command_args.virt_buff_data_addr,
+					flow_context_ptr,
+					&first_table_data,
+					&last_table_data,
+					command_args.isKernelVirtualAddress);
+  if (error)
+	goto end_function_with_error;
+
+  /* now check if there is already an existing add table for this flow */
+  if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
+	/* this buffer was for input buffers */
+	if (flow_context_ptr->input_tables_flag) {
+	  /* add table already exists - add the new tables to the end
+		of the previous */
+	num_entries = (flow_context_ptr->last_input_table.block_size >>
+			SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
+
+	info_entry_ptr =
+	(struct sep_lli_entry_t *)
+	(flow_context_ptr->last_input_table.physical_address +
+	(sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
+
+	  /* connect to list of tables */
+	  *info_entry_ptr = first_table_data;
+
+	  /* set the first table data */
+	  first_table_data = flow_context_ptr->first_input_table;
+	} else {
+	  /* set the input flag */
+	  flow_context_ptr->input_tables_flag = 1;
+
+	  /* set the first table data */
+	  flow_context_ptr->first_input_table = first_table_data;
+	}
+	/* set the last table data */
+	flow_context_ptr->last_input_table = last_table_data;
+  } else  /* this is output tables */ {
+	/* this buffer was for input buffers */
+	if (flow_context_ptr->output_tables_flag) {
+	  /* add table already exists - add the new tables to
+		the end of the previous */
+	num_entries = (flow_context_ptr->last_output_table.block_size >>
+		SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
+
+	info_entry_ptr =
+	(struct sep_lli_entry_t *)
+	(flow_context_ptr->last_output_table.physical_address +
+	(sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
+
+	  /* connect to list of tables */
+	  *info_entry_ptr = first_table_data;
+
+	  /* set the first table data */
+	  first_table_data = flow_context_ptr->first_output_table;
+	} else {
+	  /* set the input flag */
+	  flow_context_ptr->output_tables_flag = 1;
+
+	  /* set the first table data */
+	  flow_context_ptr->first_output_table = first_table_data;
+	}
+	/* set the last table data */
+	flow_context_ptr->last_output_table = last_table_data;
+  }
+
+  /* set output params */
+  command_args.first_table_addr = first_table_data.physical_address;
+  command_args.first_table_num_entries = ((first_table_data.block_size >>
+  SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
+  command_args.first_table_data_size =
+  (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
+
+  /* send the parameters to user application */
+  error = copy_to_user((void *)arg,
+	&command_args,
+	sizeof(struct sep_driver_add_flow_table_t));
+  if (error)
+	goto end_function_with_error;
+
+end_function_with_error:
+
+  /* free the allocated tables */
+  sep_deallocated_flow_tables(&first_table_data);
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_add_flow_tables_handler end\n");
+
+  return error;
+}
+
+/*
+  this function add the flow add message to the specific flow
+*/
+static int sep_add_flow_tables_message_handler(unsigned long arg)
+{
+  /* error */
+  int						error;
+
+  /* arguments */
+  struct sep_driver_add_message_t  command_args;
+
+  /* flow context */
+  struct sep_flow_context_t		*flow_context_ptr;
+
+  /*----------------------------
+	CODE
+  ------------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
+
+  error = copy_from_user(&command_args,
+	(void *)arg,
+	sizeof(struct sep_driver_add_message_t));
+  if (error)
+	goto end_function;
+
+  /* check input */
+  if (command_args.message_size_in_bytes >
+	SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
+	error = -ENOMEM;
+	goto end_function;
+  }
+
+  /* find the flow context */
+  error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
+  if (error)
+	goto end_function;
+
+  /* copy the message into context */
+  flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
+
+  error = copy_from_user(flow_context_ptr->message,
+	(void *)command_args.message_address,
+	command_args.message_size_in_bytes);
+
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
+
+  return error;
+}
+
+
+/*
+  this function returns the physical and virtual addresses of the static pool
+*/
+static int sep_get_static_pool_addr_handler(unsigned long arg)
+{
+  /* error */
+  int							error;
+
+  /* command arguments */
+  struct sep_driver_static_pool_addr_t	command_args;
+
+  /*-----------------------------
+	CODE
+  ------------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
+
+  /*prepare the output parameters in the struct */
+  command_args.physical_static_address = g_sep_phys_shared_area_addr +
+				SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
+  command_args.virtual_static_address = g_sep_shared_area_addr +
+				SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
+
+  DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+ "SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n",
+	command_args.physical_static_address,
+	command_args.virtual_static_address);
+
+  /* send the parameters to user application */
+  error = copy_to_user((void *)arg,
+	&command_args,
+	sizeof(struct sep_driver_static_pool_addr_t));
+  if (error)
+	goto end_function;
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
+
+  return error;
+}
+
+/*
+  this address gets the offset of the physical address from the start
+  of the mapped area
+*/
+static int sep_get_physical_mapped_offset_handler(unsigned long arg)
+{
+  /* error */
+  int							error;
+
+  /* command arguments */
+  struct sep_driver_get_mapped_offset_t	command_args;
+
+  /*-----------------------------
+	CODE
+  ------------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
+
+  error = copy_from_user(&command_args,
+	(void *)arg,
+	sizeof(struct sep_driver_get_mapped_offset_t));
+  if (error)
+	goto end_function;
+
+  if (command_args.physical_address < g_sep_phys_shared_area_addr) {
+	error = -ENOTTY;
+	goto end_function;
+  }
+
+  /*prepare the output parameters in the struct */
+  command_args.offset = command_args.physical_address -
+					g_sep_phys_shared_area_addr;
+
+  DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
+  "SEP Driver:physical_address is %08lx, offset is %lu\n",
+	command_args.physical_address,
+	command_args.offset);
+
+  /* send the parameters to user application */
+  error = copy_to_user((void *)arg,
+	&command_args,
+	sizeof(struct sep_driver_get_mapped_offset_t));
+  if (error)
+	goto end_function;
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+	"SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
+
+  return error;
+}
+
+
+/*
+  ?
+*/
+static int sep_start_handler(void)
+{
+  /* reg val */
+  unsigned long reg_val;
+
+  /* error */
+  unsigned long error;
+
+  /*-----------------------------
+	CODE
+  ------------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_start_handler start\n");
+
+  error = 0;
+
+  /* wait in polling for message from SEP */
+  do {
+	SEP_READ_REGISTER(g_sep_reg_base_address +
+			HW_HOST_SEP_HOST_GPR3_REG_ADDR, reg_val);
+  } while (!reg_val);
+
+  /* check the value */
+  if (reg_val == 0x1) {
+	/* fatal error - read erro status from GPRO */
+	SEP_READ_REGISTER(g_sep_reg_base_address +
+				HW_HOST_SEP_HOST_GPR0_REG_ADDR, error);
+	goto end_function;
+  }
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_start_handler end\n");
+
+  return error;
+}
+
+/*
+  this function handles the request for SEP initialization
+*/
+static int sep_init_handler(unsigned long arg)
+{
+  /* word from message */
+  unsigned long	 message_word;
+
+  /* message ptr */
+  unsigned long		*message_ptr;
+
+  /* command arguments */
+  struct sep_driver_init_t command_args;
+
+  /* counter */
+  unsigned long	counter;
+
+  /* error */
+  unsigned long	error;
+
+  /* reg val */
+  unsigned long	reg_val;
+
+  /*-------------------
+	CODE
+  ---------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_init_handler start\n");
+
+  error = 0;
+
+  error = copy_from_user(&command_args, (void *)arg,
+			sizeof(struct sep_driver_init_t));
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
+
+  if (error)
+	goto end_function;
+
+  /* PATCH - configure the DMA to single -burst instead of multi-burst */
+  /*sep_configure_dma_burst();*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
+
+  message_ptr = (unsigned long *)command_args.message_addr;
+
+  /* set the base address of the SRAM  */
+  SEP_WRITE_REGISTER(g_sep_reg_base_address +
+					HW_SRAM_ADDR_REG_ADDR,
+					HW_CC_SRAM_BASE_ADDRESS);
+
+  for (counter = 0 ;
+		counter < command_args.message_size_in_words;
+		counter++, message_ptr++) {
+	get_user(message_word, message_ptr);
+
+	/* write data to SRAM */
+	SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_SRAM_DATA_REG_ADDR,
+						message_word);
+
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+					"SEP Driver:message_word is %lu\n",
+					message_word);
+
+		/* wait for write complete */
+	SEP_WAIT_SRAM_WRITE_COMPLETE();
+  }
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
+
+  /* signal SEP */
+  SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_HOST_SEP_GPR0_REG_ADDR,
+					0x1);
+
+  do {
+	SEP_READ_REGISTER(g_sep_reg_base_address +
+			HW_HOST_SEP_HOST_GPR3_REG_ADDR, reg_val);
+  } while (!(reg_val & 0xFFFFFFFD));
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
+
+  /* check the value */
+  if (reg_val == 0x1) {
+	DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
+		"SEP Driver:init failed\n");
+
+	SEP_READ_REGISTER(g_sep_reg_base_address + 0x8060, error);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+			"SEP Driver:sw monitor is %lu\n",
+			error);
+
+	/* fatal error - read erro status from GPRO */
+	SEP_READ_REGISTER(g_sep_reg_base_address +
+				HW_HOST_SEP_HOST_GPR0_REG_ADDR,
+				error);
+	DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+			"SEP Driver:error is %lu\n", error);
+	goto end_function;
+  }
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_init_handler end\n");
+
+  return error;
+
+}
+
+/*
+  this function handles the request cache and resident reallocation
+*/
+static int sep_realloc_cache_resident_handler(unsigned long arg)
+{
+  /* error */
+  int			error;
+
+  /* physical cache addr */
+  unsigned long		phys_cache_address;
+
+  /* physical resident addr */
+  unsigned long		phys_resident_address;
+
+  /* command arguments */
+  struct sep_driver_realloc_cache_resident_t command_args;
+
+  /*------------------
+	CODE
+  ---------------------*/
+
+  /* copy the data */
+  error = copy_from_user(&command_args,
+	(void *)arg,
+	sizeof(struct sep_driver_realloc_cache_resident_t));
+  if (error)
+	goto end_function;
+
+  /* copy cache and resident to the their intended locations */
+  error = sep_copy_cache_resident_to_area(command_args.cache_addr,
+					command_args.cache_size_in_bytes,
+					command_args.resident_addr,
+					command_args.resident_size_in_bytes,
+					&phys_cache_address,
+					&phys_resident_address);
+  if (error)
+	goto end_function;
+
+  /* lock the area (if needed) */
+  sep_lock_cache_resident_area();
+
+  command_args.new_base_addr = g_sep_phys_shared_area_addr;
+
+  /* find the new base address according to the lowest address between
+	cache, resident and shared area */
+  if (phys_resident_address < command_args.new_base_addr)
+	command_args.new_base_addr = phys_resident_address;
+  if (phys_cache_address < command_args.new_base_addr)
+	command_args.new_base_addr = phys_cache_address;
+
+  /* set the return parameters */
+  command_args.new_cache_addr = phys_cache_address;
+  command_args.new_resident_addr = phys_resident_address;
+
+
+  /* set the new shared area */
+  command_args.new_shared_area_addr = g_sep_phys_shared_area_addr;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:command_args.new_shared_area_addr is %08lx\n",
+	command_args.new_shared_area_addr);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:command_args.new_base_addr is %08lx\n",
+	command_args.new_base_addr);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:command_args.new_resident_addr is %08lx\n",
+	command_args.new_resident_addr);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+	"SEP Driver:command_args.new_cache_addr is %08lx\n",
+	command_args.new_cache_addr);
+
+  /* return to user */
+  error = copy_to_user((void *)arg,
+	(void *)&command_args,
+	sizeof(struct sep_driver_realloc_cache_resident_t));
+
+end_function:
+
+  return error;
+}
+
+/*
+  this function handles the request for get time
+*/
+static int sep_get_time_handler(unsigned long arg)
+{
+  /* error */
+  int error;
+
+  /* command arguments */
+  struct sep_driver_get_time_t	command_args;
+
+  /*------------------------
+	CODE
+  --------------------------*/
+
+  error = sep_set_time(&command_args.time_physical_address,
+			&command_args.time_value);
+
+  /* return to user */
+  error = copy_to_user((void *)arg,
+	(void *)&command_args,
+	sizeof(struct sep_driver_get_time_t));
+
+  return error;
+
+}
+
+/*
+  This api handles the setting of API mode to blocking or non-blocking
+*/
+static int sep_set_api_mode_handler(unsigned long arg)
+{
+  /* error */
+  int			error;
+
+  /* flag */
+  unsigned long mode_flag;
+
+  /*----------------------------
+	CODE
+  -----------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_set_api_mode_handler start\n");
+
+  error = get_user(
+	  mode_flag, &(((struct sep_driver_set_api_mode_t *)arg)->mode));
+  if (error)
+	goto end_function;
+
+  /* set the global flag */
+  g_sep_block_mode_flag = mode_flag;
+
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_set_api_mode_handler end\n");
+
+  return error;
+}
+
+/*
+  This API handles the end transaction request
+*/
+static int sep_end_transaction_handler(unsigned long arg)
+{
+  /*----------------------------
+	CODE
+  -----------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_end_transaction_handler start\n");
+
+#if 0/*!SEP_DRIVER_POLLING_MODE*/
+  /* close IMR */
+  SEP_WRITE_REGISTER(g_sep_reg_base_address + HW_HOST_IMR_REG_ADDR, 0x7FFF);
+
+  /* release IRQ line */
+  free_irq(SEP_DIRVER_IRQ_NUM, &g_sep_reg_base_address);
+
+  /* lock the sep mutex */
+  mutex_unlock(&sep_mutex);
+#endif
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_end_transaction_handler end\n");
+
+  return 0;
+}
+
+/* handler for flow done interrupt */
+static void sep_flow_done_handler(struct work_struct		*work)
+{
+  /* flow context_ptr */
+  struct sep_flow_context_t		*flow_data_ptr;
+  /*-------------------------
+	CODE
+  ---------------------------*/
+
+  /* obtain the mutex */
+  mutex_lock(&sep_mutex);
+
+  /* get the pointer to context */
+  flow_data_ptr = (struct sep_flow_context_t *)work;
+
+  /* free all the current input tables in sep */
+  sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
+
+  /* free all the current tables output tables in SEP (if needed) */
+  if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
+	sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
+
+  /* check if we have additional tables to be sent to SEP only input
+	flag may be checked */
+  if (flow_data_ptr->input_tables_flag) {
+	/* copy the message to the shared RAM and signal SEP */
+	memcpy((void *)flow_data_ptr->message,
+	(void *)g_sep_shared_area_addr,
+	flow_data_ptr->message_size_in_bytes);
+
+	SEP_WRITE_REGISTER(g_sep_reg_base_address +
+			HW_HOST_HOST_SEP_GPR2_REG_ADDR,
+			0x2);
+  }
+  mutex_unlock(&sep_mutex);
+}
+
+
+/*
+  This function creates a list of tables for flow and returns the data for
+	the first and last tables of the list
+*/
+static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
+			unsigned long	first_buff_addr,
+			struct sep_flow_context_t	*flow_data_ptr,
+			struct sep_lli_entry_t		*first_table_data_ptr,
+			struct sep_lli_entry_t		*last_table_data_ptr,
+			bool			isKernelVirtualAddress)
+{
+  /* error */
+  int				error;
+
+  /* virtaul address of one buffer */
+  unsigned long		virt_buff_addr;
+
+  /* virtual size of one buffer */
+  unsigned long		virt_buff_size;
+
+  /* table data for each created table */
+  struct sep_lli_entry_t	table_data;
+
+  /* info entry */
+  struct sep_lli_entry_t		*info_entry_ptr;
+
+  /* prevouis info entry */
+  struct sep_lli_entry_t		*prev_info_entry_ptr;
+
+  /* counter */
+  unsigned long		i;
+
+  /*-------------------------------
+	CODE
+  ----------------------------------*/
+
+  /* init vars */
+  error = 0;
+  prev_info_entry_ptr = 0;
+
+  /* init the first table to default */
+  table_data.physical_address = 0xffffffff;
+  first_table_data_ptr->physical_address = 0xffffffff;
+  table_data.block_size = 0;
+
+  for (i = 0; i < num_virtual_buffers; i++) {
+	/* get the virtual buffer address */
+	error = get_user(virt_buff_addr, &first_buff_addr);
+	if (error)
+	goto end_function;
+
+	/* get the virtual buffer size */
+	first_buff_addr++;
+	error = get_user(virt_buff_size, &first_buff_addr);
+	if (error)
+	goto end_function;
+
+	/* advance the address to point to the next pair of address|size */
+	first_buff_addr++;
+
+	/* now prepare the one flow LLI table from the data */
+	error = sep_prepare_one_flow_dma_table(virt_buff_addr,
+					virt_buff_size,
+					&table_data,
+					&info_entry_ptr,
+					flow_data_ptr,
+					isKernelVirtualAddress);
+	if (error)
+	goto end_function;
+
+	if (i == 0) {
+	  /* if this is the first table - save it to return to the user
+		application */
+	  *first_table_data_ptr = table_data;
+
+	  /* set the pointer to info entry */
+	  prev_info_entry_ptr = info_entry_ptr;
+	} else {
+	  /* not first table - the previous table info entry should
+		be updated */
+	  prev_info_entry_ptr->block_size =
+		(0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) |
+		(table_data.block_size);
+
+	  /* set the pointer to info entry */
+	  prev_info_entry_ptr = info_entry_ptr;
+	}
+  }
+
+  /* set the last table data */
+  *last_table_data_ptr = table_data;
+
+end_function:
+
+  return error;
+}
+
+
+/*
+  This function creates one DMA table for flow and returns its data,
+  and pointer to its info entry
+*/
+static int sep_prepare_one_flow_dma_table(
+			unsigned long	 virt_buff_addr,
+			unsigned long	 virt_buff_size,
+			struct sep_lli_entry_t		*table_data,
+			struct sep_lli_entry_t		**info_entry_ptr,
+			struct sep_flow_context_t		*flow_data_ptr,
+			bool			isKernelVirtualAddress)
+{
+  /* error */
+  int				error;
+
+  /* the range in pages */
+  unsigned long		lli_array_size;
+
+  /* array of pointers ot page */
+  struct sep_lli_entry_t		*lli_array;
+
+  /* pointer to the entry in the dma table */
+  struct sep_lli_entry_t		*flow_dma_table_entry_ptr;
+
+  /* address of the dma table */
+  unsigned long		*start_dma_table_ptr;
+
+  /* total table data counter */
+  unsigned long		dma_table_data_count;
+
+  /* pointer that will keep the pointer t the pages of the virtual buffer */
+  struct page		**page_array_ptr;
+
+  /* counter */
+  unsigned long		entry_count;
+
+  /*-------------------------------
+	CODE
+  ----------------------------------*/
+
+  /* find the space for the new table */
+  error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
+  if (error)
+	goto end_function;
+
+  /* check if the pages are in Kernel Virtual Address layout */
+  if (isKernelVirtualAddress == true)
+	/* lock kernel buffer in the memory */
+	error = sep_lock_kernel_pages(virt_buff_addr,
+				  virt_buff_size,
+				  &lli_array_size,
+				  &lli_array,
+				  &page_array_ptr);
+  else
+	/* lock user buffer in the memory */
+	error = sep_lock_user_pages(virt_buff_addr,
+				virt_buff_size,
+				&lli_array_size,
+				&lli_array,
+				&page_array_ptr);
+
+  if (error)
+	goto end_function;
+
+  /* set the pointer to page array at the beginning of table - this table is
+	now considered taken */
+  *start_dma_table_ptr = lli_array_size;
+
+  /* point to the place of the pages pointers of the table */
+  start_dma_table_ptr++;
+
+  /* set the pages pointer */
+  *start_dma_table_ptr = (unsigned long)page_array_ptr;
+
+  /* set the pointer to the first entry */
+  flow_dma_table_entry_ptr = (struct sep_lli_entry_t *)(++start_dma_table_ptr);
+
+  /* now create the entries for table */
+  for (dma_table_data_count = entry_count = 0;
+		entry_count <  lli_array_size;
+		entry_count++) {
+	flow_dma_table_entry_ptr->physical_address =
+			lli_array[entry_count].physical_address;
+
+	flow_dma_table_entry_ptr->block_size =
+		lli_array[entry_count].block_size;
+
+	/* set the total data of a table */
+	dma_table_data_count += lli_array[entry_count].block_size;
+
+	flow_dma_table_entry_ptr++;
+  }
+
+  /* set the physical address */
+  table_data->physical_address = virt_to_phys(start_dma_table_ptr);
+
+  /* set the num_entries and total data size */
+  table_data->block_size = ((lli_array_size + 1) <<
+			SEP_NUM_ENTRIES_OFFSET_IN_BITS) |
+			(dma_table_data_count);
+
+  /* set the info entry */
+  flow_dma_table_entry_ptr->physical_address = 0xffffffff;
+  flow_dma_table_entry_ptr->block_size = 0;
+
+  /* set the pointer to info entry */
+  *info_entry_ptr = flow_dma_table_entry_ptr;
+
+  /* the array of the lli entries */
+  kfree(lli_array);
+
+end_function:
+
+  return error;
+}
+
+
+/*
+  This function returns pointer to the  flow data structure
+  that conatins the given id
+*/
+static int sep_find_flow_context(
+				unsigned long	flow_id,
+				struct sep_flow_context_t **flow_data_ptr)
+{
+  /* count */
+  unsigned long count;
+
+  /* error */
+  int			error;
+
+  /*-----------------------
+	CODE
+  ---------------------------*/
+
+  error = 0;
+
+  /*
+	 always search for flow with id default first - in case we
+	 already started working on the flow there can be no situation
+	 when 2 flows are with default flag
+  */
+  for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
+	if (g_sep_flows_data_array[count].flow_id == flow_id) {
+	  *flow_data_ptr = &g_sep_flows_data_array[count];
+	  break;
+	}
+  }
+
+  if (count == SEP_DRIVER_NUM_FLOWS)
+	/* no flow found  */
+	error = -ENOMEM;
+
+  return error;
+}
+
+/*
+  this function find a space for the new flow dma table
+*/
+static int sep_find_free_flow_dma_table_space(
+			unsigned long	**table_address_ptr)
+{
+  /* error */
+  int			error;
+
+  /* pointer to the id field of the flow dma table */
+  unsigned long		*start_table_ptr;
+
+  /* start address of the flow dma area */
+  unsigned long	flow_dma_area_start_addr;
+
+  /* end address of the flow dma area */
+  unsigned long	flow_dma_area_end_addr;
+
+  /* maximum table size in words */
+  unsigned long	table_size_in_words;
+
+  /*---------------------
+	CODE
+  -----------------------*/
+
+  error = 0;
+
+  /* find the start address of the flow DMA table area */
+  flow_dma_area_start_addr = g_sep_shared_area_addr +
+			SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
+
+  /* set end address of the flow table area */
+  flow_dma_area_end_addr = flow_dma_area_start_addr +
+			SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
+
+  /* set table size in words */
+  table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE *
+			(sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
+
+  /* set the pointer to the start address of DMA area */
+  start_table_ptr = (unsigned long *)flow_dma_area_start_addr;
+
+  /* find the space for the next table */
+  while (((*start_table_ptr & 0x7FFFFFFF) != 0) &&
+			((unsigned long)start_table_ptr <
+			flow_dma_area_end_addr))
+	start_table_ptr += table_size_in_words;
+
+  /* check if we reached the end of floa tables area */
+  if ((unsigned long)start_table_ptr >= flow_dma_area_end_addr)
+	error = -1;
+  else
+	*table_address_ptr = start_table_ptr;
+
+  return error;
+}
+
+/*
+  this function goes over all the flow tables connected to the given
+	table and deallocate them
+*/
+static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
+{
+  /* id poiner */
+  unsigned long		*table_ptr;
+
+  /* end address of the flow dma area */
+  unsigned long	num_entries;
+
+  unsigned long	num_pages;
+
+  /* pages ptr */
+  struct page		**pages_ptr;
+
+  /* maximum table size in words */
+  struct sep_lli_entry_t		*info_entry_ptr;
+
+  /*-------------------------------
+	CODE
+  ---------------------------------*/
+
+  /* set the pointer to the first table */
+  table_ptr = (unsigned long *)first_table_ptr->physical_address;
+
+  /* set the num of entries */
+  num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
+				& SEP_NUM_ENTRIES_MASK;
+
+  /* go over all the connected tables */
+  while (*table_ptr != 0xffffffff) {
+	/* get number of pages */
+	num_pages = *(table_ptr - 2);
+
+	/* get the pointer to the pages */
+	pages_ptr = (struct page **)(*(table_ptr - 1));
+
+	/* free the pages */
+	sep_free_dma_pages(pages_ptr, num_pages, 1);
+
+	/* goto to the info entry */
+	info_entry_ptr = ((struct sep_lli_entry_t *)table_ptr) +
+					(num_entries - 1);
+
+	table_ptr = (unsigned long *)info_entry_ptr->physical_address;
+	num_entries = (info_entry_ptr->block_size >>
+		SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
+  }
+
+  return;
+}
+
+/*
+  This function handler the set flow id command
+*/
+static int sep_set_flow_id_handler(unsigned long arg)
+{
+  /* error */
+  int					error;
+
+  /* flow _id */
+  unsigned long		 flow_id;
+
+  /* pointer to flow data structre */
+  struct sep_flow_context_t		*flow_data_ptr;
+
+  /*----------------------
+	CODE
+  -----------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"------------>SEP Driver: sep_set_flow_id_handler start\n");
+
+  error = get_user(flow_id,
+	&(((struct sep_driver_set_flow_id_t *)arg)->flow_id));
+  if (error)
+	goto end_function;
+
+  /* find the flow data structure that was just used for creating new flow
+	- its id should be default */
+  error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
+  if (error)
+	goto end_function;
+
+  /* set flow id */
+  flow_data_ptr->flow_id = flow_id;
+
+end_function:
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_set_flow_id_handler end\n");
+
+
+  return error;
+}
+
+
+/*
+  calculates time and sets it at the predefined address
+*/
+static int sep_set_time(unsigned long		*address_ptr,
+			unsigned long		*time_in_sec_ptr)
+{
+  /*  time struct */
+  struct timeval  time;
+
+  /* address of time in the kernel */
+  unsigned long	time_addr;
+
+
+  /*------------------------
+	CODE
+  --------------------------*/
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:--------> sep_set_time start\n");
+
+
+  do_gettimeofday(&time);
+
+  /* set value in the SYSTEM MEMORY offset */
+  time_addr = g_message_shared_area_addr +
+			SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
+
+  *(unsigned long *)time_addr = SEP_TIME_VAL_TOKEN;
+  *(unsigned long *)(time_addr + 4) = time.tv_sec;
+
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+			"SEP Driver:time.tv_sec is %lu\n",
+			time.tv_sec);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+			"SEP Driver:time_addr is %lu\n",
+			time_addr);
+  DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
+			"SEP Driver:g_message_shared_area_addr is %lu\n",
+			g_message_shared_area_addr);
+
+  /* set the output parameters if needed */
+  if (address_ptr)
+	*address_ptr = sep_shared_area_virt_to_phys(time_addr);
+
+  if (time_in_sec_ptr)
+	*time_in_sec_ptr = time.tv_sec;
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_set_time end\n");
+
+  return 0;
+}
+
+/*
+  PATCH for configuring the DMA to single burst instead of multi-burst
+*/
+static void sep_configure_dma_burst(void)
+{
+
+#define 	 HW_AHB_RD_WR_BURSTS_REG_ADDR 		 0x0E10UL
+
+  unsigned long	regVal;
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_configure_dma_burst start \n");
+
+  /* request access to registers from SEP */
+  SEP_WRITE_REGISTER(g_sep_reg_base_address +
+					HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2UL);
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg)  \n");
+
+  SEP_READ_REGISTER(g_sep_reg_base_address +
+					HW_HOST_SEP_BUSY_REG_ADDR, regVal);
+  while (regVal)
+	SEP_READ_REGISTER(g_sep_reg_base_address +
+					HW_HOST_SEP_BUSY_REG_ADDR, regVal);
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop)  \n");
+
+  /* set the DMA burst register to single burst*/
+  SEP_WRITE_REGISTER(g_sep_reg_base_address +
+					HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
+
+  /* release the sep busy */
+  SEP_WRITE_REGISTER(g_sep_reg_base_address +
+					HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
+  SEP_READ_REGISTER(g_sep_reg_base_address +
+					HW_HOST_SEP_BUSY_REG_ADDR, regVal);
+  while (regVal != 0x0)
+	SEP_READ_REGISTER(g_sep_reg_base_address +
+					HW_HOST_SEP_BUSY_REG_ADDR, regVal);
+
+  DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
+		"SEP Driver:<-------- sep_configure_dma_burst done  \n");
+
+}
+
+module_init(sep_init);
+module_exit(sep_exit);
+
+MODULE_LICENSE("GPL");