]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/sep/sep_main_mod.c
Staging: sep: function shuffle
[mv-sheeva.git] / drivers / staging / sep / sep_main_mod.c
1 /*
2  *
3  *  sep_main_mod.c - Security Processor Driver main group of functions
4  *
5  *  Copyright(c) 2009 Intel Corporation. All rights reserved.
6  *  Copyright(c) 2009 Discretix. All rights reserved.
7  *
8  *  This program is free software; you can redistribute it and/or modify it
9  *  under the terms of the GNU General Public License as published by the Free
10  *  Software Foundation; either version 2 of the License, or (at your option)
11  *  any later version.
12  *
13  *  This program is distributed in the hope that it will be useful, but WITHOUT
14  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
16  *  more details.
17  *
18  *  You should have received a copy of the GNU General Public License along with
19  *  this program; if not, write to the Free Software Foundation, Inc., 59
20  *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  *  CONTACTS:
23  *
24  *  Mark Allyn          mark.a.allyn@intel.com
25  *
26  *  CHANGES:
27  *
28  *  2009.06.26  Initial publish
29  *
30  */
31
32 #include <linux/init.h>
33 #include <linux/module.h>
34 #include <linux/fs.h>
35 #include <linux/cdev.h>
36 #include <linux/kdev_t.h>
37 #include <linux/mutex.h>
38 #include <linux/mm.h>
39 #include <linux/poll.h>
40 #include <linux/wait.h>
41 #include <asm/ioctl.h>
42 #include <linux/ioport.h>
43 #include <asm/io.h>
44 #include <linux/interrupt.h>
45 #include <linux/pagemap.h>
46 #include <asm/cacheflush.h>
47 #include "sep_driver_hw_defs.h"
48 #include "sep_driver_config.h"
49 #include "sep_driver_api.h"
50 #include "sep_driver_ext_api.h"
51 #include "sep_dev.h"
52
53 /*----------------------------------------
54         DEFINES
55 -----------------------------------------*/
56
57
58 #define INT_MODULE_PARM(n, v) int n = v; module_param(n, int, 0)
59
60 /*--------------------------------------
61   TYPEDEFS
62   -----------------------------------------*/
63
64
65
66 /*--------------------------------------------
67         GLOBAL variables
68 --------------------------------------------*/
69
70 /* debug messages level */
71 INT_MODULE_PARM(sepDebug, 0x0);
72 MODULE_PARM_DESC(sepDebug, "Flag to enable SEP debug messages");
73
74 /* major and minor device numbers */
75 static dev_t g_sep_device_number;
76
77 /* the files operations structure of the driver */
78 static struct file_operations g_sep_fops;
79
80 /* cdev struct of the driver */
81 static struct cdev g_sep_cdev;
82
83 /*
84   mutex for the access to the internals of the sep driver
85 */
86 static DEFINE_MUTEX(sep_mutex);
87
88
89 /* wait queue head (event) of the driver */
90 static DECLARE_WAIT_QUEUE_HEAD(g_sep_event);
91
92
93
94 /*------------------------------------------------
95   PROTOTYPES
96 ---------------------------------------------------*/
97
98 /*
99   interrupt handler function
100 */
101 irqreturn_t sep_inthandler(int irq, void *dev_id);
102
103 /*
104   this function registers the driver to the file system
105 */
106 static int sep_register_driver_to_fs(void);
107
108 /*
109   this function unregisters driver from fs
110 */
111 static void sep_unregister_driver_from_fs(void);
112
113 /*
114   this function calculates the size of data that can be inserted into the lli
115   table from this array the condition is that either the table is full
116   (all etnries are entered), or there are no more entries in the lli array
117 */
118 static unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries);
119 /*
120   this functions builds ont lli table from the lli_array according to the
121   given size of data
122 */
123 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);
124
125 /*
126   this function goes over the list of the print created tables and prints
127   all the data
128 */
129 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);
130
131
132
133 /*
134   This function raises interrupt to SEPm that signals that is has a new
135   command from HOST
136 */
137 static void sep_send_command_handler(void);
138
139
140 /*
141   This function raises interrupt to SEP that signals that is has a
142   new reply from HOST
143 */
144 static void sep_send_reply_command_handler(void);
145
146 /*
147   This function handles the allocate data pool memory request
148   This function returns calculates the physical address of the allocated memory
149   and the offset of this area from the mapped address. Therefore, the FVOs in
150   user space can calculate the exact virtual address of this allocated memory
151 */
152 static int sep_allocate_data_pool_memory_handler(unsigned long arg);
153
154
155 /*
156   This function  handles write into allocated data pool command
157 */
158 static int sep_write_into_data_pool_handler(unsigned long arg);
159
160 /*
161   this function handles the read from data pool command
162 */
163 static int sep_read_from_data_pool_handler(unsigned long arg);
164
165 /*
166   this function handles tha request for creation of the DMA table
167   for the synchronic symmetric operations (AES,DES)
168 */
169 static int sep_create_sync_dma_tables_handler(unsigned long arg);
170
171 /*
172   this function handles the request to create the DMA tables for flow
173 */
174 static int sep_create_flow_dma_tables_handler(unsigned long arg);
175
176 /*
177   This API handles the end transaction request
178 */
179 static int sep_end_transaction_handler(unsigned long arg);
180
181
182 /*
183   this function handles add tables to flow
184 */
185 static int sep_add_flow_tables_handler(unsigned long arg);
186
187 /*
188   this function add the flow add message to the specific flow
189 */
190 static int sep_add_flow_tables_message_handler(unsigned long arg);
191
192 /*
193   this function handles the request for SEP start
194 */
195 static int sep_start_handler(void);
196
197 /*
198   this function handles the request for SEP initialization
199 */
200 static int sep_init_handler(unsigned long arg);
201
202 /*
203   this function handles the request cache and resident reallocation
204 */
205 static int sep_realloc_cache_resident_handler(unsigned long arg);
206
207
208 /*
209   This api handles the setting of API mode to blocking or non-blocking
210 */
211 static int sep_set_api_mode_handler(unsigned long arg);
212
213 /* handler for flow done interrupt */
214 static void sep_flow_done_handler(struct work_struct *work);
215
216 /*
217   This function locks all the physical pages of the kernel virtual buffer
218   and construct a basic lli  array, where each entry holds the physical
219   page address and the size that application data holds in this physical pages
220 */
221 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);
222
223 /*
224   This function creates one DMA table for flow and returns its data,
225   and pointer to its info entry
226 */
227 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);
228
229 /*
230   This function creates a list of tables for flow and returns the data for the
231   first and last tables of the list
232 */
233 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
234                                        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);
235
236 /*
237   this function find a space for the new flow dma table
238 */
239 static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr);
240
241 /*
242   this function goes over all the flow tables connected to the given table and
243   deallocate them
244 */
245 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr);
246
247 /*
248   This function handler the set flow id command
249 */
250 static int sep_set_flow_id_handler(unsigned long arg);
251
252 /*
253   This function returns pointer to the  flow data structure
254   that conatins the given id
255 */
256 static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr);
257
258
259 /*
260   this function returns the physical and virtual addresses of the static pool
261 */
262 static int sep_get_static_pool_addr_handler(unsigned long arg);
263
264 /*
265   this address gets the offset of the physical address from the start of
266   the mapped area
267 */
268 static int sep_get_physical_mapped_offset_handler(unsigned long arg);
269
270
271 /*
272   this function handles the request for get time
273 */
274 static int sep_get_time_handler(unsigned long arg);
275
276 /*
277   calculates time and sets it at the predefined address
278 */
279 static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr);
280
281 /*
282   PATCH for configuring the DMA to single burst instead of multi-burst
283 */
284 static void sep_configure_dma_burst(void);
285
286 /*
287         This function locks all the physical pages of the
288         application virtual buffer and construct a basic lli
289         array, where each entry holds the physical page address
290         and the size that application data holds in this physical pages
291 */
292 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);
293
294 /*---------------------------------------------
295         FUNCTIONS
296 -----------------------------------------------*/
297
298 /*
299   this function locks SEP by locking the semaphore
300 */
301 int sep_lock()
302 {
303         mutex_lock(&sep_mutex);
304         return 0;
305 }
306
307 /*
308   this function unlocks SEP
309 */
310 void sep_unlock()
311 {
312         /* release mutex */
313         mutex_unlock(&sep_mutex);
314 }
315
316 /*
317   this function returns the address of the message shared area
318 */
319 void sep_map_shared_area(unsigned long *mappedAddr_ptr)
320 {
321         *mappedAddr_ptr = sep_dev->shared_area_addr;
322 }
323
324 /*
325   this function returns the address of the message shared area
326 */
327 void sep_send_msg_rdy_cmd()
328 {
329         sep_send_command_handler();
330 }
331
332 /* this functions frees all the resources that were allocated for the building
333 of the LLI DMA tables */
334 void sep_free_dma_resources()
335 {
336         sep_free_dma_table_data_handler();
337 }
338
339 /* poll(suspend), until reply from sep */
340 void sep_driver_poll()
341 {
342         unsigned long retVal = 0;
343
344 #ifdef SEP_DRIVER_POLLING_MODE
345
346         while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF))
347                 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
348
349         sep_dev->sep_to_host_reply_counter++;
350 #else
351         /* poll, until reply from sep */
352         wait_event(g_sep_event, (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter));
353
354 #endif
355 }
356
357 /*----------------------------------------------------------------------
358   open function of the character driver - must only lock the mutex
359         must also release the memory data pool allocations
360 ------------------------------------------------------------------------*/
361 static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
362 {
363         int error;
364
365         dbg("SEP Driver:--------> open start\n");
366
367         error = 0;
368
369         /* check the blocking mode */
370         if (sep_dev->block_mode_flag)
371                 /* lock mutex */
372                 mutex_lock(&sep_mutex);
373         else
374                 error = mutex_trylock(&sep_mutex);
375
376         /* check the error */
377         if (error) {
378                 edbg("SEP Driver: down_interruptible failed\n");
379
380                 goto end_function;
381         }
382
383         /* release data pool allocations */
384         sep_dev->data_pool_bytes_allocated = 0;
385
386 end_function:
387         dbg("SEP Driver:<-------- open end\n");
388         return error;
389 }
390
391
392
393
394 /*------------------------------------------------------------
395         release function
396 -------------------------------------------------------------*/
397 static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
398 {
399         dbg("----------->SEP Driver: sep_release start\n");
400
401 #if 0                           /*!SEP_DRIVER_POLLING_MODE */
402         /* close IMR */
403         sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
404
405         /* release IRQ line */
406         free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
407
408 #endif
409
410         /* unlock the sep mutex */
411         mutex_unlock(&sep_mutex);
412
413         dbg("SEP Driver:<-------- sep_release end\n");
414
415         return 0;
416 }
417
418
419
420
421 /*---------------------------------------------------------------
422   map function - this functions maps the message shared area
423 -----------------------------------------------------------------*/
424 static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
425 {
426         unsigned long phys_addr;
427
428         dbg("-------->SEP Driver: mmap start\n");
429
430         /* check that the size of the mapped range is as the size of the message
431            shared area */
432         if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
433                 edbg("SEP Driver mmap requested size is more than allowed\n");
434                 printk(KERN_WARNING "SEP Driver mmap requested size is more \
435                         than allowed\n");
436                 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_end);
437                 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_start);
438                 return -EAGAIN;
439         }
440
441         edbg("SEP Driver:g_message_shared_area_addr is %08lx\n", sep_dev->message_shared_area_addr);
442
443         /* get physical address */
444         phys_addr = sep_dev->phys_shared_area_addr;
445
446         edbg("SEP Driver: phys_addr is %08lx\n", phys_addr);
447
448         if (remap_pfn_range(vma, vma->vm_start, phys_addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
449                 edbg("SEP Driver remap_page_range failed\n");
450                 printk(KERN_WARNING "SEP Driver remap_page_range failed\n");
451                 return -EAGAIN;
452         }
453
454         dbg("SEP Driver:<-------- mmap end\n");
455
456         return 0;
457 }
458
459
460 /*-----------------------------------------------
461   poll function
462 *----------------------------------------------*/
463 static unsigned int sep_poll(struct file *filp, poll_table * wait)
464 {
465         unsigned long count;
466         unsigned int mask = 0;
467         unsigned long retVal = 0;       /* flow id */
468
469         dbg("---------->SEP Driver poll: start\n");
470
471
472 #if SEP_DRIVER_POLLING_MODE
473
474         while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
475                 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
476
477                 for (count = 0; count < 10 * 4; count += 4)
478                         edbg("Poll Debug Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
479         }
480
481         sep_dev->sep_to_host_reply_counter++;
482 #else
483         /* add the event to the polling wait table */
484         poll_wait(filp, &g_sep_event, wait);
485
486 #endif
487
488         edbg("sep_dev->host_to_sep_send_counter is %lu\n", sep_dev->host_to_sep_send_counter);
489         edbg("sep_dev->sep_to_host_reply_counter is %lu\n", sep_dev->sep_to_host_reply_counter);
490
491         /* check if the data is ready */
492         if (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter) {
493                 for (count = 0; count < 12 * 4; count += 4)
494                         edbg("Sep Mesg Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
495
496                 for (count = 0; count < 10 * 4; count += 4)
497                         edbg("Debug Data Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + 0x1800 + count)));
498
499                 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
500                 edbg("retVal is %lu\n", retVal);
501                 /* check if the this is sep reply or request */
502                 if (retVal >> 31) {
503                         edbg("SEP Driver: sep request in\n");
504                         /* request */
505                         mask |= POLLOUT | POLLWRNORM;
506                 } else {
507                         edbg("SEP Driver: sep reply in\n");
508                         mask |= POLLIN | POLLRDNORM;
509                 }
510         }
511         dbg("SEP Driver:<-------- poll exit\n");
512         return mask;
513 }
514
515
516 static int sep_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
517 {
518         int error = 0;
519
520         dbg("------------>SEP Driver: ioctl start\n");
521
522         edbg("SEP Driver: cmd is %x\n", cmd);
523
524         /* check that the command is for sep device */
525         if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
526                 error = -ENOTTY;
527
528         switch (cmd) {
529         case SEP_IOCSENDSEPCOMMAND:
530                 /* send command to SEP */
531                 sep_send_command_handler();
532                 edbg("SEP Driver: after sep_send_command_handler\n");
533                 break;
534         case SEP_IOCSENDSEPRPLYCOMMAND:
535                 /* send reply command to SEP */
536                 sep_send_reply_command_handler();
537                 break;
538         case SEP_IOCALLOCDATAPOLL:
539                 /* allocate data pool */
540                 error = sep_allocate_data_pool_memory_handler(arg);
541                 break;
542         case SEP_IOCWRITEDATAPOLL:
543                 /* write data into memory pool */
544                 error = sep_write_into_data_pool_handler(arg);
545                 break;
546         case SEP_IOCREADDATAPOLL:
547                 /* read data from data pool into application memory */
548                 error = sep_read_from_data_pool_handler(arg);
549                 break;
550         case SEP_IOCCREATESYMDMATABLE:
551                 /* create dma table for synhronic operation */
552                 error = sep_create_sync_dma_tables_handler(arg);
553                 break;
554         case SEP_IOCCREATEFLOWDMATABLE:
555                 /* create flow dma tables */
556                 error = sep_create_flow_dma_tables_handler(arg);
557                 break;
558         case SEP_IOCFREEDMATABLEDATA:
559                 /* free the pages */
560                 error = sep_free_dma_table_data_handler();
561                 break;
562         case SEP_IOCSETFLOWID:
563                 /* set flow id */
564                 error = sep_set_flow_id_handler(arg);
565                 break;
566         case SEP_IOCADDFLOWTABLE:
567                 /* add tables to the dynamic flow */
568                 error = sep_add_flow_tables_handler(arg);
569                 break;
570         case SEP_IOCADDFLOWMESSAGE:
571                 /* add message of add tables to flow */
572                 error = sep_add_flow_tables_message_handler(arg);
573                 break;
574         case SEP_IOCSEPSTART:
575                 /* start command to sep */
576                 error = sep_start_handler();
577                 break;
578         case SEP_IOCSEPINIT:
579                 /* init command to sep */
580                 error = sep_init_handler(arg);
581                 break;
582         case SEP_IOCSETAPIMODE:
583                 /* set non- blocking mode */
584                 error = sep_set_api_mode_handler(arg);
585                 break;
586         case SEP_IOCGETSTATICPOOLADDR:
587                 /* get the physical and virtual addresses of the static pool */
588                 error = sep_get_static_pool_addr_handler(arg);
589                 break;
590         case SEP_IOCENDTRANSACTION:
591                 error = sep_end_transaction_handler(arg);
592                 break;
593         case SEP_IOCREALLOCCACHERES:
594                 error = sep_realloc_cache_resident_handler(arg);
595                 break;
596         case SEP_IOCGETMAPPEDADDROFFSET:
597                 error = sep_get_physical_mapped_offset_handler(arg);
598                 break;
599         case SEP_IOCGETIME:
600                 error = sep_get_time_handler(arg);
601                 break;
602         default:
603                 error = -ENOTTY;
604                 break;
605         }
606         dbg("SEP Driver:<-------- ioctl end\n");
607         return error;
608 }
609
610
611
612 /*
613   interrupt handler function
614 */
615 irqreturn_t sep_inthandler(int irq, void *dev_id)
616 {
617         irqreturn_t int_error;
618         unsigned long error;
619         unsigned long reg_val;
620         unsigned long flow_id;
621         struct sep_flow_context_t *flow_context_ptr;
622
623         int_error = IRQ_HANDLED;
624
625         /* read the IRR register to check if this is SEP interrupt */
626         reg_val = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
627         edbg("SEP Interrupt - reg is %08lx\n", reg_val);
628
629         /* check if this is the flow interrupt */
630         if (0 /*reg_val & (0x1 << 11) */ ) {
631                 /* read GPRO to find out the which flow is done */
632                 flow_id = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
633
634                 /* find the contex of the flow */
635                 error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
636                 if (error)
637                         goto end_function_with_error;
638
639                 INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
640
641                 /* queue the work */
642                 queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq);
643
644         } else {
645                 /* check if this is reply interrupt from SEP */
646                 if (reg_val & (0x1 << 13)) {
647                         /* update the counter of reply messages */
648                         sep_dev->sep_to_host_reply_counter++;
649
650                         /* wake up the waiting process */
651                         wake_up(&g_sep_event);
652                 } else {
653                         int_error = IRQ_NONE;
654                         goto end_function;
655                 }
656         }
657 end_function_with_error:
658         /* clear the interrupt */
659         sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, reg_val);
660 end_function:
661         return int_error;
662 }
663
664
665 /*
666   This function prepares only input DMA table for synhronic symmetric
667   operations (HASH)
668 */
669 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)
670 {
671         /* pointer to the info entry of the table - the last entry */
672         struct sep_lli_entry_t *info_entry_ptr;
673         /* array of pointers ot page */
674         struct sep_lli_entry_t *lli_array_ptr;
675         /* points to the first entry to be processed in the lli_in_array */
676         unsigned long current_entry;
677         /* num entries in the virtual buffer */
678         unsigned long sep_lli_entries;
679         /* lli table pointer */
680         struct sep_lli_entry_t *in_lli_table_ptr;
681         /* the total data in one table */
682         unsigned long table_data_size;
683         /* number of entries in lli table */
684         unsigned long num_entries_in_table;
685         /* next table address */
686         unsigned long lli_table_alloc_addr;
687         unsigned long result;
688
689         dbg("SEP Driver:--------> sep_prepare_input_dma_table start\n");
690
691         edbg("SEP Driver:data_size is %lu\n", data_size);
692         edbg("SEP Driver:block_size is %lu\n", block_size);
693
694         /* initialize the pages pointers */
695         sep_dev->in_page_array = 0;
696         sep_dev->in_num_pages = 0;
697
698         if (data_size == 0) {
699                 /* special case  - created 2 entries table with zero data */
700                 in_lli_table_ptr = (struct sep_lli_entry_t *) (sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
701                 in_lli_table_ptr->physical_address = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
702                 in_lli_table_ptr->block_size = 0;
703
704                 in_lli_table_ptr++;
705                 in_lli_table_ptr->physical_address = 0xFFFFFFFF;
706                 in_lli_table_ptr->block_size = 0;
707
708                 *lli_table_ptr = sep_dev->phys_shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
709                 *num_entries_ptr = 2;
710                 *table_data_size_ptr = 0;
711
712                 goto end_function;
713         }
714
715         /* check if the pages are in Kernel Virtual Address layout */
716         if (isKernelVirtualAddress == true)
717                 /* lock the pages of the kernel buffer and translate them to pages */
718                 result = sep_lock_kernel_pages(app_virt_addr, data_size, &sep_dev->in_num_pages, &lli_array_ptr, &sep_dev->in_page_array);
719         else
720                 /* lock the pages of the user buffer and translate them to pages */
721                 result = sep_lock_user_pages(app_virt_addr, data_size, &sep_dev->in_num_pages, &lli_array_ptr, &sep_dev->in_page_array);
722
723         if (result)
724                 return result;
725
726         edbg("SEP Driver:output sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
727
728         current_entry = 0;
729         info_entry_ptr = 0;
730         sep_lli_entries = sep_dev->in_num_pages;
731
732         /* initiate to point after the message area */
733         lli_table_alloc_addr = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
734
735         /* loop till all the entries in in array are not processed */
736         while (current_entry < sep_lli_entries) {
737                 /* set the new input and output tables */
738                 in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
739
740                 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
741
742                 /* calculate the maximum size of data for input table */
743                 table_data_size = sep_calculate_lli_table_max_size(&lli_array_ptr[current_entry], (sep_lli_entries - current_entry));
744
745                 /* now calculate the table size so that it will be module block size */
746                 table_data_size = (table_data_size / block_size) * block_size;
747
748                 edbg("SEP Driver:output table_data_size is %lu\n", table_data_size);
749
750                 /* construct input lli table */
751                 sep_build_lli_table(&lli_array_ptr[current_entry], in_lli_table_ptr, &current_entry, &num_entries_in_table, table_data_size);
752
753                 if (info_entry_ptr == 0) {
754                         /* set the output parameters to physical addresses */
755                         *lli_table_ptr = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
756                         *num_entries_ptr = num_entries_in_table;
757                         *table_data_size_ptr = table_data_size;
758
759                         edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_ptr);
760                 } else {
761                         /* update the info entry of the previous in table */
762                         info_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
763                         info_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
764                 }
765
766                 /* save the pointer to the info entry of the current tables */
767                 info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
768         }
769
770         /* print input tables */
771         sep_debug_print_lli_tables((struct sep_lli_entry_t *)
772                                    sep_shared_area_phys_to_virt(*lli_table_ptr), *num_entries_ptr, *table_data_size_ptr);
773
774         /* the array of the pages */
775         kfree(lli_array_ptr);
776 end_function:
777         dbg("SEP Driver:<-------- sep_prepare_input_dma_table end\n");
778         return 0;
779
780 }
781
782 /*
783   This function builds input and output DMA tables for synhronic
784   symmetric operations (AES, DES). It also checks that each table
785   is of the modular block size
786 */
787 int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr,
788                                        unsigned long app_virt_out_addr,
789                                        unsigned long data_size,
790                                        unsigned long block_size,
791                                        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)
792 {
793         /* array of pointers of page */
794         struct sep_lli_entry_t *lli_in_array;
795         /* array of pointers of page */
796         struct sep_lli_entry_t *lli_out_array;
797         int result = 0;
798
799         dbg("SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
800
801         /* initialize the pages pointers */
802         sep_dev->in_page_array = 0;
803         sep_dev->out_page_array = 0;
804
805         /* check if the pages are in Kernel Virtual Address layout */
806         if (isKernelVirtualAddress == true) {
807                 /* lock the pages of the kernel buffer and translate them to pages */
808                 result = sep_lock_kernel_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array);
809                 if (result) {
810                         edbg("SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
811                         goto end_function;
812                 }
813         } else {
814                 /* lock the pages of the user buffer and translate them to pages */
815                 result = sep_lock_user_pages(app_virt_in_addr, data_size, &sep_dev->in_num_pages, &lli_in_array, &sep_dev->in_page_array);
816                 if (result) {
817                         edbg("SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
818                         goto end_function;
819                 }
820         }
821
822         if (isKernelVirtualAddress == true) {
823                 result = sep_lock_kernel_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array);
824                 if (result) {
825                         edbg("SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
826                         goto end_function_with_error1;
827                 }
828         } else {
829                 result = sep_lock_user_pages(app_virt_out_addr, data_size, &sep_dev->out_num_pages, &lli_out_array, &sep_dev->out_page_array);
830                 if (result) {
831                         edbg("SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
832                         goto end_function_with_error1;
833                 }
834         }
835         edbg("sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
836         edbg("sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages);
837         edbg("SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n", SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
838
839
840         /* call the fucntion that creates table from the lli arrays */
841         result = sep_construct_dma_tables_from_lli(lli_in_array, sep_dev->in_num_pages, lli_out_array, sep_dev->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);
842         if (result) {
843                 edbg("SEP Driver: sep_construct_dma_tables_from_lli failed\n");
844                 goto end_function_with_error2;
845         }
846
847         /* fall through - free the lli entry arrays */
848         dbg("in_num_entries_ptr is %08lx\n", *in_num_entries_ptr);
849         dbg("out_num_entries_ptr is %08lx\n", *out_num_entries_ptr);
850         dbg("table_data_size_ptr is %08lx\n", *table_data_size_ptr);
851 end_function_with_error2:
852         kfree(lli_out_array);
853 end_function_with_error1:
854         kfree(lli_in_array);
855 end_function:
856         dbg("SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n", (int) result);
857         return result;
858
859 }
860
861
862 /*
863  This function creates the input and output dma tables for
864  symmetric operations (AES/DES) according to the block size from LLI arays
865 */
866 int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t *lli_in_array,
867                                       unsigned long sep_in_lli_entries,
868                                       struct sep_lli_entry_t *lli_out_array,
869                                       unsigned long sep_out_lli_entries,
870                                       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)
871 {
872         /* points to the area where next lli table can be allocated */
873         unsigned long lli_table_alloc_addr;
874         /* input lli table */
875         struct sep_lli_entry_t *in_lli_table_ptr;
876         /* output lli table */
877         struct sep_lli_entry_t *out_lli_table_ptr;
878         /* pointer to the info entry of the table - the last entry */
879         struct sep_lli_entry_t *info_in_entry_ptr;
880         /* pointer to the info entry of the table - the last entry */
881         struct sep_lli_entry_t *info_out_entry_ptr;
882         /* points to the first entry to be processed in the lli_in_array */
883         unsigned long current_in_entry;
884         /* points to the first entry to be processed in the lli_out_array */
885         unsigned long current_out_entry;
886         /* max size of the input table */
887         unsigned long in_table_data_size;
888         /* max size of the output table */
889         unsigned long out_table_data_size;
890         /* flag te signifies if this is the first tables build from the arrays */
891         unsigned long first_table_flag;
892         /* the data size that should be in table */
893         unsigned long table_data_size;
894         /* number of etnries in the input table */
895         unsigned long num_entries_in_table;
896         /* number of etnries in the output table */
897         unsigned long num_entries_out_table;
898
899         dbg("SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
900
901         /* initiate to pint after the message area */
902         lli_table_alloc_addr = sep_dev->shared_area_addr + SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
903
904         current_in_entry = 0;
905         current_out_entry = 0;
906         first_table_flag = 1;
907         info_in_entry_ptr = 0;
908         info_out_entry_ptr = 0;
909
910         /* loop till all the entries in in array are not processed */
911         while (current_in_entry < sep_in_lli_entries) {
912                 /* set the new input and output tables */
913                 in_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
914
915                 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
916
917                 /* set the first output tables */
918                 out_lli_table_ptr = (struct sep_lli_entry_t *) lli_table_alloc_addr;
919
920                 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) * SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
921
922                 /* calculate the maximum size of data for input table */
923                 in_table_data_size = sep_calculate_lli_table_max_size(&lli_in_array[current_in_entry], (sep_in_lli_entries - current_in_entry));
924
925                 /* calculate the maximum size of data for output table */
926                 out_table_data_size = sep_calculate_lli_table_max_size(&lli_out_array[current_out_entry], (sep_out_lli_entries - current_out_entry));
927
928                 edbg("SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
929                 edbg("SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
930
931                 /* check where the data is smallest */
932                 table_data_size = in_table_data_size;
933                 if (table_data_size > out_table_data_size)
934                         table_data_size = out_table_data_size;
935
936                 /* now calculate the table size so that it will be module block size */
937                 table_data_size = (table_data_size / block_size) * block_size;
938
939                 dbg("SEP Driver:table_data_size is %lu\n", table_data_size);
940
941                 /* construct input lli table */
942                 sep_build_lli_table(&lli_in_array[current_in_entry], in_lli_table_ptr, &current_in_entry, &num_entries_in_table, table_data_size);
943
944                 /* construct output lli table */
945                 sep_build_lli_table(&lli_out_array[current_out_entry], out_lli_table_ptr, &current_out_entry, &num_entries_out_table, table_data_size);
946
947                 /* if info entry is null - this is the first table built */
948                 if (info_in_entry_ptr == 0) {
949                         /* set the output parameters to physical addresses */
950                         *lli_table_in_ptr = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
951                         *in_num_entries_ptr = num_entries_in_table;
952                         *lli_table_out_ptr = sep_shared_area_virt_to_phys((unsigned long) out_lli_table_ptr);
953                         *out_num_entries_ptr = num_entries_out_table;
954                         *table_data_size_ptr = table_data_size;
955
956                         edbg("SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
957                         edbg("SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
958                 } else {
959                         /* update the info entry of the previous in table */
960                         info_in_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) in_lli_table_ptr);
961                         info_in_entry_ptr->block_size = ((num_entries_in_table) << 24) | (table_data_size);
962
963                         /* update the info entry of the previous in table */
964                         info_out_entry_ptr->physical_address = sep_shared_area_virt_to_phys((unsigned long) out_lli_table_ptr);
965                         info_out_entry_ptr->block_size = ((num_entries_out_table) << 24) | (table_data_size);
966                 }
967
968                 /* save the pointer to the info entry of the current tables */
969                 info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
970                 info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
971
972                 edbg("SEP Driver:output num_entries_out_table is %lu\n", (unsigned long) num_entries_out_table);
973                 edbg("SEP Driver:output info_in_entry_ptr is %lu\n", (unsigned long) info_in_entry_ptr);
974                 edbg("SEP Driver:output info_out_entry_ptr is %lu\n", (unsigned long) info_out_entry_ptr);
975         }
976
977         /* print input tables */
978         sep_debug_print_lli_tables((struct sep_lli_entry_t *)
979                                    sep_shared_area_phys_to_virt(*lli_table_in_ptr), *in_num_entries_ptr, *table_data_size_ptr);
980         /* print output tables */
981         sep_debug_print_lli_tables((struct sep_lli_entry_t *)
982                                    sep_shared_area_phys_to_virt(*lli_table_out_ptr), *out_num_entries_ptr, *table_data_size_ptr);
983         dbg("SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
984         return 0;
985 }
986
987 /*
988   this function calculates the size of data that can be inserted into the lli
989   table from this array the condition is that either the table is full
990   (all etnries are entered), or there are no more entries in the lli array
991 */
992 unsigned long sep_calculate_lli_table_max_size(struct sep_lli_entry_t *lli_in_array_ptr, unsigned long num_array_entries)
993 {
994         unsigned long table_data_size = 0;
995         unsigned long counter;
996
997         /* calculate the data in the out lli table if till we fill the whole
998            table or till the data has ended */
999         for (counter = 0; (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) && (counter < num_array_entries); counter++)
1000                 table_data_size += lli_in_array_ptr[counter].block_size;
1001         return table_data_size;
1002 }
1003
1004 /*
1005   this functions builds ont lli table from the lli_array according to
1006   the given size of data
1007 */
1008 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)
1009 {
1010         unsigned long curr_table_data_size;
1011         /* counter of lli array entry */
1012         unsigned long array_counter;
1013
1014         dbg("SEP Driver:--------> sep_build_lli_table start\n");
1015
1016         /* init currrent table data size and lli array entry counter */
1017         curr_table_data_size = 0;
1018         array_counter = 0;
1019         *num_table_entries_ptr = 1;
1020
1021         edbg("SEP Driver:table_data_size is %lu\n", table_data_size);
1022
1023         /* fill the table till table size reaches the needed amount */
1024         while (curr_table_data_size < table_data_size) {
1025                 /* update the number of entries in table */
1026                 (*num_table_entries_ptr)++;
1027
1028                 lli_table_ptr->physical_address = lli_array_ptr[array_counter].physical_address;
1029                 lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
1030                 curr_table_data_size += lli_table_ptr->block_size;
1031
1032                 edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr);
1033                 edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1034                 edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1035
1036                 /* check for overflow of the table data */
1037                 if (curr_table_data_size > table_data_size) {
1038                         edbg("SEP Driver:curr_table_data_size > table_data_size\n");
1039
1040                         /* update the size of block in the table */
1041                         lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
1042
1043                         /* update the physical address in the lli array */
1044                         lli_array_ptr[array_counter].physical_address += lli_table_ptr->block_size;
1045
1046                         /* update the block size left in the lli array */
1047                         lli_array_ptr[array_counter].block_size = (curr_table_data_size - table_data_size);
1048                 } else
1049                         /* advance to the next entry in the lli_array */
1050                         array_counter++;
1051
1052                 edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1053                 edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1054
1055                 /* move to the next entry in table */
1056                 lli_table_ptr++;
1057         }
1058
1059         /* set the info entry to default */
1060         lli_table_ptr->physical_address = 0xffffffff;
1061         lli_table_ptr->block_size = 0;
1062
1063         edbg("SEP Driver:lli_table_ptr is %08lx\n", (unsigned long) lli_table_ptr);
1064         edbg("SEP Driver:lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1065         edbg("SEP Driver:lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1066
1067         /* set the output parameter */
1068         *num_processed_entries_ptr += array_counter;
1069
1070         edbg("SEP Driver:*num_processed_entries_ptr is %lu\n", *num_processed_entries_ptr);
1071         dbg("SEP Driver:<-------- sep_build_lli_table end\n");
1072         return;
1073 }
1074
1075 /*
1076   this function goes over the list of the print created tables and
1077   prints all the data
1078 */
1079 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)
1080 {
1081         unsigned long table_count;
1082         unsigned long entries_count;
1083
1084         dbg("SEP Driver:--------> sep_debug_print_lli_tables start\n");
1085
1086         table_count = 1;
1087         while ((unsigned long) lli_table_ptr != 0xffffffff) {
1088                 edbg("SEP Driver: lli table %08lx, table_data_size is %lu\n", table_count, table_data_size);
1089                 edbg("SEP Driver: num_table_entries is %lu\n", num_table_entries);
1090
1091                 /* print entries of the table (without info entry) */
1092                 for (entries_count = 0; entries_count < num_table_entries; entries_count++, lli_table_ptr++) {
1093                         edbg("SEP Driver:lli_table_ptr address is %08lx\n", (unsigned long) lli_table_ptr);
1094                         edbg("SEP Driver:phys address is %08lx block size is %lu\n", lli_table_ptr->physical_address, lli_table_ptr->block_size);
1095                 }
1096
1097                 /* point to the info entry */
1098                 lli_table_ptr--;
1099
1100                 edbg("SEP Driver:phys lli_table_ptr->block_size is %lu\n", lli_table_ptr->block_size);
1101                 edbg("SEP Driver:phys lli_table_ptr->physical_address is %08lx\n", lli_table_ptr->physical_address);
1102
1103
1104                 table_data_size = lli_table_ptr->block_size & 0xffffff;
1105                 num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
1106                 lli_table_ptr = (struct sep_lli_entry_t *)
1107                     (lli_table_ptr->physical_address);
1108
1109                 edbg("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);
1110
1111                 if ((unsigned long) lli_table_ptr != 0xffffffff)
1112                         lli_table_ptr = (struct sep_lli_entry_t *) sep_shared_area_phys_to_virt((unsigned long) lli_table_ptr);
1113
1114                 table_count++;
1115         }
1116         dbg("SEP Driver:<-------- sep_debug_print_lli_tables end\n");
1117 }
1118
1119
1120 /*
1121   This function locks all the physical pages of the application virtual buffer
1122   and construct a basic lli  array, where each entry holds the physical page
1123   address and the size that application data holds in this physical pages
1124 */
1125 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)
1126 {
1127         int error = 0;
1128         /* the the page of the end address of the user space buffer */
1129         unsigned long end_page;
1130         /* the page of the start address of the user space buffer */
1131         unsigned long start_page;
1132         /* the range in pages */
1133         unsigned long num_pages;
1134         struct page **page_array;
1135         struct sep_lli_entry_t *lli_array;
1136         unsigned long count;
1137         int result;
1138
1139         dbg("SEP Driver:--------> sep_lock_user_pages start\n");
1140
1141         /* set start and end pages  and num pages */
1142         end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
1143         start_page = app_virt_addr >> PAGE_SHIFT;
1144         num_pages = end_page - start_page + 1;
1145
1146         edbg("SEP Driver: app_virt_addr is %08lx\n", app_virt_addr);
1147         edbg("SEP Driver: data_size is %lu\n", data_size);
1148         edbg("SEP Driver: start_page is %lu\n", start_page);
1149         edbg("SEP Driver: end_page is %lu\n", end_page);
1150         edbg("SEP Driver: num_pages is %lu\n", num_pages);
1151
1152         /* allocate array of pages structure pointers */
1153         page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
1154         if (!page_array) {
1155                 edbg("SEP Driver: kmalloc for page_array failed\n");
1156
1157                 error = -ENOMEM;
1158                 goto end_function;
1159         }
1160
1161         lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1162         if (!lli_array) {
1163                 edbg("SEP Driver: kmalloc for lli_array failed\n");
1164
1165                 error = -ENOMEM;
1166                 goto end_function_with_error1;
1167         }
1168
1169         /* convert the application virtual address into a set of physical */
1170         down_read(&current->mm->mmap_sem);
1171         result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0, page_array, 0);
1172         up_read(&current->mm->mmap_sem);
1173
1174         /* check the number of pages locked - if not all then exit with error */
1175         if (result != num_pages) {
1176                 dbg("SEP Driver: not all pages locked by get_user_pages\n");
1177
1178                 error = -ENOMEM;
1179                 goto end_function_with_error2;
1180         }
1181
1182         /* flush the cache */
1183         for (count = 0; count < num_pages; count++)
1184                 flush_dcache_page(page_array[count]);
1185
1186         /* set the start address of the first page - app data may start not at
1187            the beginning of the page */
1188         lli_array[0].physical_address = ((unsigned long) page_to_phys(page_array[0])) + (app_virt_addr & (~PAGE_MASK));
1189
1190         /* check that not all the data is in the first page only */
1191         if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
1192                 lli_array[0].block_size = data_size;
1193         else
1194                 lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
1195
1196         /* debug print */
1197         dbg("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);
1198
1199         /* go from the second page to the prev before last */
1200         for (count = 1; count < (num_pages - 1); count++) {
1201                 lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]);
1202                 lli_array[count].block_size = PAGE_SIZE;
1203
1204                 edbg("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);
1205         }
1206
1207         /* if more then 1 pages locked - then update for the last page size needed */
1208         if (num_pages > 1) {
1209                 /* update the address of the last page */
1210                 lli_array[count].physical_address = (unsigned long) page_to_phys(page_array[count]);
1211
1212                 /* set the size of the last page */
1213                 lli_array[count].block_size = (app_virt_addr + data_size) & (~PAGE_MASK);
1214
1215                 if (lli_array[count].block_size == 0) {
1216                         dbg("app_virt_addr is %08lx\n", app_virt_addr);
1217                         dbg("data_size is %lu\n", data_size);
1218                         while (1);
1219                 }
1220                 edbg("lli_array[%lu].physical_address is %08lx, \
1221                 lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
1222         }
1223
1224         /* set output params */
1225         *lli_array_ptr = lli_array;
1226         *num_pages_ptr = num_pages;
1227         *page_array_ptr = page_array;
1228         goto end_function;
1229
1230 end_function_with_error2:
1231         /* release the cache */
1232         for (count = 0; count < num_pages; count++)
1233                 page_cache_release(page_array[count]);
1234         kfree(lli_array);
1235 end_function_with_error1:
1236         kfree(page_array);
1237 end_function:
1238         dbg("SEP Driver:<-------- sep_lock_user_pages end\n");
1239         return 0;
1240 }
1241
1242 /*
1243   This function locks all the physical pages of the kernel virtual buffer
1244   and construct a basic lli  array, where each entry holds the physical
1245   page address and the size that application data holds in this physical pages
1246 */
1247 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)
1248 {
1249         int error = 0;
1250         /* the the page of the end address of the user space buffer */
1251         unsigned long end_page;
1252         /* the page of the start address of the user space buffer */
1253         unsigned long start_page;
1254         /* the range in pages */
1255         unsigned long num_pages;
1256         struct sep_lli_entry_t *lli_array;
1257         /* next kernel address to map */
1258         unsigned long next_kernel_address;
1259         unsigned long count;
1260
1261         dbg("SEP Driver:--------> sep_lock_kernel_pages start\n");
1262
1263         /* set start and end pages  and num pages */
1264         end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
1265         start_page = kernel_virt_addr >> PAGE_SHIFT;
1266         num_pages = end_page - start_page + 1;
1267
1268         edbg("SEP Driver: kernel_virt_addr is %08lx\n", kernel_virt_addr);
1269         edbg("SEP Driver: data_size is %lu\n", data_size);
1270         edbg("SEP Driver: start_page is %lx\n", start_page);
1271         edbg("SEP Driver: end_page is %lx\n", end_page);
1272         edbg("SEP Driver: num_pages is %lu\n", num_pages);
1273
1274         lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1275         if (!lli_array) {
1276                 edbg("SEP Driver: kmalloc for lli_array failed\n");
1277                 error = -ENOMEM;
1278                 goto end_function;
1279         }
1280
1281         /* set the start address of the first page - app data may start not at
1282            the beginning of the page */
1283         lli_array[0].physical_address = (unsigned long) virt_to_phys((unsigned long *) kernel_virt_addr);
1284
1285         /* check that not all the data is in the first page only */
1286         if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
1287                 lli_array[0].block_size = data_size;
1288         else
1289                 lli_array[0].block_size = PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
1290
1291         /* debug print */
1292         dbg("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);
1293
1294         /* advance the address to the start of the next page */
1295         next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
1296
1297         /* go from the second page to the prev before last */
1298         for (count = 1; count < (num_pages - 1); count++) {
1299                 lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address);
1300                 lli_array[count].block_size = PAGE_SIZE;
1301
1302                 edbg("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);
1303                 next_kernel_address += PAGE_SIZE;
1304         }
1305
1306         /* if more then 1 pages locked - then update for the last page size needed */
1307         if (num_pages > 1) {
1308                 /* update the address of the last page */
1309                 lli_array[count].physical_address = (unsigned long) virt_to_phys((unsigned long *) next_kernel_address);
1310
1311                 /* set the size of the last page */
1312                 lli_array[count].block_size = (kernel_virt_addr + data_size) & (~PAGE_MASK);
1313
1314                 if (lli_array[count].block_size == 0) {
1315                         dbg("app_virt_addr is %08lx\n", kernel_virt_addr);
1316                         dbg("data_size is %lu\n", data_size);
1317                         while (1);
1318                 }
1319
1320                 edbg("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);
1321         }
1322         /* set output params */
1323         *lli_array_ptr = lli_array;
1324         *num_pages_ptr = num_pages;
1325         *page_array_ptr = 0;
1326 end_function:
1327         dbg("SEP Driver:<-------- sep_lock_kernel_pages end\n");
1328         return 0;
1329 }
1330
1331 /*
1332   This function releases all the application virtual buffer physical pages,
1333         that were previously locked
1334 */
1335 int sep_free_dma_pages(struct page **page_array_ptr, unsigned long num_pages, unsigned long dirtyFlag)
1336 {
1337         unsigned long count;
1338
1339         if (dirtyFlag) {
1340                 for (count = 0; count < num_pages; count++) {
1341                         /* the out array was written, therefore the data was changed */
1342                         if (!PageReserved(page_array_ptr[count]))
1343                                 SetPageDirty(page_array_ptr[count]);
1344                         page_cache_release(page_array_ptr[count]);
1345                 }
1346         } else {
1347                 /* free in pages - the data was only read, therefore no update was done
1348                    on those pages */
1349                 for (count = 0; count < num_pages; count++)
1350                         page_cache_release(page_array_ptr[count]);
1351         }
1352
1353         if (page_array_ptr)
1354                 /* free the array */
1355                 kfree(page_array_ptr);
1356
1357         return 0;
1358 }
1359
1360 /*
1361   This function raises interrupt to SEP that signals that is has a new
1362         command from HOST
1363 */
1364 static void sep_send_command_handler()
1365 {
1366         unsigned long count;
1367
1368         dbg("SEP Driver:--------> sep_send_command_handler start\n");
1369         sep_set_time(0, 0);
1370
1371         /* flash cache */
1372         flush_cache_all();
1373
1374         for (count = 0; count < 12 * 4; count += 4)
1375                 edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
1376
1377         /* update counter */
1378         sep_dev->host_to_sep_send_counter++;
1379         /* send interrupt to SEP */
1380         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
1381         dbg("SEP Driver:<-------- sep_send_command_handler end\n");
1382         return;
1383 }
1384
1385 /*
1386   This function raises interrupt to SEPm that signals that is has a
1387   new command from HOST
1388 */
1389 static void sep_send_reply_command_handler()
1390 {
1391         unsigned long count;
1392
1393         dbg("SEP Driver:--------> sep_send_reply_command_handler start\n");
1394
1395         /* flash cache */
1396         flush_cache_all();
1397         for (count = 0; count < 12 * 4; count += 4)
1398                 edbg("Word %lu of the message is %lu\n", count, *((unsigned long *) (sep_dev->shared_area_addr + count)));
1399         /* update counter */
1400         sep_dev->host_to_sep_send_counter++;
1401         /* send the interrupt to SEP */
1402         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, sep_dev->host_to_sep_send_counter);
1403         /* update both counters */
1404         sep_dev->host_to_sep_send_counter++;
1405         sep_dev->sep_to_host_reply_counter++;
1406         dbg("SEP Driver:<-------- sep_send_reply_command_handler end\n");
1407 }
1408
1409
1410
1411 /*
1412   This function handles the allocate data pool memory request
1413   This function returns calculates the physical address of the
1414   allocated memory, and the offset of this area from the mapped address.
1415   Therefore, the FVOs in user space can calculate the exact virtual
1416   address of this allocated memory
1417 */
1418 static int sep_allocate_data_pool_memory_handler(unsigned long arg)
1419 {
1420         int error;
1421         struct sep_driver_alloc_t command_args;
1422
1423         dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
1424
1425         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_alloc_t));
1426         if (error)
1427                 goto end_function;
1428
1429         /* allocate memory */
1430         if ((sep_dev->data_pool_bytes_allocated + command_args.num_bytes) > SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
1431                 error = -ENOTTY;
1432                 goto end_function;
1433         }
1434
1435         /* set the virtual and physical address */
1436         command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated;
1437         command_args.phys_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + sep_dev->data_pool_bytes_allocated;
1438
1439         /* write the memory back to the user space */
1440         error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_alloc_t));
1441         if (error)
1442                 goto end_function;
1443
1444         /* set the allocation */
1445         sep_dev->data_pool_bytes_allocated += command_args.num_bytes;
1446
1447 end_function:
1448         dbg("SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
1449         return error;
1450 }
1451
1452 /*
1453   This function  handles write into allocated data pool command
1454 */
1455 static int sep_write_into_data_pool_handler(unsigned long arg)
1456 {
1457         int error;
1458         unsigned long virt_address;
1459         unsigned long app_in_address;
1460         unsigned long num_bytes;
1461         unsigned long data_pool_area_addr;
1462
1463         dbg("SEP Driver:--------> sep_write_into_data_pool_handler start\n");
1464
1465         /* get the application address */
1466         error = get_user(app_in_address, &(((struct sep_driver_write_t *) arg)->app_address));
1467         if (error)
1468                 goto end_function;
1469
1470         /* get the virtual kernel address address */
1471         error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address));
1472         if (error)
1473                 goto end_function;
1474
1475         /* get the number of bytes */
1476         error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes));
1477         if (error)
1478                 goto end_function;
1479
1480         /* calculate the start of the data pool */
1481         data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
1482
1483
1484         /* check that the range of the virtual kernel address is correct */
1485         if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
1486                 error = -ENOTTY;
1487                 goto end_function;
1488         }
1489         /* copy the application data */
1490         error = copy_from_user((void *) virt_address, (void *) app_in_address, num_bytes);
1491 end_function:
1492         dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
1493         return error;
1494 }
1495
1496 /*
1497   this function handles the read from data pool command
1498 */
1499 static int sep_read_from_data_pool_handler(unsigned long arg)
1500 {
1501         int error;
1502         /* virtual address of dest application buffer */
1503         unsigned long app_out_address;
1504         /* virtual address of the data pool */
1505         unsigned long virt_address;
1506         unsigned long num_bytes;
1507         unsigned long data_pool_area_addr;
1508
1509         dbg("SEP Driver:--------> sep_read_from_data_pool_handler start\n");
1510
1511         /* get the application address */
1512         error = get_user(app_out_address, &(((struct sep_driver_write_t *) arg)->app_address));
1513         if (error)
1514                 goto end_function;
1515
1516         /* get the virtual kernel address address */
1517         error = get_user(virt_address, &(((struct sep_driver_write_t *) arg)->datapool_address));
1518         if (error)
1519                 goto end_function;
1520
1521         /* get the number of bytes */
1522         error = get_user(num_bytes, &(((struct sep_driver_write_t *) arg)->num_bytes));
1523         if (error)
1524                 goto end_function;
1525
1526         /* calculate the start of the data pool */
1527         data_pool_area_addr = sep_dev->shared_area_addr + SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
1528
1529         /* check that the range of the virtual kernel address is correct */
1530         if ((virt_address < data_pool_area_addr) || (virt_address > (data_pool_area_addr + SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
1531                 error = -ENOTTY;
1532                 goto end_function;
1533         }
1534
1535         /* copy the application data */
1536         error = copy_to_user((void *) app_out_address, (void *) virt_address, num_bytes);
1537 end_function:
1538         dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
1539         return error;
1540 }
1541
1542
1543 /*
1544   this function handles tha request for creation of the DMA table
1545   for the synchronic symmetric operations (AES,DES)
1546 */
1547 static int sep_create_sync_dma_tables_handler(unsigned long arg)
1548 {
1549         int error;
1550         /* command arguments */
1551         struct sep_driver_build_sync_table_t command_args;
1552
1553         dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
1554
1555         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_sync_table_t));
1556         if (error)
1557                 goto end_function;
1558
1559         edbg("app_in_address is %08lx\n", command_args.app_in_address);
1560         edbg("app_out_address is %08lx\n", command_args.app_out_address);
1561         edbg("data_size is %lu\n", command_args.data_in_size);
1562         edbg("block_size is %lu\n", command_args.block_size);
1563
1564         /* check if we need to build only input table or input/output */
1565         if (command_args.app_out_address)
1566                 /* prepare input and output tables */
1567                 error = sep_prepare_input_output_dma_table(command_args.app_in_address,
1568                                                            command_args.app_out_address,
1569                                                            command_args.data_in_size,
1570                                                            command_args.block_size,
1571                                                            &command_args.in_table_address,
1572                                                            &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);
1573         else
1574                 /* prepare input tables */
1575                 error = sep_prepare_input_dma_table(command_args.app_in_address,
1576                                                     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);
1577
1578         if (error)
1579                 goto end_function;
1580         /* copy to user */
1581         error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_build_sync_table_t));
1582 end_function:
1583         dbg("SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
1584         return error;
1585 }
1586
1587 /*
1588   this function handles the request for freeing dma table for synhronic actions
1589 */
1590 int sep_free_dma_table_data_handler()
1591 {
1592         dbg("SEP Driver:--------> sep_free_dma_table_data_handler start\n");
1593
1594         /* free input pages array */
1595         sep_free_dma_pages(sep_dev->in_page_array, sep_dev->in_num_pages, 0);
1596
1597         /* free output pages array if needed */
1598         if (sep_dev->out_page_array)
1599                 sep_free_dma_pages(sep_dev->out_page_array, sep_dev->out_num_pages, 1);
1600
1601         /* reset all the values */
1602         sep_dev->in_page_array = 0;
1603         sep_dev->out_page_array = 0;
1604         sep_dev->in_num_pages = 0;
1605         sep_dev->out_num_pages = 0;
1606         dbg("SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
1607         return 0;
1608 }
1609
1610 /*
1611   this function handles the request to create the DMA tables for flow
1612 */
1613 static int sep_create_flow_dma_tables_handler(unsigned long arg)
1614 {
1615         int error;
1616         struct sep_driver_build_flow_table_t command_args;
1617         /* first table - output */
1618         struct sep_lli_entry_t first_table_data;
1619         /* dma table data */
1620         struct sep_lli_entry_t last_table_data;
1621         /* pointer to the info entry of the previuos DMA table */
1622         struct sep_lli_entry_t *prev_info_entry_ptr;
1623         /* pointer to the flow data strucutre */
1624         struct sep_flow_context_t *flow_context_ptr;
1625
1626         dbg("SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
1627
1628         /* init variables */
1629         prev_info_entry_ptr = 0;
1630         first_table_data.physical_address = 0xffffffff;
1631
1632         /* find the free structure for flow data */
1633         error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
1634         if (error)
1635                 goto end_function;
1636
1637         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_build_flow_table_t));
1638         if (error)
1639                 goto end_function;
1640
1641         /* create flow tables */
1642         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);
1643         if (error)
1644                 goto end_function_with_error;
1645
1646         /* check if flow is static */
1647         if (!command_args.flow_type)
1648                 /* point the info entry of the last to the info entry of the first */
1649                 last_table_data = first_table_data;
1650
1651         /* set output params */
1652         command_args.first_table_addr = first_table_data.physical_address;
1653         command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
1654         command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
1655
1656         /* send the parameters to user application */
1657         error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_build_flow_table_t));
1658         if (error)
1659                 goto end_function_with_error;
1660
1661         /* all the flow created  - update the flow entry with temp id */
1662         flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
1663
1664         /* set the processing tables data in the context */
1665         if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
1666                 flow_context_ptr->input_tables_in_process = first_table_data;
1667         else
1668                 flow_context_ptr->output_tables_in_process = first_table_data;
1669
1670         goto end_function;
1671
1672 end_function_with_error:
1673         /* free the allocated tables */
1674         sep_deallocated_flow_tables(&first_table_data);
1675 end_function:
1676         dbg("SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
1677         return error;
1678 }
1679
1680 /*
1681   this functio n handles add tables to flow
1682 */
1683 static int sep_add_flow_tables_handler(unsigned long arg)
1684 {
1685         int error;
1686         unsigned long num_entries;
1687         struct sep_driver_add_flow_table_t command_args;
1688         struct sep_flow_context_t *flow_context_ptr;
1689         /* first dma table data */
1690         struct sep_lli_entry_t first_table_data;
1691         /* last dma table data */
1692         struct sep_lli_entry_t last_table_data;
1693         /* pointer to the info entry of the current DMA table */
1694         struct sep_lli_entry_t *info_entry_ptr;
1695
1696         dbg("SEP Driver:--------> sep_add_flow_tables_handler start\n");
1697
1698         /* get input parameters */
1699         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_flow_table_t));
1700         if (error)
1701                 goto end_function;
1702
1703         /* find the flow structure for the flow id */
1704         error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
1705         if (error)
1706                 goto end_function;
1707
1708         /* prepare the flow dma tables */
1709         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);
1710         if (error)
1711                 goto end_function_with_error;
1712
1713         /* now check if there is already an existing add table for this flow */
1714         if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
1715                 /* this buffer was for input buffers */
1716                 if (flow_context_ptr->input_tables_flag) {
1717                         /* add table already exists - add the new tables to the end
1718                            of the previous */
1719                         num_entries = (flow_context_ptr->last_input_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
1720
1721                         info_entry_ptr = (struct sep_lli_entry_t *)
1722                             (flow_context_ptr->last_input_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
1723
1724                         /* connect to list of tables */
1725                         *info_entry_ptr = first_table_data;
1726
1727                         /* set the first table data */
1728                         first_table_data = flow_context_ptr->first_input_table;
1729                 } else {
1730                         /* set the input flag */
1731                         flow_context_ptr->input_tables_flag = 1;
1732
1733                         /* set the first table data */
1734                         flow_context_ptr->first_input_table = first_table_data;
1735                 }
1736                 /* set the last table data */
1737                 flow_context_ptr->last_input_table = last_table_data;
1738         } else {                /* this is output tables */
1739
1740                 /* this buffer was for input buffers */
1741                 if (flow_context_ptr->output_tables_flag) {
1742                         /* add table already exists - add the new tables to
1743                            the end of the previous */
1744                         num_entries = (flow_context_ptr->last_output_table.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
1745
1746                         info_entry_ptr = (struct sep_lli_entry_t *)
1747                             (flow_context_ptr->last_output_table.physical_address + (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
1748
1749                         /* connect to list of tables */
1750                         *info_entry_ptr = first_table_data;
1751
1752                         /* set the first table data */
1753                         first_table_data = flow_context_ptr->first_output_table;
1754                 } else {
1755                         /* set the input flag */
1756                         flow_context_ptr->output_tables_flag = 1;
1757
1758                         /* set the first table data */
1759                         flow_context_ptr->first_output_table = first_table_data;
1760                 }
1761                 /* set the last table data */
1762                 flow_context_ptr->last_output_table = last_table_data;
1763         }
1764
1765         /* set output params */
1766         command_args.first_table_addr = first_table_data.physical_address;
1767         command_args.first_table_num_entries = ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
1768         command_args.first_table_data_size = (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
1769
1770         /* send the parameters to user application */
1771         error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_add_flow_table_t));
1772 end_function_with_error:
1773         /* free the allocated tables */
1774         sep_deallocated_flow_tables(&first_table_data);
1775 end_function:
1776         dbg("SEP Driver:<-------- sep_add_flow_tables_handler end\n");
1777         return error;
1778 }
1779
1780 /*
1781   this function add the flow add message to the specific flow
1782 */
1783 static int sep_add_flow_tables_message_handler(unsigned long arg)
1784 {
1785         int error;
1786         struct sep_driver_add_message_t command_args;
1787         struct sep_flow_context_t *flow_context_ptr;
1788
1789         dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
1790
1791         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_add_message_t));
1792         if (error)
1793                 goto end_function;
1794
1795         /* check input */
1796         if (command_args.message_size_in_bytes > SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
1797                 error = -ENOMEM;
1798                 goto end_function;
1799         }
1800
1801         /* find the flow context */
1802         error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
1803         if (error)
1804                 goto end_function;
1805
1806         /* copy the message into context */
1807         flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
1808         error = copy_from_user(flow_context_ptr->message, (void *) command_args.message_address, command_args.message_size_in_bytes);
1809 end_function:
1810         dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
1811         return error;
1812 }
1813
1814
1815 /*
1816   this function returns the physical and virtual addresses of the static pool
1817 */
1818 static int sep_get_static_pool_addr_handler(unsigned long arg)
1819 {
1820         int error;
1821         struct sep_driver_static_pool_addr_t command_args;
1822
1823         dbg("SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
1824
1825         /*prepare the output parameters in the struct */
1826         command_args.physical_static_address = sep_dev->phys_shared_area_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
1827         command_args.virtual_static_address = sep_dev->shared_area_addr + SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
1828
1829         edbg("SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n", command_args.physical_static_address, command_args.virtual_static_address);
1830
1831         /* send the parameters to user application */
1832         error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_static_pool_addr_t));
1833         dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
1834         return error;
1835 }
1836
1837 /*
1838   this address gets the offset of the physical address from the start
1839   of the mapped area
1840 */
1841 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
1842 {
1843         int error;
1844         struct sep_driver_get_mapped_offset_t command_args;
1845
1846         dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
1847
1848         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_get_mapped_offset_t));
1849         if (error)
1850                 goto end_function;
1851
1852         if (command_args.physical_address < sep_dev->phys_shared_area_addr) {
1853                 error = -ENOTTY;
1854                 goto end_function;
1855         }
1856
1857         /*prepare the output parameters in the struct */
1858         command_args.offset = command_args.physical_address - sep_dev->phys_shared_area_addr;
1859
1860         edbg("SEP Driver:physical_address is %08lx, offset is %lu\n", command_args.physical_address, command_args.offset);
1861
1862         /* send the parameters to user application */
1863         error = copy_to_user((void *) arg, &command_args, sizeof(struct sep_driver_get_mapped_offset_t));
1864 end_function:
1865         dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
1866         return error;
1867 }
1868
1869
1870 /*
1871   ?
1872 */
1873 static int sep_start_handler(void)
1874 {
1875         unsigned long reg_val;
1876         unsigned long error = 0;
1877
1878         dbg("SEP Driver:--------> sep_start_handler start\n");
1879
1880         /* wait in polling for message from SEP */
1881         do
1882                 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
1883         while (!reg_val);
1884
1885         /* check the value */
1886         if (reg_val == 0x1)
1887                 /* fatal error - read erro status from GPRO */
1888                 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
1889 end_function:
1890         dbg("SEP Driver:<-------- sep_start_handler end\n");
1891         return error;
1892 }
1893
1894 /*
1895   this function handles the request for SEP initialization
1896 */
1897 static int sep_init_handler(unsigned long arg)
1898 {
1899         unsigned long message_word;
1900         unsigned long *message_ptr;
1901         struct sep_driver_init_t command_args;
1902         unsigned long counter;
1903         unsigned long error;
1904         unsigned long reg_val;
1905
1906         dbg("SEP Driver:--------> sep_init_handler start\n");
1907         error = 0;
1908
1909         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_init_t));
1910
1911         dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
1912
1913         if (error)
1914                 goto end_function;
1915
1916         /* PATCH - configure the DMA to single -burst instead of multi-burst */
1917         /*sep_configure_dma_burst(); */
1918
1919         dbg("SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
1920
1921         message_ptr = (unsigned long *) command_args.message_addr;
1922
1923         /* set the base address of the SRAM  */
1924         sep_write_reg(sep_dev, HW_SRAM_ADDR_REG_ADDR, HW_CC_SRAM_BASE_ADDRESS);
1925
1926         for (counter = 0; counter < command_args.message_size_in_words; counter++, message_ptr++) {
1927                 get_user(message_word, message_ptr);
1928                 /* write data to SRAM */
1929                 sep_write_reg(sep_dev, HW_SRAM_DATA_REG_ADDR, message_word);
1930                 edbg("SEP Driver:message_word is %lu\n", message_word);
1931                 /* wait for write complete */
1932                 sep_wait_sram_write(sep_dev);
1933         }
1934         dbg("SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
1935         /* signal SEP */
1936         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x1);
1937
1938         do
1939                 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
1940         while (!(reg_val & 0xFFFFFFFD));
1941
1942         dbg("SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
1943
1944         /* check the value */
1945         if (reg_val == 0x1) {
1946                 edbg("SEP Driver:init failed\n");
1947
1948                 error = sep_read_reg(sep_dev, 0x8060);
1949                 edbg("SEP Driver:sw monitor is %lu\n", error);
1950
1951                 /* fatal error - read erro status from GPRO */
1952                 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
1953                 edbg("SEP Driver:error is %lu\n", error);
1954         }
1955 end_function:
1956         dbg("SEP Driver:<-------- sep_init_handler end\n");
1957         return error;
1958
1959 }
1960
1961 /*
1962   this function handles the request cache and resident reallocation
1963 */
1964 static int sep_realloc_cache_resident_handler(unsigned long arg)
1965 {
1966         int error;
1967         unsigned long phys_cache_address;
1968         unsigned long phys_resident_address;
1969         struct sep_driver_realloc_cache_resident_t command_args;
1970
1971         /* copy the data */
1972         error = copy_from_user(&command_args, (void *) arg, sizeof(struct sep_driver_realloc_cache_resident_t));
1973         if (error)
1974                 goto end_function;
1975
1976         /* copy cache and resident to the their intended locations */
1977         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);
1978         if (error)
1979                 goto end_function;
1980
1981         /* lock the area (if needed) */
1982         sep_lock_cache_resident_area();
1983
1984         command_args.new_base_addr = sep_dev->phys_shared_area_addr;
1985
1986         /* find the new base address according to the lowest address between
1987            cache, resident and shared area */
1988         if (phys_resident_address < command_args.new_base_addr)
1989                 command_args.new_base_addr = phys_resident_address;
1990         if (phys_cache_address < command_args.new_base_addr)
1991                 command_args.new_base_addr = phys_cache_address;
1992
1993         /* set the return parameters */
1994         command_args.new_cache_addr = phys_cache_address;
1995         command_args.new_resident_addr = phys_resident_address;
1996
1997         /* set the new shared area */
1998         command_args.new_shared_area_addr = sep_dev->phys_shared_area_addr;
1999
2000         edbg("SEP Driver:command_args.new_shared_area_addr is %08lx\n", command_args.new_shared_area_addr);
2001         edbg("SEP Driver:command_args.new_base_addr is %08lx\n", command_args.new_base_addr);
2002         edbg("SEP Driver:command_args.new_resident_addr is %08lx\n", command_args.new_resident_addr);
2003         edbg("SEP Driver:command_args.new_cache_addr is %08lx\n", command_args.new_cache_addr);
2004
2005         /* return to user */
2006         error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_realloc_cache_resident_t));
2007 end_function:
2008         return error;
2009 }
2010
2011 /*
2012   this function handles the request for get time
2013 */
2014 static int sep_get_time_handler(unsigned long arg)
2015 {
2016         int error;
2017         struct sep_driver_get_time_t command_args;
2018
2019         error = sep_set_time(&command_args.time_physical_address, &command_args.time_value);
2020         error = copy_to_user((void *) arg, (void *) &command_args, sizeof(struct sep_driver_get_time_t));
2021         return error;
2022
2023 }
2024
2025 /*
2026   This api handles the setting of API mode to blocking or non-blocking
2027 */
2028 static int sep_set_api_mode_handler(unsigned long arg)
2029 {
2030         int error;
2031         unsigned long mode_flag;
2032
2033         dbg("SEP Driver:--------> sep_set_api_mode_handler start\n");
2034
2035         error = get_user(mode_flag, &(((struct sep_driver_set_api_mode_t *) arg)->mode));
2036         if (error)
2037                 goto end_function;
2038
2039         /* set the global flag */
2040         sep_dev->block_mode_flag = mode_flag;
2041 end_function:
2042         dbg("SEP Driver:<-------- sep_set_api_mode_handler end\n");
2043         return error;
2044 }
2045
2046 /*
2047   This API handles the end transaction request
2048 */
2049 static int sep_end_transaction_handler(unsigned long arg)
2050 {
2051         dbg("SEP Driver:--------> sep_end_transaction_handler start\n");
2052
2053 #if 0                           /*!SEP_DRIVER_POLLING_MODE */
2054         /* close IMR */
2055         sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
2056
2057         /* release IRQ line */
2058         free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
2059
2060         /* lock the sep mutex */
2061         mutex_unlock(&sep_mutex);
2062 #endif
2063
2064         dbg("SEP Driver:<-------- sep_end_transaction_handler end\n");
2065
2066         return 0;
2067 }
2068
2069 /* handler for flow done interrupt */
2070 static void sep_flow_done_handler(struct work_struct *work)
2071 {
2072         struct sep_flow_context_t *flow_data_ptr;
2073
2074         /* obtain the mutex */
2075         mutex_lock(&sep_mutex);
2076
2077         /* get the pointer to context */
2078         flow_data_ptr = (struct sep_flow_context_t *) work;
2079
2080         /* free all the current input tables in sep */
2081         sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
2082
2083         /* free all the current tables output tables in SEP (if needed) */
2084         if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
2085                 sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
2086
2087         /* check if we have additional tables to be sent to SEP only input
2088            flag may be checked */
2089         if (flow_data_ptr->input_tables_flag) {
2090                 /* copy the message to the shared RAM and signal SEP */
2091                 memcpy((void *) flow_data_ptr->message, (void *) sep_dev->shared_area_addr, flow_data_ptr->message_size_in_bytes);
2092
2093                 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2);
2094         }
2095         mutex_unlock(&sep_mutex);
2096 }
2097
2098
2099 /*
2100   This function creates a list of tables for flow and returns the data for
2101         the first and last tables of the list
2102 */
2103 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
2104                                        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)
2105 {
2106         int error;
2107         unsigned long virt_buff_addr;
2108         unsigned long virt_buff_size;
2109         struct sep_lli_entry_t table_data;
2110         struct sep_lli_entry_t *info_entry_ptr;
2111         struct sep_lli_entry_t *prev_info_entry_ptr;
2112         unsigned long i;
2113
2114         /* init vars */
2115         error = 0;
2116         prev_info_entry_ptr = 0;
2117
2118         /* init the first table to default */
2119         table_data.physical_address = 0xffffffff;
2120         first_table_data_ptr->physical_address = 0xffffffff;
2121         table_data.block_size = 0;
2122
2123         for (i = 0; i < num_virtual_buffers; i++) {
2124                 /* get the virtual buffer address */
2125                 error = get_user(virt_buff_addr, &first_buff_addr);
2126                 if (error)
2127                         goto end_function;
2128
2129                 /* get the virtual buffer size */
2130                 first_buff_addr++;
2131                 error = get_user(virt_buff_size, &first_buff_addr);
2132                 if (error)
2133                         goto end_function;
2134
2135                 /* advance the address to point to the next pair of address|size */
2136                 first_buff_addr++;
2137
2138                 /* now prepare the one flow LLI table from the data */
2139                 error = sep_prepare_one_flow_dma_table(virt_buff_addr, virt_buff_size, &table_data, &info_entry_ptr, flow_data_ptr, isKernelVirtualAddress);
2140                 if (error)
2141                         goto end_function;
2142
2143                 if (i == 0) {
2144                         /* if this is the first table - save it to return to the user
2145                            application */
2146                         *first_table_data_ptr = table_data;
2147
2148                         /* set the pointer to info entry */
2149                         prev_info_entry_ptr = info_entry_ptr;
2150                 } else {
2151                         /* not first table - the previous table info entry should
2152                            be updated */
2153                         prev_info_entry_ptr->block_size = (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) | (table_data.block_size);
2154
2155                         /* set the pointer to info entry */
2156                         prev_info_entry_ptr = info_entry_ptr;
2157                 }
2158         }
2159
2160         /* set the last table data */
2161         *last_table_data_ptr = table_data;
2162 end_function:
2163         return error;
2164 }
2165
2166
2167 /*
2168   This function creates one DMA table for flow and returns its data,
2169   and pointer to its info entry
2170 */
2171 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)
2172 {
2173         int error;
2174         /* the range in pages */
2175         unsigned long lli_array_size;
2176         struct sep_lli_entry_t *lli_array;
2177         struct sep_lli_entry_t *flow_dma_table_entry_ptr;
2178         unsigned long *start_dma_table_ptr;
2179         /* total table data counter */
2180         unsigned long dma_table_data_count;
2181         /* pointer that will keep the pointer to the pages of the virtual buffer */
2182         struct page **page_array_ptr;
2183         unsigned long entry_count;
2184
2185         /* find the space for the new table */
2186         error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
2187         if (error)
2188                 goto end_function;
2189
2190         /* check if the pages are in Kernel Virtual Address layout */
2191         if (isKernelVirtualAddress == true)
2192                 /* lock kernel buffer in the memory */
2193                 error = sep_lock_kernel_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
2194         else
2195                 /* lock user buffer in the memory */
2196                 error = sep_lock_user_pages(virt_buff_addr, virt_buff_size, &lli_array_size, &lli_array, &page_array_ptr);
2197
2198         if (error)
2199                 goto end_function;
2200
2201         /* set the pointer to page array at the beginning of table - this table is
2202            now considered taken */
2203         *start_dma_table_ptr = lli_array_size;
2204
2205         /* point to the place of the pages pointers of the table */
2206         start_dma_table_ptr++;
2207
2208         /* set the pages pointer */
2209         *start_dma_table_ptr = (unsigned long) page_array_ptr;
2210
2211         /* set the pointer to the first entry */
2212         flow_dma_table_entry_ptr = (struct sep_lli_entry_t *) (++start_dma_table_ptr);
2213
2214         /* now create the entries for table */
2215         for (dma_table_data_count = entry_count = 0; entry_count < lli_array_size; entry_count++) {
2216                 flow_dma_table_entry_ptr->physical_address = lli_array[entry_count].physical_address;
2217
2218                 flow_dma_table_entry_ptr->block_size = lli_array[entry_count].block_size;
2219
2220                 /* set the total data of a table */
2221                 dma_table_data_count += lli_array[entry_count].block_size;
2222
2223                 flow_dma_table_entry_ptr++;
2224         }
2225
2226         /* set the physical address */
2227         table_data->physical_address = virt_to_phys(start_dma_table_ptr);
2228
2229         /* set the num_entries and total data size */
2230         table_data->block_size = ((lli_array_size + 1) << SEP_NUM_ENTRIES_OFFSET_IN_BITS) | (dma_table_data_count);
2231
2232         /* set the info entry */
2233         flow_dma_table_entry_ptr->physical_address = 0xffffffff;
2234         flow_dma_table_entry_ptr->block_size = 0;
2235
2236         /* set the pointer to info entry */
2237         *info_entry_ptr = flow_dma_table_entry_ptr;
2238
2239         /* the array of the lli entries */
2240         kfree(lli_array);
2241 end_function:
2242         return error;
2243 }
2244
2245
2246 /*
2247   This function returns pointer to the  flow data structure
2248   that contains the given id
2249 */
2250 static int sep_find_flow_context(unsigned long flow_id, struct sep_flow_context_t **flow_data_ptr)
2251 {
2252         unsigned long count;
2253         int error = 0;
2254
2255         /*
2256            always search for flow with id default first - in case we
2257            already started working on the flow there can be no situation
2258            when 2 flows are with default flag
2259          */
2260         for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
2261                 if (sep_dev->flows_data_array[count].flow_id == flow_id) {
2262                         *flow_data_ptr = &sep_dev->flows_data_array[count];
2263                         break;
2264                 }
2265         }
2266
2267         if (count == SEP_DRIVER_NUM_FLOWS)
2268                 /* no flow found  */
2269                 error = -ENOMEM;
2270
2271         return error;
2272 }
2273
2274 /*
2275   this function find a space for the new flow dma table
2276 */
2277 static int sep_find_free_flow_dma_table_space(unsigned long **table_address_ptr)
2278 {
2279         int error = 0;
2280         /* pointer to the id field of the flow dma table */
2281         unsigned long *start_table_ptr;
2282         unsigned long flow_dma_area_start_addr;
2283         unsigned long flow_dma_area_end_addr;
2284         /* maximum table size in words */
2285         unsigned long table_size_in_words;
2286
2287         /* find the start address of the flow DMA table area */
2288         flow_dma_area_start_addr = sep_dev->shared_area_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
2289
2290         /* set end address of the flow table area */
2291         flow_dma_area_end_addr = flow_dma_area_start_addr + SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
2292
2293         /* set table size in words */
2294         table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE * (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
2295
2296         /* set the pointer to the start address of DMA area */
2297         start_table_ptr = (unsigned long *) flow_dma_area_start_addr;
2298
2299         /* find the space for the next table */
2300         while (((*start_table_ptr & 0x7FFFFFFF) != 0) && ((unsigned long) start_table_ptr < flow_dma_area_end_addr))
2301                 start_table_ptr += table_size_in_words;
2302
2303         /* check if we reached the end of floa tables area */
2304         if ((unsigned long) start_table_ptr >= flow_dma_area_end_addr)
2305                 error = -1;
2306         else
2307                 *table_address_ptr = start_table_ptr;
2308
2309         return error;
2310 }
2311
2312 /*
2313   this function goes over all the flow tables connected to the given
2314         table and deallocate them
2315 */
2316 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
2317 {
2318         /* id pointer */
2319         unsigned long *table_ptr;
2320         /* end address of the flow dma area */
2321         unsigned long num_entries;
2322         unsigned long num_pages;
2323         struct page **pages_ptr;
2324         /* maximum table size in words */
2325         struct sep_lli_entry_t *info_entry_ptr;
2326
2327         /* set the pointer to the first table */
2328         table_ptr = (unsigned long *) first_table_ptr->physical_address;
2329
2330         /* set the num of entries */
2331         num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
2332             & SEP_NUM_ENTRIES_MASK;
2333
2334         /* go over all the connected tables */
2335         while (*table_ptr != 0xffffffff) {
2336                 /* get number of pages */
2337                 num_pages = *(table_ptr - 2);
2338
2339                 /* get the pointer to the pages */
2340                 pages_ptr = (struct page **) (*(table_ptr - 1));
2341
2342                 /* free the pages */
2343                 sep_free_dma_pages(pages_ptr, num_pages, 1);
2344
2345                 /* goto to the info entry */
2346                 info_entry_ptr = ((struct sep_lli_entry_t *) table_ptr) + (num_entries - 1);
2347
2348                 table_ptr = (unsigned long *) info_entry_ptr->physical_address;
2349                 num_entries = (info_entry_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2350         }
2351
2352         return;
2353 }
2354
2355 /*
2356   This function handler the set flow id command
2357 */
2358 static int sep_set_flow_id_handler(unsigned long arg)
2359 {
2360         int error;
2361         unsigned long flow_id;
2362         struct sep_flow_context_t *flow_data_ptr;
2363
2364         dbg("------------>SEP Driver: sep_set_flow_id_handler start\n");
2365
2366         error = get_user(flow_id, &(((struct sep_driver_set_flow_id_t *) arg)->flow_id));
2367         if (error)
2368                 goto end_function;
2369
2370         /* find the flow data structure that was just used for creating new flow
2371            - its id should be default */
2372         error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
2373         if (error)
2374                 goto end_function;
2375
2376         /* set flow id */
2377         flow_data_ptr->flow_id = flow_id;
2378
2379 end_function:
2380         dbg("SEP Driver:<-------- sep_set_flow_id_handler end\n");
2381         return error;
2382 }
2383
2384
2385 /*
2386   calculates time and sets it at the predefined address
2387 */
2388 static int sep_set_time(unsigned long *address_ptr, unsigned long *time_in_sec_ptr)
2389 {
2390         struct timeval time;
2391         /* address of time in the kernel */
2392         unsigned long time_addr;
2393
2394
2395         dbg("SEP Driver:--------> sep_set_time start\n");
2396
2397         do_gettimeofday(&time);
2398
2399         /* set value in the SYSTEM MEMORY offset */
2400         time_addr = sep_dev->message_shared_area_addr + SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
2401
2402         *(unsigned long *) time_addr = SEP_TIME_VAL_TOKEN;
2403         *(unsigned long *) (time_addr + 4) = time.tv_sec;
2404
2405         edbg("SEP Driver:time.tv_sec is %lu\n", time.tv_sec);
2406         edbg("SEP Driver:time_addr is %lu\n", time_addr);
2407         edbg("SEP Driver:g_message_shared_area_addr is %lu\n", sep_dev->message_shared_area_addr);
2408
2409         /* set the output parameters if needed */
2410         if (address_ptr)
2411                 *address_ptr = sep_shared_area_virt_to_phys(time_addr);
2412
2413         if (time_in_sec_ptr)
2414                 *time_in_sec_ptr = time.tv_sec;
2415
2416         dbg("SEP Driver:<-------- sep_set_time end\n");
2417
2418         return 0;
2419 }
2420
2421 static void sep_wait_busy(struct sep_device *dev)
2422 {
2423         u32 reg;
2424
2425         do {
2426                 reg = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
2427         } while (reg);
2428 }
2429
2430 /*
2431   PATCH for configuring the DMA to single burst instead of multi-burst
2432 */
2433 static void sep_configure_dma_burst(void)
2434 {
2435 #define          HW_AHB_RD_WR_BURSTS_REG_ADDR            0x0E10UL
2436
2437         dbg("SEP Driver:<-------- sep_configure_dma_burst start \n");
2438
2439         /* request access to registers from SEP */
2440         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2441
2442         dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg)  \n");
2443
2444         sep_wait_busy(sep_dev);
2445
2446         dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop)  \n");
2447
2448         /* set the DMA burst register to single burst */
2449         sep_write_reg(sep_dev, HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
2450
2451         /* release the sep busy */
2452         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
2453         sep_wait_busy(sep_dev);
2454
2455         dbg("SEP Driver:<-------- sep_configure_dma_burst done  \n");
2456
2457 }
2458
2459 /*
2460   this function registers the driver to the file system
2461 */
2462 static int sep_register_driver_to_fs(void)
2463 {
2464         int ret_val = alloc_chrdev_region(&g_sep_device_number, 0, 1, "sep_sec_driver");
2465         if (ret_val) {
2466                 edbg("sep_driver:major number allocation failed, retval is %d\n", ret_val);
2467                 goto end_function;
2468         }
2469
2470         /* set the files operations structure */
2471         g_sep_fops.owner = THIS_MODULE;
2472         g_sep_fops.ioctl = sep_ioctl;
2473         g_sep_fops.poll = sep_poll;
2474         g_sep_fops.open = sep_open;
2475         g_sep_fops.release = sep_release;
2476         g_sep_fops.mmap = sep_mmap;
2477
2478         /* init cdev */
2479         cdev_init(&g_sep_cdev, &g_sep_fops);
2480         g_sep_cdev.owner = THIS_MODULE;
2481
2482         /* register the driver with the kernel */
2483         ret_val = cdev_add(&g_sep_cdev, g_sep_device_number, 1);
2484
2485         if (ret_val) {
2486                 edbg("sep_driver:cdev_add failed, retval is %d\n", ret_val);
2487                 goto end_function_unregister_devnum;
2488         }
2489
2490         goto end_function;
2491
2492 end_function_unregister_devnum:
2493
2494         /* unregister dev numbers */
2495         unregister_chrdev_region(g_sep_device_number, 1);
2496
2497 end_function:
2498       return ret_val;
2499 }
2500
2501 /*
2502   this function unregisters driver from fs
2503 */
2504 static void sep_unregister_driver_from_fs(void)
2505 {
2506         cdev_del(&g_sep_cdev);
2507         /* unregister dev numbers */
2508         unregister_chrdev_region(g_sep_device_number, 1);
2509 }
2510
2511
2512 /*--------------------------------------------------------------
2513   init function
2514 ----------------------------------------------------------------*/
2515 static int __init sep_init(void)
2516 {
2517         int ret_val = 0;
2518         int counter;
2519         int size;               /* size of memory for allocation */
2520
2521         dbg("SEP Driver:-------->Init start\n");
2522         edbg("sep->shared_area_addr = %lx\n", (unsigned long) &sep_dev->shared_area_addr);
2523
2524         /* transaction counter that coordinates the transactions between SEP
2525         and HOST */
2526         sep_dev->host_to_sep_send_counter = 0;
2527
2528         /* counter for the messages from sep */
2529         sep_dev->sep_to_host_reply_counter = 0;
2530
2531         /* counter for the number of bytes allocated in the pool
2532         for the current transaction */
2533         sep_dev->data_pool_bytes_allocated = 0;
2534
2535         /* set the starting mode to blocking */
2536         sep_dev->block_mode_flag = 1;
2537
2538         ret_val = sep_register_driver_to_device();
2539         if (ret_val) {
2540                 edbg("sep_driver:sep_driver_to_device failed, ret_val is %d\n", ret_val);
2541                 goto end_function_unregister_from_fs;
2542         }
2543         /* calculate the total size for allocation */
2544         size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
2545             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;
2546
2547         /* allocate the shared area */
2548         if (sep_map_and_alloc_shared_area(size, &sep_dev->shared_area_addr, &sep_dev->phys_shared_area_addr)) {
2549                 ret_val = -ENOMEM;
2550                 /* allocation failed */
2551                 goto end_function_unmap_io_memory;
2552         }
2553         /* now set the memory regions */
2554         sep_dev->message_shared_area_addr = sep_dev->shared_area_addr;
2555
2556         edbg("SEP Driver: g_message_shared_area_addr is %08lx\n", sep_dev->message_shared_area_addr);
2557
2558 #if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
2559         /* send the new SHARED MESSAGE AREA to the SEP */
2560         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep_dev->phys_shared_area_addr);
2561
2562         /* poll for SEP response */
2563         retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
2564         while (retVal != 0xffffffff && retVal != sep_dev->phys_shared_area_addr)
2565                 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
2566
2567         /* check the return value (register) */
2568         if (retVal != sep_dev->phys_shared_area_addr) {
2569                 ret_val = -ENOMEM;
2570                 goto end_function_deallocate_message_area;
2571         }
2572 #endif
2573         /* init the flow contextes */
2574         for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
2575                 sep_dev->flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
2576
2577         sep_dev->flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
2578         if (sep_dev->flow_wq_ptr == 0) {
2579                 ret_val = -ENOMEM;
2580                 edbg("sep_driver:flow queue creation failed\n");
2581                 goto end_function_deallocate_sep_shared_area;
2582         }
2583         edbg("SEP Driver: create flow workqueue \n");
2584
2585         /* register driver to fs */
2586         ret_val = sep_register_driver_to_fs();
2587         if (ret_val)
2588                 goto end_function_deallocate_sep_shared_area;
2589         /* load the rom code */
2590         sep_load_rom_code();
2591         goto end_function;
2592 end_function_unregister_from_fs:
2593         /* unregister from fs */
2594         sep_unregister_driver_from_fs();
2595 end_function_deallocate_sep_shared_area:
2596         /* de-allocate shared area */
2597         sep_unmap_and_free_shared_area(size, sep_dev->shared_area_addr, sep_dev->phys_shared_area_addr);
2598 end_function_unmap_io_memory:
2599         iounmap((void *) sep_dev->reg_base_address);
2600         /* release io memory region */
2601         release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
2602 end_function:
2603         dbg("SEP Driver:<-------- Init end\n");
2604         return ret_val;
2605 }
2606
2607
2608 /*-------------------------------------------------------------
2609   exit function
2610 --------------------------------------------------------------*/
2611 static void __exit sep_exit(void)
2612 {
2613         int size;
2614
2615         dbg("SEP Driver:--------> Exit start\n");
2616
2617         /* unregister from fs */
2618         sep_unregister_driver_from_fs();
2619         /* calculate the total size for de-allocation */
2620         size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
2621             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;
2622         /* free shared area  */
2623         sep_unmap_and_free_shared_area(size, sep_dev->shared_area_addr, sep_dev->phys_shared_area_addr);
2624         edbg("SEP Driver: free pages SEP SHARED AREA \n");
2625         iounmap((void *) sep_dev->reg_base_address);
2626         edbg("SEP Driver: iounmap \n");
2627         /* release io memory region */
2628         release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
2629         edbg("SEP Driver: release_mem_region \n");
2630         dbg("SEP Driver:<-------- Exit end\n");
2631 }
2632
2633
2634 module_init(sep_init);
2635 module_exit(sep_exit);
2636
2637 MODULE_LICENSE("GPL");