]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/sep/sep_main_mod.c
7e2fd3d1fbe25a06dff61c154f49f9ae09b2e3ee
[karo-tx-linux.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(
119                         struct sep_lli_entry_t  *lli_in_array_ptr,
120                         unsigned long   num_array_entries);
121 /*
122   this functions builds ont lli table from the lli_array according to the
123   given size of data
124 */
125 static void sep_build_lli_table(struct sep_lli_entry_t  *lli_array_ptr,
126                         struct sep_lli_entry_t          *lli_table_ptr,
127                         unsigned long           *num_processed_entries_ptr,
128                         unsigned long           *num_table_entries_ptr,
129                         unsigned long   table_data_size);
130
131 /*
132   this function goes over the list of the print created tables and prints
133   all the data
134 */
135 static void sep_debug_print_lli_tables(struct sep_lli_entry_t   *lli_table_ptr,
136                                         unsigned long   num_table_entries,
137                                         unsigned long   table_data_size);
138
139
140
141 /*
142   This function raises interrupt to SEPm that signals that is has a new
143   command from HOST
144 */
145 static void sep_send_command_handler(void);
146
147
148 /*
149   This function raises interrupt to SEP that signals that is has a
150   new reply from HOST
151 */
152 static void sep_send_reply_command_handler(void);
153
154 /*
155   This function handles the allocate data pool memory request
156   This function returns calculates the physical address of the allocated memory
157   and the offset of this area from the mapped address. Therefore, the FVOs in
158   user space can calculate the exact virtual address of this allocated memory
159 */
160 static int sep_allocate_data_pool_memory_handler(unsigned long arg);
161
162
163 /*
164   This function  handles write into allocated data pool command
165 */
166 static int sep_write_into_data_pool_handler(unsigned long arg);
167
168 /*
169   this function handles the read from data pool command
170 */
171 static int sep_read_from_data_pool_handler(unsigned long arg);
172
173 /*
174   this function handles tha request for creation of the DMA table
175   for the synchronic symmetric operations (AES,DES)
176 */
177 static int sep_create_sync_dma_tables_handler(unsigned long arg);
178
179 /*
180   this function handles the request to create the DMA tables for flow
181 */
182 static int sep_create_flow_dma_tables_handler(unsigned long arg);
183
184 /*
185   This API handles the end transaction request
186 */
187 static int sep_end_transaction_handler(unsigned long arg);
188
189
190 /*
191   this function handles add tables to flow
192 */
193 static int sep_add_flow_tables_handler(unsigned long arg);
194
195 /*
196   this function add the flow add message to the specific flow
197 */
198 static int sep_add_flow_tables_message_handler(unsigned long arg);
199
200 /*
201   this function handles the request for SEP start
202 */
203 static int sep_start_handler(void);
204
205 /*
206   this function handles the request for SEP initialization
207 */
208 static int sep_init_handler(unsigned long arg);
209
210 /*
211   this function handles the request cache and resident reallocation
212 */
213 static int sep_realloc_cache_resident_handler(unsigned long arg);
214
215
216 /*
217   This api handles the setting of API mode to blocking or non-blocking
218 */
219 static int sep_set_api_mode_handler(unsigned long arg);
220
221 /* handler for flow done interrupt */
222 static void sep_flow_done_handler(struct work_struct            *work);
223
224 /*
225   This function locks all the physical pages of the kernel virtual buffer
226   and construct a basic lli  array, where each entry holds the physical
227   page address and the size that application data holds in this physical pages
228 */
229 static int sep_lock_kernel_pages(unsigned long  kernel_virt_addr,
230                                 unsigned long   data_size,
231                                 unsigned long   *num_pages_ptr,
232                                 struct sep_lli_entry_t  **lli_array_ptr,
233                                 struct page     ***page_array_ptr);
234
235 /*
236   This function creates one DMA table for flow and returns its data,
237   and pointer to its info entry
238 */
239 static int sep_prepare_one_flow_dma_table(unsigned long  virt_buff_addr,
240                         unsigned long    virt_buff_size,
241                         struct sep_lli_entry_t          *table_data,
242                         struct sep_lli_entry_t          **info_entry_ptr,
243                         struct sep_flow_context_t       *flow_data_ptr,
244                         bool                    isKernelVirtualAddress);
245
246 /*
247   This function creates a list of tables for flow and returns the data for the
248   first and last tables of the list
249 */
250 static int sep_prepare_flow_dma_tables(unsigned long    num_virtual_buffers,
251                 unsigned long           first_buff_addr,
252                 struct sep_flow_context_t       *flow_data_ptr,
253                 struct sep_lli_entry_t          *first_table_data_ptr,
254                 struct sep_lli_entry_t          *last_table_data_ptr,
255                 bool                    isKernelVirtualAddress);
256
257 /*
258   this function find a space for the new flow dma table
259 */
260 static int sep_find_free_flow_dma_table_space(
261         unsigned long           **table_address_ptr);
262
263 /*
264   this function goes over all the flow tables connected to the given table and
265   deallocate them
266 */
267 static void sep_deallocated_flow_tables(
268                 struct sep_lli_entry_t *first_table_ptr);
269
270 /*
271   This function handler the set flow id command
272 */
273 static int sep_set_flow_id_handler(unsigned long arg);
274
275 /*
276   This function returns pointer to the  flow data structure
277   that conatins the given id
278 */
279 static int sep_find_flow_context(unsigned long flow_id,
280                                 struct sep_flow_context_t **flow_data_ptr);
281
282
283 /*
284   this function returns the physical and virtual addresses of the static pool
285 */
286 static int sep_get_static_pool_addr_handler(unsigned long arg);
287
288 /*
289   this address gets the offset of the physical address from the start of
290   the mapped area
291 */
292 static int sep_get_physical_mapped_offset_handler(unsigned long arg);
293
294
295 /*
296   this function handles the request for get time
297 */
298 static int sep_get_time_handler(unsigned long arg);
299
300 /*
301   calculates time and sets it at the predefined address
302 */
303 static int sep_set_time(unsigned long   *address_ptr,
304                         unsigned long   *time_in_sec_ptr);
305
306 /*
307   PATCH for configuring the DMA to single burst instead of multi-burst
308 */
309 static void sep_configure_dma_burst(void);
310
311 /*
312         This function locks all the physical pages of the
313         application virtual buffer and construct a basic lli
314         array, where each entry holds the physical page address
315         and the size that application data holds in this physical pages
316 */
317 static int sep_lock_user_pages(unsigned long  app_virt_addr,
318                                 unsigned long       data_size,
319                                 unsigned long      *num_pages_ptr,
320                                 struct sep_lli_entry_t   **lli_array_ptr,
321                                 struct page      ***page_array_ptr);
322
323 /*---------------------------------------------
324         FUNCTIONS
325 -----------------------------------------------*/
326
327 /*
328   this function locks SEP by locking the semaphore
329 */
330 int sep_lock()
331 {
332   mutex_lock(&sep_mutex);
333
334   return 0;
335 }
336
337 /*
338   this function unlocks SEP
339 */
340 void sep_unlock()
341 {
342   /* release mutex */
343   mutex_unlock(&sep_mutex);
344 }
345
346 /*
347   this function returns the address of the message shared area
348 */
349 void sep_map_shared_area(unsigned long          *mappedAddr_ptr)
350 {
351   *mappedAddr_ptr = sep_dev->shared_area_addr;
352 }
353
354 /*
355   this function returns the address of the message shared area
356 */
357 void sep_send_msg_rdy_cmd()
358 {
359   sep_send_command_handler();
360 }
361
362 /* this functions frees all the resources that were allocated for the building
363 of the LLI DMA tables */
364 void sep_free_dma_resources()
365 {
366   sep_free_dma_table_data_handler();
367 }
368
369 /* poll(suspend), until reply from sep */
370 void sep_driver_poll()
371 {
372   unsigned long retVal = 0;
373
374 #ifdef SEP_DRIVER_POLLING_MODE
375
376   while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF))
377         retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
378
379   sep_dev->sep_to_host_reply_counter++;
380 #else
381   /* poll, until reply from sep */
382   wait_event(g_sep_event,
383   (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter));
384
385 #endif
386 }
387
388 /*----------------------------------------------------------------------
389   open function of the character driver - must only lock the mutex
390         must also release the memory data pool allocations
391 ------------------------------------------------------------------------*/
392 static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
393 {
394   /* return value */
395   int                   error;
396
397   /*-----------------
398         CODE
399   ---------------------*/
400
401   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> open start\n");
402
403   error = 0;
404
405   /* check the blocking mode */
406   if (sep_dev->block_mode_flag)
407         /* lock mutex */
408         mutex_lock(&sep_mutex);
409   else
410         error = mutex_trylock(&sep_mutex);
411
412   /* check the error */
413   if (error) {
414         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
415                 "SEP Driver: down_interruptible failed\n");
416
417         goto end_function;
418   }
419
420   /* release data pool allocations */
421   sep_dev->data_pool_bytes_allocated = 0;
422
423 end_function:
424
425   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- open end\n");
426
427   return error;
428 }
429
430
431
432
433 /*------------------------------------------------------------
434         release function
435 -------------------------------------------------------------*/
436 static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
437 {
438   /*-----------------
439         CODE
440   ---------------------*/
441
442   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
443                 "----------->SEP Driver: sep_release start\n");
444
445 #if 0/*!SEP_DRIVER_POLLING_MODE*/
446   /* close IMR */
447   sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
448
449   /* release IRQ line */
450   free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
451
452 #endif
453
454   /* unlock the sep mutex */
455   mutex_unlock(&sep_mutex);
456
457   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
458                 "SEP Driver:<-------- sep_release end\n");
459
460   return 0;
461 }
462
463
464
465
466 /*---------------------------------------------------------------
467   map function - this functions maps the message shared area
468 -----------------------------------------------------------------*/
469 static int sep_mmap(struct file  *filp, struct vm_area_struct  *vma)
470 {
471   /* physical addr */
472   unsigned long phys_addr;
473
474   /*-----------------------
475         CODE
476   -------------------------*/
477
478   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "-------->SEP Driver: mmap start\n");
479
480   /* check that the size of the mapped range is as the size of the message
481   shared area */
482   if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
483         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
484                 "SEP Driver mmap requested size is more than allowed\n");
485         printk(KERN_WARNING "SEP Driver mmap requested size is more \
486                         than allowed\n");
487         printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
488         vma->vm_end);
489         printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
490         vma->vm_start);
491         return -EAGAIN;
492   }
493
494   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
495   "SEP Driver:g_message_shared_area_addr is %08lx\n",
496   sep_dev->message_shared_area_addr);
497
498   /* get physical address */
499   phys_addr  = sep_dev->phys_shared_area_addr;
500
501   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: phys_addr is %08lx\n",
502 phys_addr);
503
504   if (remap_pfn_range(vma,
505          vma->vm_start,
506          phys_addr >> PAGE_SHIFT,
507          vma->vm_end - vma->vm_start,
508          vma->vm_page_prot)) {
509         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
510                 "SEP Driver remap_page_range failed\n");
511         printk(KERN_WARNING  "SEP Driver remap_page_range failed\n");
512         return -EAGAIN;
513   }
514
515   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- mmap end\n");
516
517   return 0;
518 }
519
520
521 /*-----------------------------------------------
522   poll function
523 *----------------------------------------------*/
524 static unsigned int sep_poll(struct file  *filp, poll_table  *wait)
525 {
526   unsigned long count;
527
528   unsigned int  mask = 0;
529
530   /* flow id */
531   unsigned long retVal = 0;
532
533   /*----------------------------------------------
534         CODE
535   -------------------------------------------------*/
536
537   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "---------->SEP Driver poll: start\n");
538
539
540 #if SEP_DRIVER_POLLING_MODE
541
542   while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
543         retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
544
545         for (count = 0; count < 10 * 4; count += 4)
546         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
547         "Poll Debug Word %lu of the message is %lu\n",
548         count,
549         *((unsigned long *)(sep_dev->shared_area_addr +
550         SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
551   }
552
553   sep_dev->sep_to_host_reply_counter++;
554 #else
555   /* add the event to the polling wait table */
556   poll_wait(filp, &g_sep_event, wait);
557
558 #endif
559
560   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
561         "sep_dev->host_to_sep_send_counter is %lu\n",
562                 sep_dev->host_to_sep_send_counter);
563   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
564         "sep_dev->sep_to_host_reply_counter is %lu\n",
565         sep_dev->sep_to_host_reply_counter);
566
567   /* check if the data is ready */
568   if (sep_dev->host_to_sep_send_counter ==  sep_dev->sep_to_host_reply_counter) {
569         for (count = 0; count < 12 * 4; count += 4)
570         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
571         "Sep Mesg Word %lu of the message is %lu\n",
572         count, *((unsigned long *)(sep_dev->shared_area_addr + count)));
573
574         for (count = 0; count < 10 * 4; count += 4)
575         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
576         "Debug Data Word %lu of the message is %lu\n",
577         count,
578         *((unsigned long *)(sep_dev->shared_area_addr + 0x1800 + count)));
579
580         retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
581         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "retVal is %lu\n", retVal);
582         /* check if the this is sep reply or request */
583         if (retVal >> 31) {
584         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
585         "SEP Driver: sep request in\n");
586           /* request */
587           mask |= POLLOUT | POLLWRNORM;
588         } else {
589         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: sep reply in\n");
590           mask |= POLLIN | POLLRDNORM;
591         }
592   }
593
594   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:<-------- poll exit\n");
595   return mask;
596 }
597
598
599 static int sep_ioctl(struct inode               *inode,
600                                         struct file             *filp,
601                                         unsigned int            cmd,
602                                         unsigned long           arg)
603 {
604
605   /* error */
606   int                   error;
607
608   /*------------------------
609         CODE
610   ------------------------*/
611   error = 0;
612
613   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
614                 "------------>SEP Driver: ioctl start\n");
615
616   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: cmd is %x\n", cmd);
617
618   /* check that the command is for sep device */
619   if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
620         error = -ENOTTY;
621
622         switch (cmd) {
623         case SEP_IOCSENDSEPCOMMAND:
624
625           /* send command to SEP */
626         sep_send_command_handler();
627
628         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
629                 "SEP Driver: after sep_send_command_handler\n");
630
631           break;
632
633         case SEP_IOCSENDSEPRPLYCOMMAND:
634
635           /* send reply command to SEP */
636         sep_send_reply_command_handler();
637
638           break;
639
640         case SEP_IOCALLOCDATAPOLL:
641
642           /* allocate data pool */
643         error = sep_allocate_data_pool_memory_handler(arg);
644
645           break;
646
647         case SEP_IOCWRITEDATAPOLL:
648
649           /* write data into memory pool */
650         error = sep_write_into_data_pool_handler(arg);
651
652           break;
653
654         case SEP_IOCREADDATAPOLL:
655
656           /* read data from data pool into application memory */
657         error = sep_read_from_data_pool_handler(arg);
658
659           break;
660
661         case SEP_IOCCREATESYMDMATABLE:
662
663           /* create dma table for synhronic operation */
664         error = sep_create_sync_dma_tables_handler(arg);
665
666           break;
667
668         case SEP_IOCCREATEFLOWDMATABLE:
669
670           /* create flow dma tables */
671         error = sep_create_flow_dma_tables_handler(arg);
672
673           break;
674
675         case SEP_IOCFREEDMATABLEDATA:
676
677           /* free the pages */
678         error = sep_free_dma_table_data_handler();
679
680           break;
681
682         case SEP_IOCSETFLOWID:
683
684           /* set flow id */
685         error = sep_set_flow_id_handler(arg);
686
687           break;
688
689         case SEP_IOCADDFLOWTABLE:
690
691           /* add tables to the dynamic flow */
692         error = sep_add_flow_tables_handler(arg);
693
694           break;
695
696         case SEP_IOCADDFLOWMESSAGE:
697
698           /* add message of add tables to flow */
699         error = sep_add_flow_tables_message_handler(arg);
700
701           break;
702
703         case SEP_IOCSEPSTART:
704
705           /* start command to sep */
706         error = sep_start_handler();
707           break;
708
709         case SEP_IOCSEPINIT:
710
711           /* init command to sep */
712         error = sep_init_handler(arg);
713           break;
714
715         case SEP_IOCSETAPIMODE:
716
717           /* set non- blocking mode */
718         error = sep_set_api_mode_handler(arg);
719
720           break;
721
722         case SEP_IOCGETSTATICPOOLADDR:
723
724                 /* get the physical and virtual addresses of the static pool */
725                 error = sep_get_static_pool_addr_handler(arg);
726
727                 break;
728
729         case SEP_IOCENDTRANSACTION:
730
731         error = sep_end_transaction_handler(arg);
732
733                 break;
734
735         case SEP_IOCREALLOCCACHERES:
736
737         error = sep_realloc_cache_resident_handler(arg);
738
739           break;
740
741         case SEP_IOCGETMAPPEDADDROFFSET:
742
743         error = sep_get_physical_mapped_offset_handler(arg);
744
745           break;
746         case SEP_IOCGETIME:
747
748         error = sep_get_time_handler(arg);
749
750           break;
751
752         default:
753         error = -ENOTTY;
754           break;
755   }
756
757   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
758                 "SEP Driver:<-------- ioctl end\n");
759
760   return error;
761 }
762
763
764 /*
765   this function registers the driver to the file system
766 */
767 static int  sep_register_driver_to_fs(void)
768 {
769   /* return value */
770   int                   ret_val;
771
772   /*---------------------
773         CODE
774   -----------------------*/
775
776   ret_val = alloc_chrdev_region(&g_sep_device_number, 0, 1, "sep_sec_driver");
777   if (ret_val) {
778         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
779         "sep_driver:major number allocation failed, retval is %d\n", ret_val);
780         goto end_function;
781   }
782
783   /* set the files operations structure */
784   g_sep_fops.owner = THIS_MODULE;
785   g_sep_fops.ioctl = sep_ioctl;
786   g_sep_fops.poll = sep_poll;
787   g_sep_fops.open = sep_open;
788   g_sep_fops.release = sep_release;
789   g_sep_fops.mmap = sep_mmap;
790
791   /* init cdev */
792   cdev_init(&g_sep_cdev, &g_sep_fops);
793   g_sep_cdev.owner = THIS_MODULE;
794
795   /* register the driver with the kernel */
796   ret_val = cdev_add(&g_sep_cdev, g_sep_device_number, 1);
797
798   if (ret_val) {
799         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
800         "sep_driver:cdev_add failed, retval is %d\n",
801         ret_val);
802         goto end_function_unregister_devnum;
803   }
804
805   goto end_function;
806
807 end_function_unregister_devnum:
808
809   /* unregister dev numbers */
810   unregister_chrdev_region(g_sep_device_number, 1);
811
812 end_function:
813
814   return ret_val;
815 }
816
817 /*
818   this function unregisters driver from fs
819 */
820 static void sep_unregister_driver_from_fs(void)
821 {
822   /*-------------------
823         CODE
824   ---------------------*/
825
826   cdev_del(&g_sep_cdev);
827
828   /* unregister dev numbers */
829   unregister_chrdev_region(g_sep_device_number, 1);
830 }
831
832 /*--------------------------------------------------------------
833   init function
834 ----------------------------------------------------------------*/
835 static int __init sep_init(void)
836 {
837   /* return value */
838   int                   ret_val;
839
840   /* counter */
841   int                   counter;
842
843   /* size to of memory for allocation */
844   int                   size;
845
846   /*------------------------
847         CODE
848   ------------------------*/
849
850   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
851                 "SEP Driver:-------->Init start\n");
852   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
853         "g_sep_shared_area_addr = %lx\n",
854         (unsigned long)&sep_dev->shared_area_addr);
855
856   ret_val = 0;
857
858 /* transaction counter that coordinates the transactions between SEP
859         and HOST */
860   sep_dev->host_to_sep_send_counter = 0;
861
862 /* counter for the messages from sep */
863   sep_dev->sep_to_host_reply_counter = 0;
864
865 /* counter for the number of bytes allocated in the pool
866 for the current transaction */
867   sep_dev->data_pool_bytes_allocated = 0;
868
869   /* set the starting mode to blocking */
870   sep_dev->block_mode_flag = 1;
871
872
873   ret_val = sep_register_driver_to_device();
874   if (ret_val) {
875         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
876         "sep_driver:sep_driver_to_device failed, ret_val is %d\n",
877         ret_val);
878         goto end_function_unregister_from_fs;
879   }
880
881   /* calculate the total size for allocation */
882   size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
883                 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
884                 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
885                 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
886                 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
887                 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
888
889
890
891   /* allocate the shared area */
892   if (sep_map_and_alloc_shared_area(size,
893                                 &sep_dev->shared_area_addr,
894                                 &sep_dev->phys_shared_area_addr)) {
895         ret_val = -ENOMEM;
896         /* allocation failed */
897         goto end_function_unmap_io_memory;
898   }
899
900   /* now set the memory regions */
901   sep_dev->message_shared_area_addr = sep_dev->shared_area_addr;
902
903   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
904         "SEP Driver: g_message_shared_area_addr is %08lx\n",
905         sep_dev->message_shared_area_addr);
906
907 #if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
908
909   /* send the new SHARED MESSAGE AREA to the SEP */
910   sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR1_REG_ADDR,
911                         sep_dev->phys_shared_area_addr);
912
913   /* poll for SEP response */
914   retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
915   while (retVal != 0xffffffff && retVal != sep_dev->phys_shared_area_addr)
916         retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
917
918   /* check the return value (register) */
919   if (retVal != sep_dev->phys_shared_area_addr) {
920         ret_val = -ENOMEM;
921         goto end_function_deallocate_message_area;
922   }
923
924 #endif
925
926   /* init the flow contextes */
927   for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
928         sep_dev->flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
929
930   sep_dev->flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
931   if (sep_dev->flow_wq_ptr == 0) {
932         ret_val = -ENOMEM;
933         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
934                 "sep_driver:flow queue creation failed\n");
935         goto end_function_deallocate_sep_shared_area;
936   }
937
938   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
939                 "SEP Driver: create flow workqueue \n");
940
941   /* register driver to fs */
942   ret_val = sep_register_driver_to_fs();
943   if (ret_val)
944         goto end_function_deallocate_sep_shared_area;
945
946   /* load the rom code */
947   sep_load_rom_code();
948
949   goto end_function;
950
951 end_function_unregister_from_fs:
952
953   /* unregister from fs */
954   sep_unregister_driver_from_fs();
955
956 end_function_deallocate_sep_shared_area:
957
958   /* de-allocate shared area */
959   sep_unmap_and_free_shared_area(size,
960                                 sep_dev->shared_area_addr,
961                                 sep_dev->phys_shared_area_addr);
962
963 end_function_unmap_io_memory:
964
965   iounmap((void *)sep_dev->reg_base_address);
966
967   /* release io memory region */
968   release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
969
970 end_function:
971
972   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,  "SEP Driver:<-------- Init end\n");
973
974   return ret_val;
975 }
976
977
978
979
980 /*-------------------------------------------------------------
981   exit function
982 --------------------------------------------------------------*/
983 static void __exit sep_exit(void)
984 {
985   /* size */
986   int                   size;
987
988   /*-----------------------------
989         CODE
990   --------------------------------*/
991
992   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC, "SEP Driver:--------> Exit start\n");
993
994   /* unregister from fs */
995   sep_unregister_driver_from_fs();
996
997   /* calculate the total size for de-allocation */
998   size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
999                 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
1000                 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
1001                 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
1002                 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
1003                 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
1004
1005
1006   /* free shared area  */
1007   sep_unmap_and_free_shared_area(size,
1008                                 sep_dev->shared_area_addr,
1009                                 sep_dev->phys_shared_area_addr);
1010
1011   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1012                 "SEP Driver: free pages SEP SHARED AREA \n");
1013
1014   iounmap((void *)sep_dev->reg_base_address);
1015
1016   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: iounmap \n");
1017
1018   /* release io memory region */
1019   release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
1020
1021   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver: release_mem_region \n");
1022
1023   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,  "SEP Driver:<-------- Exit end\n");
1024 }
1025
1026
1027 /*
1028   interrupt handler function
1029 */
1030 irqreturn_t sep_inthandler(int irq, void *dev_id)
1031 {
1032   /* int error */
1033   irqreturn_t                   int_error;
1034
1035   /* error */
1036   unsigned long         error;
1037
1038   /* reg value */
1039   unsigned long         reg_val;
1040
1041   /* flow id */
1042   unsigned long          flow_id;
1043
1044   /* flow context */
1045   struct sep_flow_context_t             *flow_context_ptr;
1046
1047   /*-----------------------------
1048         CODE
1049   -----------------------------*/
1050
1051   int_error = IRQ_HANDLED;
1052
1053   /* read the IRR register to check if this is SEP interrupt */
1054   reg_val = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
1055   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Interrupt - reg is %08lx\n",
1056                         reg_val);
1057
1058   /* check if this is the flow interrupt */
1059   if (0/*reg_val & (0x1 << 11)*/) {
1060         /* read GPRO to find out the which flow is done */
1061         flow_id = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
1062
1063         /* find the contex of the flow */
1064         error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
1065         if (error)
1066                 goto end_function_with_error;
1067
1068         INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
1069
1070         /* queue the work */
1071         queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq);
1072
1073   } else {
1074         /* check if this is reply interrupt from SEP */
1075         if (reg_val & (0x1 << 13)) {
1076                 /* update the counter of reply messages */
1077                 sep_dev->sep_to_host_reply_counter++;
1078
1079                 /* wake up the waiting process */
1080                 wake_up(&g_sep_event);
1081         } else {
1082                 int_error = IRQ_NONE;
1083                 goto end_function;
1084         }
1085   }
1086
1087 end_function_with_error:
1088
1089   /* clear the interrupt */
1090   sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, reg_val);
1091
1092 end_function:
1093
1094   return int_error;
1095 }
1096
1097
1098 /*
1099   This function prepares only input DMA table for synhronic symmetric
1100   operations (HASH)
1101 */
1102 int sep_prepare_input_dma_table(unsigned long   app_virt_addr,
1103                                 unsigned long   data_size,
1104                                 unsigned long   block_size,
1105                                 unsigned long   *lli_table_ptr,
1106                                 unsigned long   *num_entries_ptr,
1107                                 unsigned long   *table_data_size_ptr,
1108                                 bool                    isKernelVirtualAddress)
1109
1110 {
1111   /* pointer to the info entry of the table - the last entry */
1112   struct sep_lli_entry_t                *info_entry_ptr;
1113
1114   /* array of pointers ot page */
1115   struct sep_lli_entry_t                *lli_array_ptr;
1116
1117   /* points to the first entry to be processed in the lli_in_array */
1118   unsigned long         current_entry;
1119
1120   /* num entries in the virtual buffer */
1121   unsigned long         sep_lli_entries;
1122
1123   /* lli table pointer */
1124   struct sep_lli_entry_t                *in_lli_table_ptr;
1125
1126   /* the total data in one table */
1127   unsigned long         table_data_size;
1128
1129   /* number of entries in lli table */
1130   unsigned long         num_entries_in_table;
1131
1132   /* next table address */
1133   unsigned long         lli_table_alloc_addr;
1134
1135   /* result */
1136   unsigned long         result;
1137
1138   /*------------------------
1139         CODE
1140   --------------------------*/
1141
1142   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1143                 "SEP Driver:--------> sep_prepare_input_dma_table start\n");
1144
1145   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:data_size is %lu\n",
1146                 data_size);
1147   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED, "SEP Driver:block_size is %lu\n",
1148                 block_size);
1149
1150   /* initialize the pages pointers */
1151   sep_dev->in_page_array = 0;
1152   sep_dev->in_num_pages = 0;
1153
1154   if (data_size == 0) {
1155         /* special case  - created 2 entries table with zero data */
1156         in_lli_table_ptr = (struct sep_lli_entry_t *)(sep_dev->shared_area_addr +
1157                         SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
1158         in_lli_table_ptr->physical_address = sep_dev->shared_area_addr +
1159                         SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1160         in_lli_table_ptr->block_size = 0;
1161
1162         in_lli_table_ptr++;
1163         in_lli_table_ptr->physical_address = 0xFFFFFFFF;
1164         in_lli_table_ptr->block_size = 0;
1165
1166         *lli_table_ptr = sep_dev->phys_shared_area_addr +
1167                         SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1168         *num_entries_ptr = 2;
1169         *table_data_size_ptr = 0;
1170
1171         goto end_function;
1172   }
1173
1174   /* check if the pages are in Kernel Virtual Address layout */
1175   if (isKernelVirtualAddress == true)
1176         /* lock the pages of the kernel buffer and translate them to pages */
1177         result = sep_lock_kernel_pages(app_virt_addr,
1178                                         data_size,
1179                                         &sep_dev->in_num_pages,
1180                                         &lli_array_ptr,
1181                                         &sep_dev->in_page_array);
1182   else
1183         /* lock the pages of the user buffer and translate them to pages */
1184         result = sep_lock_user_pages(app_virt_addr,
1185                                 data_size,
1186                                 &sep_dev->in_num_pages,
1187                                 &lli_array_ptr,
1188                                 &sep_dev->in_page_array);
1189
1190   if (result)
1191         return result;
1192
1193   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1194   "SEP Driver:output sep_dev->in_num_pages is %lu\n",
1195   sep_dev->in_num_pages);
1196
1197   current_entry = 0;
1198   info_entry_ptr = 0;
1199   sep_lli_entries = sep_dev->in_num_pages;
1200
1201   /* initiate to point after the message area */
1202   lli_table_alloc_addr = sep_dev->shared_area_addr +
1203                 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1204
1205   /* loop till all the entries in in array are not processed */
1206   while (current_entry < sep_lli_entries) {
1207         /* set the new input and output tables */
1208         in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1209
1210         lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1211                                 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1212
1213         /* calculate the maximum size of data for input table */
1214         table_data_size = sep_calculate_lli_table_max_size(
1215                 &lli_array_ptr[current_entry],
1216                 (sep_lli_entries - current_entry));
1217
1218         /* now calculate the table size so that it will be module block size */
1219         table_data_size = (table_data_size / block_size) * block_size;
1220
1221         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1222         "SEP Driver:output table_data_size is %lu\n",
1223         table_data_size);
1224
1225         /* construct input lli table */
1226         sep_build_lli_table(&lli_array_ptr[current_entry],
1227                                                 in_lli_table_ptr,
1228                                                 &current_entry,
1229                                                 &num_entries_in_table,
1230                                                 table_data_size);
1231
1232         if (info_entry_ptr == 0) {
1233           /* set the output parameters to physical addresses */
1234           *lli_table_ptr = sep_shared_area_virt_to_phys(
1235                   (unsigned long)in_lli_table_ptr);
1236           *num_entries_ptr = num_entries_in_table;
1237           *table_data_size_ptr = table_data_size;
1238
1239         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1240         "SEP Driver:output lli_table_in_ptr is %08lx\n",
1241         *lli_table_ptr);
1242         } else {
1243           /* update the info entry of the previous in table */
1244         info_entry_ptr->physical_address = sep_shared_area_virt_to_phys(
1245                                 (unsigned long)in_lli_table_ptr);
1246         info_entry_ptr->block_size = ((num_entries_in_table) << 24) |
1247                                 (table_data_size);
1248         }
1249
1250         /* save the pointer to the info entry of the current tables */
1251         info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1252   }
1253
1254   /* print input tables */
1255   sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1256                         sep_shared_area_phys_to_virt(*lli_table_ptr),
1257                         *num_entries_ptr,
1258                         *table_data_size_ptr);
1259
1260   /* the array of the pages */
1261   kfree(lli_array_ptr);
1262
1263 end_function:
1264
1265   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1266                 "SEP Driver:<-------- sep_prepare_input_dma_table end\n");
1267
1268   return 0;
1269
1270 }
1271
1272 /*
1273   This function builds input and output DMA tables for synhronic
1274   symmetric operations (AES, DES). It also checks that each table
1275   is of the modular block size
1276 */
1277 int sep_prepare_input_output_dma_table(unsigned long    app_virt_in_addr,
1278                                         unsigned long   app_virt_out_addr,
1279                                         unsigned long   data_size,
1280                                         unsigned long   block_size,
1281                                         unsigned long   *lli_table_in_ptr,
1282                                         unsigned long   *lli_table_out_ptr,
1283                                         unsigned long   *in_num_entries_ptr,
1284                                         unsigned long   *out_num_entries_ptr,
1285                                         unsigned long   *table_data_size_ptr,
1286                                         bool            isKernelVirtualAddress)
1287
1288 {
1289   /* array of pointers of page */
1290   struct sep_lli_entry_t                *lli_in_array;
1291
1292   /* array of pointers of page */
1293   struct sep_lli_entry_t                *lli_out_array;
1294
1295   /* result */
1296   int                           result;
1297
1298
1299   /*------------------------
1300         CODE
1301   --------------------------*/
1302
1303   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1304         "SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
1305
1306   result = 0;
1307
1308   /* initialize the pages pointers */
1309   sep_dev->in_page_array = 0;
1310   sep_dev->out_page_array = 0;
1311
1312   /* check if the pages are in Kernel Virtual Address layout */
1313   if (isKernelVirtualAddress == true) {
1314         /* lock the pages of the kernel buffer and translate them to pages */
1315         result = sep_lock_kernel_pages(app_virt_in_addr,
1316                                 data_size,
1317                                 &sep_dev->in_num_pages,
1318                                 &lli_in_array,
1319                                 &sep_dev->in_page_array);
1320         if (result) {
1321         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1322         "SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
1323         goto end_function;
1324         }
1325   } else {
1326         /* lock the pages of the user buffer and translate them to pages */
1327         result = sep_lock_user_pages(app_virt_in_addr,
1328                                         data_size,
1329                                         &sep_dev->in_num_pages,
1330                                         &lli_in_array,
1331                                         &sep_dev->in_page_array);
1332         if (result) {
1333         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1334         "SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
1335         goto end_function;
1336         }
1337   }
1338
1339   if (isKernelVirtualAddress == true) {
1340         result = sep_lock_kernel_pages(app_virt_out_addr,
1341                                 data_size,
1342                                 &sep_dev->out_num_pages,
1343                                 &lli_out_array,
1344                                 &sep_dev->out_page_array);
1345         if (result) {
1346         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1347         "SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
1348         goto end_function_with_error1;
1349         }
1350   } else {
1351         result = sep_lock_user_pages(app_virt_out_addr,
1352                                         data_size,
1353                                         &sep_dev->out_num_pages,
1354                                         &lli_out_array,
1355                                         &sep_dev->out_page_array);
1356         if (result) {
1357         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1358         "SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
1359         goto end_function_with_error1;
1360         }
1361   }
1362
1363
1364   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1365         "sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
1366         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1367         "sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages);
1368         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1369         "SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n",
1370         SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
1371
1372
1373   /* call the fucntion that creates table from the lli arrays */
1374   result = sep_construct_dma_tables_from_lli(lli_in_array,
1375                                         sep_dev->in_num_pages,
1376                                         lli_out_array,
1377                                         sep_dev->out_num_pages,
1378                                          block_size,
1379                                         lli_table_in_ptr,
1380                                         lli_table_out_ptr,
1381                                         in_num_entries_ptr,
1382                                         out_num_entries_ptr,
1383                                         table_data_size_ptr);
1384   if (result) {
1385         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1386                 "SEP Driver: sep_construct_dma_tables_from_lli failed\n");
1387         goto end_function_with_error2;
1388   }
1389
1390   /* fall through - free the lli entry arrays */
1391
1392   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "in_num_entries_ptr is %08lx\n",
1393         *in_num_entries_ptr);
1394   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "out_num_entries_ptr is %08lx\n",
1395         *out_num_entries_ptr);
1396   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "table_data_size_ptr is %08lx\n",
1397         *table_data_size_ptr);
1398
1399
1400 end_function_with_error2:
1401
1402   kfree(lli_out_array);
1403
1404 end_function_with_error1:
1405
1406   kfree(lli_in_array);
1407
1408 end_function:
1409
1410   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1411 "SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n",
1412 (int)result);
1413
1414   return result;
1415
1416 }
1417
1418
1419 /*
1420  This function creates the input and output dma tables for
1421  symmetric operations (AES/DES) according to the block size from LLI arays
1422 */
1423 int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t    *lli_in_array,
1424                                         unsigned long   sep_in_lli_entries,
1425                                         struct sep_lli_entry_t  *lli_out_array,
1426                                         unsigned long   sep_out_lli_entries,
1427                                         unsigned long   block_size,
1428                                         unsigned long   *lli_table_in_ptr,
1429                                         unsigned long   *lli_table_out_ptr,
1430                                         unsigned long   *in_num_entries_ptr,
1431                                         unsigned long   *out_num_entries_ptr,
1432                                         unsigned long   *table_data_size_ptr)
1433 {
1434   /* points to the area where next lli table can be allocated */
1435   unsigned long lli_table_alloc_addr;
1436
1437   /* input lli table */
1438   struct sep_lli_entry_t                *in_lli_table_ptr;
1439
1440   /* output lli table */
1441   struct sep_lli_entry_t                *out_lli_table_ptr;
1442
1443   /* pointer to the info entry of the table - the last entry */
1444   struct sep_lli_entry_t                *info_in_entry_ptr;
1445
1446   /* pointer to the info entry of the table - the last entry */
1447   struct sep_lli_entry_t                *info_out_entry_ptr;
1448
1449   /* points to the first entry to be processed in the lli_in_array */
1450   unsigned long current_in_entry;
1451
1452   /* points to the first entry to be processed in the lli_out_array */
1453   unsigned long current_out_entry;
1454
1455   /* max size of the input table */
1456   unsigned long in_table_data_size;
1457
1458   /* max size of the output table */
1459   unsigned long out_table_data_size;
1460
1461   /* flag te signifies if this is the first tables build from the arrays */
1462   unsigned long   first_table_flag;
1463
1464   /* the data size that should be in table */
1465   unsigned long table_data_size;
1466
1467   /* number of etnries in the input table */
1468   unsigned long num_entries_in_table;
1469
1470   /* number of etnries in the output table */
1471   unsigned long num_entries_out_table;
1472
1473   /*---------------------
1474         CODE
1475   ------------------------*/
1476
1477   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1478         "SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
1479
1480   /* initiate to pint after the message area */
1481   lli_table_alloc_addr = sep_dev->shared_area_addr +
1482         SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1483
1484   current_in_entry = 0;
1485   current_out_entry = 0;
1486   first_table_flag = 1;
1487   info_in_entry_ptr = 0;
1488   info_out_entry_ptr = 0;
1489
1490   /* loop till all the entries in in array are not processed */
1491   while (current_in_entry < sep_in_lli_entries) {
1492         /* set the new input and output tables */
1493         in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1494
1495         lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1496                         SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1497
1498         /* set the first output tables */
1499         out_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1500
1501         lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1502                                 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1503
1504         /* calculate the maximum size of data for input table */
1505         in_table_data_size =
1506                         sep_calculate_lli_table_max_size(
1507                         &lli_in_array[current_in_entry],
1508                         (sep_in_lli_entries - current_in_entry));
1509
1510         /* calculate the maximum size of data for output table */
1511         out_table_data_size =
1512                         sep_calculate_lli_table_max_size(
1513                         &lli_out_array[current_out_entry],
1514                         (sep_out_lli_entries - current_out_entry));
1515
1516         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1517         "SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
1518         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1519         "SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
1520
1521         /* check where the data is smallest */
1522         table_data_size = in_table_data_size;
1523         if (table_data_size > out_table_data_size)
1524         table_data_size = out_table_data_size;
1525
1526         /* now calculate the table size so that it will be module block size */
1527         table_data_size = (table_data_size / block_size) * block_size;
1528
1529         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1530                 "SEP Driver:table_data_size is %lu\n",
1531                 table_data_size);
1532
1533         /* construct input lli table */
1534         sep_build_lli_table(&lli_in_array[current_in_entry],
1535                                                 in_lli_table_ptr,
1536                                                 &current_in_entry,
1537                                                 &num_entries_in_table,
1538                                                 table_data_size);
1539
1540         /* construct output lli table */
1541         sep_build_lli_table(&lli_out_array[current_out_entry],
1542                                                 out_lli_table_ptr,
1543                                                 &current_out_entry,
1544                                                 &num_entries_out_table,
1545                                                 table_data_size);
1546
1547         /* if info entry is null - this is the first table built */
1548         if (info_in_entry_ptr == 0) {
1549           /* set the output parameters to physical addresses */
1550           *lli_table_in_ptr =
1551                 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1552           *in_num_entries_ptr = num_entries_in_table;
1553           *lli_table_out_ptr =
1554                 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1555           *out_num_entries_ptr = num_entries_out_table;
1556           *table_data_size_ptr = table_data_size;
1557
1558         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1559         "SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
1560         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1561         "SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
1562         } else {
1563           /* update the info entry of the previous in table */
1564         info_in_entry_ptr->physical_address =
1565                 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1566         info_in_entry_ptr->block_size =
1567                 ((num_entries_in_table) << 24) | (table_data_size);
1568
1569           /* update the info entry of the previous in table */
1570         info_out_entry_ptr->physical_address =
1571                 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1572         info_out_entry_ptr->block_size =
1573                 ((num_entries_out_table) << 24) | (table_data_size);
1574         }
1575
1576         /* save the pointer to the info entry of the current tables */
1577         info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1578         info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
1579
1580         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1581                 "SEP Driver:output num_entries_out_table is %lu\n",
1582                 (unsigned long)num_entries_out_table);
1583         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1584                 "SEP Driver:output info_in_entry_ptr is %lu\n",
1585                 (unsigned long)info_in_entry_ptr);
1586         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1587                 "SEP Driver:output info_out_entry_ptr is %lu\n",
1588                 (unsigned long)info_out_entry_ptr);
1589   }
1590
1591   /* print input tables */
1592   sep_debug_print_lli_tables(
1593         (struct sep_lli_entry_t *)
1594         sep_shared_area_phys_to_virt(*lli_table_in_ptr),
1595         *in_num_entries_ptr,
1596         *table_data_size_ptr);
1597
1598   /* print output tables */
1599   sep_debug_print_lli_tables(
1600         (struct sep_lli_entry_t *)
1601         sep_shared_area_phys_to_virt(*lli_table_out_ptr),
1602         *out_num_entries_ptr,
1603         *table_data_size_ptr);
1604
1605   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1606         "SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
1607
1608   return 0;
1609 }
1610
1611 /*
1612   this function calculates the size of data that can be inserted into the lli
1613   table from this array the condition is that either the table is full
1614   (all etnries are entered), or there are no more entries in the lli array
1615 */
1616 unsigned long sep_calculate_lli_table_max_size(
1617                         struct sep_lli_entry_t  *lli_in_array_ptr,
1618                         unsigned long   num_array_entries)
1619 {
1620   /* table data size */
1621   unsigned long table_data_size;
1622
1623   /* counter */
1624   unsigned long counter;
1625
1626   /*---------------------
1627         CODE
1628   ----------------------*/
1629
1630   table_data_size = 0;
1631
1632   /* calculate the data in the out lli table if till we fill the whole
1633   table or till the data has ended */
1634   for (counter = 0;
1635         (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) &&
1636         (counter < num_array_entries); counter++)
1637         table_data_size += lli_in_array_ptr[counter].block_size;
1638
1639   return table_data_size;
1640 }
1641
1642 /*
1643   this functions builds ont lli table from the lli_array according to
1644   the given size of data
1645 */
1646 static void sep_build_lli_table(struct sep_lli_entry_t  *lli_array_ptr,
1647                                 struct sep_lli_entry_t  *lli_table_ptr,
1648                                 unsigned long   *num_processed_entries_ptr,
1649                                 unsigned long   *num_table_entries_ptr,
1650                                 unsigned long   table_data_size)
1651 {
1652   /* current table data size */
1653   unsigned long curr_table_data_size;
1654
1655   /* counter of lli array entry */
1656   unsigned long array_counter;
1657
1658   /*-----------------------
1659         CODE
1660   ---------------------------*/
1661
1662   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1663                 "SEP Driver:--------> sep_build_lli_table start\n");
1664
1665   /* init currrent table data size and lli array entry counter */
1666   curr_table_data_size = 0;
1667   array_counter = 0;
1668   *num_table_entries_ptr = 1;
1669
1670   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1671   "SEP Driver:table_data_size is %lu\n",
1672         table_data_size);
1673
1674   /* fill the table till table size reaches the needed amount */
1675   while (curr_table_data_size < table_data_size) {
1676         /* update the number of entries in table */
1677         (*num_table_entries_ptr)++;
1678
1679         lli_table_ptr->physical_address =
1680                 lli_array_ptr[array_counter].physical_address;
1681         lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
1682         curr_table_data_size += lli_table_ptr->block_size;
1683
1684         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1685         "SEP Driver:lli_table_ptr is %08lx\n",
1686         (unsigned long)lli_table_ptr);
1687         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1688         "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1689         lli_table_ptr->physical_address);
1690         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1691         "SEP Driver:lli_table_ptr->block_size is %lu\n",
1692         lli_table_ptr->block_size);
1693
1694         /* check for overflow of the table data */
1695         if (curr_table_data_size > table_data_size) {
1696         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1697                 "SEP Driver:curr_table_data_size > table_data_size\n");
1698
1699           /* update the size of block in the table */
1700         lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
1701
1702           /* update the physical address in the lli array */
1703         lli_array_ptr[array_counter].physical_address +=
1704                         lli_table_ptr->block_size;
1705
1706           /* update the block size left in the lli array */
1707         lli_array_ptr[array_counter].block_size =
1708                         (curr_table_data_size - table_data_size);
1709         } else
1710           /* advance to the next entry in the lli_array */
1711           array_counter++;
1712
1713         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1714         "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1715         lli_table_ptr->physical_address);
1716         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1717         "SEP Driver:lli_table_ptr->block_size is %lu\n",
1718         lli_table_ptr->block_size);
1719
1720         /* move to the next entry in table */
1721         lli_table_ptr++;
1722   }
1723
1724   /* set the info entry to default */
1725   lli_table_ptr->physical_address = 0xffffffff;
1726   lli_table_ptr->block_size = 0;
1727
1728   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1729         "SEP Driver:lli_table_ptr is %08lx\n",
1730         (unsigned long)lli_table_ptr);
1731   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1732         "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1733         lli_table_ptr->physical_address);
1734   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1735         "SEP Driver:lli_table_ptr->block_size is %lu\n",
1736         lli_table_ptr->block_size);
1737
1738
1739   /* set the output parameter */
1740   *num_processed_entries_ptr += array_counter;
1741
1742   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1743         "SEP Driver:*num_processed_entries_ptr is %lu\n",
1744         *num_processed_entries_ptr);
1745
1746
1747   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1748                 "SEP Driver:<-------- sep_build_lli_table end\n");
1749
1750   return;
1751 }
1752
1753 /*
1754   this function goes over the list of the print created tables and
1755   prints all the data
1756 */
1757 static void sep_debug_print_lli_tables(struct sep_lli_entry_t   *lli_table_ptr,
1758                                         unsigned long   num_table_entries,
1759                                         unsigned long   table_data_size)
1760 {
1761   unsigned long table_count;
1762
1763   unsigned long entries_count;
1764   /*-----------------------------
1765         CODE
1766   -------------------------------*/
1767
1768   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1769                 "SEP Driver:--------> sep_debug_print_lli_tables start\n");
1770
1771   table_count = 1;
1772   while ((unsigned long)lli_table_ptr != 0xffffffff) {
1773         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1774         "SEP Driver: lli table %08lx, table_data_size is %lu\n",
1775         table_count,
1776         table_data_size);
1777         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1778         "SEP Driver: num_table_entries is %lu\n", num_table_entries);
1779
1780         /* print entries of the table (without info entry) */
1781         for (entries_count = 0;
1782                 entries_count < num_table_entries;
1783                 entries_count++, lli_table_ptr++) {
1784                 DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1785                 "SEP Driver:lli_table_ptr address is %08lx\n",
1786                 (unsigned long)lli_table_ptr);
1787                 DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1788                 "SEP Driver:phys address is %08lx block size is %lu\n",
1789                 lli_table_ptr->physical_address, lli_table_ptr->block_size);
1790         }
1791
1792         /* point to the info entry */
1793         lli_table_ptr--;
1794
1795         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1796         "SEP Driver:phys lli_table_ptr->block_size is %lu\n",
1797         lli_table_ptr->block_size);
1798         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1799         "SEP Driver:phys lli_table_ptr->physical_address is %08lx\n",
1800         lli_table_ptr->physical_address);
1801
1802
1803         table_data_size = lli_table_ptr->block_size & 0xffffff;
1804         num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
1805         lli_table_ptr = (struct sep_lli_entry_t *)
1806                                 (lli_table_ptr->physical_address);
1807
1808         DEBUG_PRINT_3(SEP_DEBUG_LEVEL_EXTENDED,
1809         "SEP Driver:phys table_data_size is %lu num_table_entries is \
1810         %lu lli_table_ptr is%lu\n",
1811         table_data_size, num_table_entries, (unsigned long)lli_table_ptr);
1812
1813         if ((unsigned long)lli_table_ptr != 0xffffffff)
1814         lli_table_ptr = (struct sep_lli_entry_t *)sep_shared_area_phys_to_virt(
1815                                         (unsigned long)lli_table_ptr);
1816
1817         table_count++;
1818   }
1819
1820   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1821                 "SEP Driver:<-------- sep_debug_print_lli_tables end\n");
1822 }
1823
1824
1825 /*
1826   This function locks all the physical pages of the application virtual buffer
1827   and construct a basic lli  array, where each entry holds the physical page
1828   address and the size that application data holds in this physical pages
1829 */
1830 int sep_lock_user_pages(unsigned long           app_virt_addr,
1831                         unsigned long           data_size,
1832                         unsigned long           *num_pages_ptr,
1833                         struct sep_lli_entry_t          **lli_array_ptr,
1834                         struct page             ***page_array_ptr)
1835
1836 {
1837   /* error */
1838   int                           error;
1839
1840   /* the the page of the end address of the user space buffer */
1841   unsigned long         end_page;
1842
1843   /* the page of the start address of the user space buffer */
1844   unsigned long         start_page;
1845
1846   /* the range in pages */
1847   unsigned long         num_pages;
1848
1849   /* array of pointers ot page */
1850   struct page           **page_array;
1851
1852   /* array of lli */
1853   struct sep_lli_entry_t                *lli_array;
1854
1855   /* count */
1856   unsigned long         count;
1857
1858   /* result */
1859   int                           result;
1860
1861   /*------------------------
1862         CODE
1863   --------------------------*/
1864
1865   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1866                 "SEP Driver:--------> sep_lock_user_pages start\n");
1867
1868   error = 0;
1869
1870   /* set start and end pages  and num pages */
1871   end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
1872   start_page = app_virt_addr >> PAGE_SHIFT;
1873   num_pages = end_page - start_page + 1;
1874
1875   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1876         "SEP Driver: app_virt_addr is %08lx\n",
1877         app_virt_addr);
1878   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1879         "SEP Driver: data_size is %lu\n",
1880         data_size);
1881   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1882         "SEP Driver: start_page is %lu\n",
1883         start_page);
1884   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1885         "SEP Driver: end_page is %lu\n",
1886         end_page);
1887   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
1888         "SEP Driver: num_pages is %lu\n",
1889         num_pages);
1890
1891   /* allocate array of pages structure pointers */
1892   page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
1893   if (!page_array) {
1894         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1895                 "SEP Driver: kmalloc for page_array failed\n");
1896
1897         error = -ENOMEM;
1898         goto end_function;
1899   }
1900
1901   lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1902   if (!lli_array) {
1903         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
1904                 "SEP Driver: kmalloc for lli_array failed\n");
1905
1906         error = -ENOMEM;
1907         goto end_function_with_error1;
1908   }
1909
1910   /* convert the application virtual address into a set of physical */
1911   down_read(&current->mm->mmap_sem);
1912   result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0,
1913         page_array,
1914         0);
1915   up_read(&current->mm->mmap_sem);
1916
1917   /* check the number of pages locked - if not all then exit with error */
1918   if (result != num_pages) {
1919         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
1920                 "SEP Driver: not all pages locked by get_user_pages\n");
1921
1922         error = -ENOMEM;
1923         goto end_function_with_error2;
1924   }
1925
1926   /* flush the cache */
1927   for (count = 0; count < num_pages; count++)
1928         flush_dcache_page(page_array[count]);
1929
1930   /* set the start address of the first page - app data may start not at
1931         the beginning of the page */
1932   lli_array[0].physical_address = (
1933                         (unsigned long)page_to_phys(page_array[0])) +
1934                         (app_virt_addr & (~PAGE_MASK)) ;
1935
1936   /* check that not all the data is in the first page only */
1937   if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
1938         lli_array[0].block_size = data_size;
1939   else
1940         lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
1941
1942   /* debug print */
1943   DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
1944   "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
1945         lli_array[0].physical_address,
1946         lli_array[0].block_size);
1947
1948   /* go from the second page to the prev before last */
1949   for (count = 1; count < (num_pages - 1); count++) {
1950         lli_array[count].physical_address =
1951                 (unsigned long)page_to_phys(page_array[count]);
1952         lli_array[count].block_size = PAGE_SIZE;
1953
1954         DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
1955         "lli_array[%lu].physical_address is %08lx, \
1956         lli_array[%lu].block_size is %lu\n",
1957         count, lli_array[count].physical_address,
1958         count,
1959         lli_array[count].block_size);
1960   }
1961
1962   /* if more then 1 pages locked - then update for the last page size needed */
1963   if (num_pages > 1) {
1964         /* update the address of the last page */
1965         lli_array[count].physical_address =
1966                 (unsigned long)page_to_phys(page_array[count]);
1967
1968         /* set the size of the last page */
1969         lli_array[count].block_size = (app_virt_addr + data_size) &
1970                                         (~PAGE_MASK);
1971
1972         if (lli_array[count].block_size == 0) {
1973         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
1974         "app_virt_addr is %08lx\n",
1975         app_virt_addr);
1976         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
1977           while (1);
1978         }
1979         DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
1980         "lli_array[%lu].physical_address is %08lx, \
1981                 lli_array[%lu].block_size is %lu\n",
1982         count, lli_array[count].physical_address,
1983         count,
1984         lli_array[count].block_size);
1985   }
1986
1987   /* set output params */
1988   *lli_array_ptr = lli_array;
1989   *num_pages_ptr = num_pages;
1990   *page_array_ptr = page_array;
1991
1992   goto end_function;
1993
1994 end_function_with_error2:
1995
1996   /* release the cache */
1997   for (count = 0; count < num_pages; count++)
1998         page_cache_release(page_array[count]);
1999
2000   /* free lli array */
2001   kfree(lli_array);
2002
2003 end_function_with_error1:
2004
2005   /* free page array */
2006   kfree(page_array);
2007
2008 end_function:
2009
2010   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2011                 "SEP Driver:<-------- sep_lock_user_pages end\n");
2012
2013   return 0;
2014 }
2015
2016 /*
2017   This function locks all the physical pages of the kernel virtual buffer
2018   and construct a basic lli  array, where each entry holds the physical
2019   page address and the size that application data holds in this physical pages
2020 */
2021 int sep_lock_kernel_pages(unsigned long         kernel_virt_addr,
2022                         unsigned long           data_size,
2023                         unsigned long           *num_pages_ptr,
2024                         struct sep_lli_entry_t          **lli_array_ptr,
2025                         struct page             ***page_array_ptr)
2026
2027 {
2028   /* error */
2029   int                           error;
2030
2031   /* the the page of the end address of the user space buffer */
2032   unsigned long         end_page;
2033
2034   /* the page of the start address of the user space buffer */
2035   unsigned long         start_page;
2036
2037   /* the range in pages */
2038   unsigned long         num_pages;
2039
2040   /* array of lli */
2041   struct sep_lli_entry_t                *lli_array;
2042
2043   /* next kernel address to map */
2044   unsigned long         next_kernel_address;
2045
2046   /* count */
2047   unsigned long         count;
2048
2049
2050   /*------------------------
2051         CODE
2052   --------------------------*/
2053
2054   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2055                 "SEP Driver:--------> sep_lock_kernel_pages start\n");
2056
2057   error = 0;
2058
2059   /* set start and end pages  and num pages */
2060   end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
2061   start_page = kernel_virt_addr >> PAGE_SHIFT;
2062   num_pages = end_page - start_page + 1;
2063
2064   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2065         "SEP Driver: kernel_virt_addr is %08lx\n",
2066         kernel_virt_addr);
2067   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2068         "SEP Driver: data_size is %lu\n",
2069         data_size);
2070   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2071         "SEP Driver: start_page is %lx\n",
2072         start_page);
2073   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2074         "SEP Driver: end_page is %lx\n",
2075         end_page);
2076   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2077         "SEP Driver: num_pages is %lu\n",
2078         num_pages);
2079
2080   lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
2081   if (!lli_array) {
2082         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
2083                 "SEP Driver: kmalloc for lli_array failed\n");
2084
2085         error = -ENOMEM;
2086         goto end_function;
2087   }
2088
2089   /* set the start address of the first page - app data may start not at
2090   the beginning of the page */
2091   lli_array[0].physical_address =
2092         (unsigned long)virt_to_phys((unsigned long *)kernel_virt_addr);
2093
2094   /* check that not all the data is in the first page only */
2095   if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
2096         lli_array[0].block_size = data_size;
2097   else
2098         lli_array[0].block_size =
2099                 PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
2100
2101   /* debug print */
2102   DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2103   "lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
2104         lli_array[0].physical_address,
2105         lli_array[0].block_size);
2106
2107   /* advance the address to the start of the next page */
2108   next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
2109
2110   /* go from the second page to the prev before last */
2111   for (count = 1; count < (num_pages - 1); count++) {
2112         lli_array[count].physical_address =
2113         (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2114         lli_array[count].block_size = PAGE_SIZE;
2115
2116         DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2117         "lli_array[%lu].physical_address is %08lx, \
2118         lli_array[%lu].block_size is %lu\n",
2119         count, lli_array[count].physical_address, count,
2120         lli_array[count].block_size);
2121
2122         next_kernel_address += PAGE_SIZE;
2123   }
2124
2125   /* if more then 1 pages locked - then update for the last page size needed */
2126   if (num_pages > 1) {
2127         /* update the address of the last page */
2128         lli_array[count].physical_address =
2129         (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2130
2131         /* set the size of the last page */
2132         lli_array[count].block_size =
2133                 (kernel_virt_addr + data_size) & (~PAGE_MASK);
2134
2135         if (lli_array[count].block_size == 0) {
2136         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC,
2137         "app_virt_addr is %08lx\n",
2138         kernel_virt_addr);
2139         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_BASIC, "data_size is %lu\n", data_size);
2140           while (1);
2141         }
2142
2143         DEBUG_PRINT_4(SEP_DEBUG_LEVEL_EXTENDED,
2144         "lli_array[%lu].physical_address is %08lx, \
2145         lli_array[%lu].block_size is %lu\n",
2146         count, lli_array[count].physical_address,
2147         count,
2148         lli_array[count].block_size);
2149   }
2150
2151   /* set output params */
2152   *lli_array_ptr = lli_array;
2153   *num_pages_ptr = num_pages;
2154   *page_array_ptr = 0;
2155
2156
2157 end_function:
2158
2159   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2160                 "SEP Driver:<-------- sep_lock_kernel_pages end\n");
2161
2162   return 0;
2163 }
2164
2165 /*
2166   This function releases all the application virtual buffer physical pages,
2167         that were previously locked
2168 */
2169 int sep_free_dma_pages(struct page      **page_array_ptr,
2170                                         unsigned long num_pages,
2171                                         unsigned long dirtyFlag)
2172 {
2173   /* count */
2174   unsigned long count;
2175
2176   /*-------------------
2177         CODE
2178   ---------------------*/
2179
2180   if (dirtyFlag) {
2181         for (count = 0; count < num_pages; count++) {
2182           /* the out array was written, therefore the data was changed */
2183         if (!PageReserved(page_array_ptr[count]))
2184                 SetPageDirty(page_array_ptr[count]);
2185           page_cache_release(page_array_ptr[count]);
2186         }
2187   } else {
2188         /* free in pages - the data was only read, therefore no update was done
2189                 on those pages */
2190         for (count = 0; count < num_pages; count++)
2191           page_cache_release(page_array_ptr[count]);
2192   }
2193
2194   if (page_array_ptr)
2195         /* free the array */
2196         kfree(page_array_ptr);
2197
2198   return 0;
2199 }
2200
2201 /*
2202   This function raises interrupt to SEP that signals that is has a new
2203         command from HOST
2204 */
2205 static void sep_send_command_handler()
2206 {
2207
2208   unsigned long count;
2209
2210   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2211                 "SEP Driver:--------> sep_send_command_handler start\n");
2212
2213   sep_set_time(0, 0);
2214
2215   /* flash cache */
2216   flush_cache_all();
2217
2218   for (count = 0; count < 12 * 4; count += 4)
2219         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2220         "Word %lu of the message is %lu\n",
2221         count,
2222         *((unsigned long *)(sep_dev->shared_area_addr + count)));
2223
2224   /* update counter */
2225   sep_dev->host_to_sep_send_counter++;
2226
2227   /* send interrupt to SEP */
2228   sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2229
2230   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2231                 "SEP Driver:<-------- sep_send_command_handler end\n");
2232
2233   return;
2234 }
2235
2236 /*
2237   This function raises interrupt to SEPm that signals that is has a
2238   new command from HOST
2239 */
2240 static void sep_send_reply_command_handler()
2241 {
2242   unsigned long count;
2243
2244   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2245                 "SEP Driver:--------> sep_send_reply_command_handler start\n");
2246
2247   /* flash cache */
2248   flush_cache_all();
2249
2250   for (count = 0; count < 12 * 4; count += 4)
2251         DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2252         "Word %lu of the message is %lu\n",
2253         count,
2254         *((unsigned long *)(sep_dev->shared_area_addr + count)));
2255
2256
2257   /* update counter */
2258   sep_dev->host_to_sep_send_counter++;
2259
2260   /* send the interrupt to SEP */
2261   sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR,
2262                                 sep_dev->host_to_sep_send_counter);
2263
2264   /* update both counters */
2265   sep_dev->host_to_sep_send_counter++;
2266
2267   sep_dev->sep_to_host_reply_counter++;
2268
2269   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2270                 "SEP Driver:<-------- sep_send_reply_command_handler end\n");
2271
2272   return;
2273 }
2274
2275
2276
2277 /*
2278   This function handles the allocate data pool memory request
2279   This function returns calculates the physical address of the
2280   allocated memory, and the offset of this area from the mapped address.
2281   Therefore, the FVOs in user space can calculate the exact virtual
2282   address of this allocated memory
2283 */
2284 static int sep_allocate_data_pool_memory_handler(unsigned long arg)
2285 {
2286   /* error */
2287   int                           error;
2288
2289   /* command paramaters */
2290   struct sep_driver_alloc_t  command_args;
2291
2292   /*-------------------------
2293         CODE
2294   ----------------------------*/
2295
2296   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2297         "SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
2298
2299
2300   error = copy_from_user(&command_args,
2301         (void *)arg,
2302         sizeof(struct sep_driver_alloc_t));
2303   if (error)
2304         goto end_function;
2305
2306   /* allocate memory */
2307   if (
2308         (sep_dev->data_pool_bytes_allocated + command_args.num_bytes) >
2309         SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
2310         error = -ENOTTY;
2311         goto end_function;
2312   }
2313
2314   /* set the virtual and physical address */
2315   command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2316                         sep_dev->data_pool_bytes_allocated;
2317   command_args.phys_address = sep_dev->phys_shared_area_addr +
2318                         SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2319                         sep_dev->data_pool_bytes_allocated;
2320
2321   /* write the memory back to the user space */
2322   error = copy_to_user((void *)arg,
2323         (void *)&command_args,
2324         sizeof(struct sep_driver_alloc_t));
2325   if (error)
2326         goto end_function;
2327
2328   /* set the allocation */
2329   sep_dev->data_pool_bytes_allocated += command_args.num_bytes;
2330
2331 end_function:
2332
2333   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2334         "SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
2335
2336   return error;
2337 }
2338
2339 /*
2340   This function  handles write into allocated data pool command
2341 */
2342 static int sep_write_into_data_pool_handler(unsigned long arg)
2343 {
2344   /* error */
2345   int                   error;
2346
2347   /* virtual address */
2348   unsigned long virt_address;
2349
2350   /* application in address */
2351   unsigned long app_in_address;
2352
2353   /* number of bytes */
2354   unsigned long num_bytes;
2355
2356   /* address of the data pool */
2357   unsigned long data_pool_area_addr;
2358
2359   /*--------------------------
2360         CODE
2361   -----------------------------*/
2362
2363   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2364         "SEP Driver:--------> sep_write_into_data_pool_handler start\n");
2365
2366   /* get the application address */
2367   error = get_user(app_in_address,
2368                 &(((struct sep_driver_write_t *)arg)->app_address));
2369   if (error)
2370         goto end_function;
2371
2372   /* get the virtual kernel address address */
2373   error = get_user(virt_address,
2374                 &(((struct sep_driver_write_t *)arg)->datapool_address));
2375   if (error)
2376         goto end_function;
2377
2378   /* get the number of bytes */
2379   error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2380   if (error)
2381         goto end_function;
2382
2383   /* calculate the start of the data pool */
2384   data_pool_area_addr = sep_dev->shared_area_addr +
2385                         SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2386
2387
2388   /* check that the range of the virtual kernel address is correct */
2389   if ((virt_address < data_pool_area_addr) ||
2390           (virt_address > (data_pool_area_addr +
2391           SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2392         error = -ENOTTY;
2393         goto end_function;
2394   }
2395
2396   /* copy the application data */
2397   error = copy_from_user((void *)virt_address,
2398         (void *)app_in_address,
2399         num_bytes);
2400
2401 end_function:
2402
2403   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2404                 "SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
2405
2406   return error;
2407 }
2408
2409 /*
2410   this function handles the read from data pool command
2411 */
2412 static int sep_read_from_data_pool_handler(unsigned long arg)
2413 {
2414   /* error */
2415   int                   error;
2416
2417   /* virtual address of dest application buffer */
2418   unsigned long app_out_address;
2419
2420   /* virtual address of the data pool */
2421   unsigned long virt_address;
2422
2423   /* number bytes */
2424   unsigned long num_bytes;
2425
2426   /* address of the data pool */
2427   unsigned long data_pool_area_addr;
2428
2429   /*------------------------
2430         CODE
2431   -----------------------------*/
2432
2433   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2434         "SEP Driver:--------> sep_read_from_data_pool_handler start\n");
2435
2436   /* get the application address */
2437   error = get_user(app_out_address,
2438                 &(((struct sep_driver_write_t *)arg)->app_address));
2439   if (error)
2440         goto end_function;
2441
2442   /* get the virtual kernel address address */
2443   error = get_user(virt_address,
2444         &(((struct sep_driver_write_t *)arg)->datapool_address));
2445   if (error)
2446         goto end_function;
2447
2448   /* get the number of bytes */
2449   error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2450   if (error)
2451         goto end_function;
2452
2453   /* calculate the start of the data pool */
2454   data_pool_area_addr = sep_dev->shared_area_addr +
2455                         SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2456
2457   /* check that the range of the virtual kernel address is correct */
2458   if ((virt_address < data_pool_area_addr) ||
2459           (virt_address > (data_pool_area_addr +
2460           SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2461         error = -ENOTTY;
2462         goto end_function;
2463   }
2464
2465   /* copy the application data */
2466   error = copy_to_user((void *)app_out_address, (void *)virt_address,
2467   num_bytes);
2468
2469 end_function:
2470
2471   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2472                 "SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
2473
2474   return error;
2475 }
2476
2477
2478 /*
2479   this function handles tha request for creation of the DMA table
2480   for the synchronic symmetric operations (AES,DES)
2481 */
2482 static int sep_create_sync_dma_tables_handler(unsigned long arg)
2483 {
2484   /* error */
2485   int                                                   error;
2486
2487   /* command arguments */
2488   struct sep_driver_build_sync_table_t command_args;
2489
2490   /*------------------------
2491         CODE
2492   --------------------------*/
2493
2494   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2495         "SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
2496
2497   error = copy_from_user(&command_args,
2498         (void *)arg,
2499         sizeof(struct sep_driver_build_sync_table_t));
2500   if (error)
2501         goto end_function;
2502
2503   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2504         "app_in_address is %08lx\n",
2505         command_args.app_in_address);
2506   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2507         "app_out_address is %08lx\n",
2508         command_args.app_out_address);
2509   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2510         "data_size is %lu\n",
2511         command_args.data_in_size);
2512   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
2513         "block_size is %lu\n",
2514         command_args.block_size);
2515
2516
2517   /* check if we need to build only input table or input/output */
2518   if (command_args.app_out_address)
2519         /* prepare input and output tables */
2520         error = sep_prepare_input_output_dma_table(command_args.app_in_address,
2521                                         command_args.app_out_address,
2522                                         command_args.data_in_size,
2523                                         command_args.block_size,
2524                                         &command_args.in_table_address,
2525                                         &command_args.out_table_address,
2526                                         &command_args.in_table_num_entries,
2527                                         &command_args.out_table_num_entries,
2528                                         &command_args.table_data_size,
2529                                         command_args.isKernelVirtualAddress);
2530   else
2531         /* prepare input tables */
2532         error = sep_prepare_input_dma_table(command_args.app_in_address,
2533                                         command_args.data_in_size,
2534                                         command_args.block_size,
2535                                         &command_args.in_table_address,
2536                                         &command_args.in_table_num_entries,
2537                                         &command_args.table_data_size,
2538                                         command_args.isKernelVirtualAddress);
2539
2540   if (error)
2541         goto end_function;
2542
2543   /* copy to user */
2544   error = copy_to_user((void *)arg,
2545         (void *)&command_args,
2546         sizeof(struct sep_driver_build_sync_table_t));
2547
2548 end_function:
2549
2550   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2551         "SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
2552
2553   return error;
2554 }
2555
2556 /*
2557   this function handles the request for freeing dma table for synhronic actions
2558 */
2559 int sep_free_dma_table_data_handler()
2560 {
2561   /*-------------------------
2562         CODE
2563   -----------------------------*/
2564
2565   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2566         "SEP Driver:--------> sep_free_dma_table_data_handler start\n");
2567
2568   /* free input pages array */
2569   sep_free_dma_pages(sep_dev->in_page_array,
2570                                         sep_dev->in_num_pages,
2571                                          0);
2572
2573   /* free output pages array if needed */
2574   if (sep_dev->out_page_array)
2575         sep_free_dma_pages(sep_dev->out_page_array,
2576                                                 sep_dev->out_num_pages,
2577                                                 1);
2578
2579   /* reset all the values */
2580   sep_dev->in_page_array = 0;
2581   sep_dev->out_page_array = 0;
2582   sep_dev->in_num_pages = 0;
2583   sep_dev->out_num_pages = 0;
2584
2585
2586   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2587                 "SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
2588
2589   return 0;
2590 }
2591
2592 /*
2593   this function handles the request to create the DMA tables for flow
2594 */
2595 static int sep_create_flow_dma_tables_handler(unsigned long arg)
2596 {
2597   /* error */
2598   int                                                   error;
2599
2600   /* command arguments */
2601   struct sep_driver_build_flow_table_t  command_args;
2602
2603   /* first table - output */
2604   struct sep_lli_entry_t                                 first_table_data;
2605
2606   /* dma table data */
2607   struct sep_lli_entry_t                                last_table_data;
2608
2609   /* pointer to the info entry of the previuos DMA table */
2610   struct sep_lli_entry_t                *prev_info_entry_ptr;
2611
2612   /* pointer to the flow data strucutre */
2613   struct sep_flow_context_t             *flow_context_ptr;
2614
2615   /*------------------------
2616         CODE
2617   --------------------------*/
2618
2619   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2620         "SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
2621
2622   /* init variables */
2623   prev_info_entry_ptr = 0;
2624   first_table_data.physical_address = 0xffffffff;
2625
2626   /* find the free structure for flow data */
2627   error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
2628   if (error)
2629         goto end_function;
2630
2631   error = copy_from_user(&command_args,
2632         (void *)arg,
2633         sizeof(struct sep_driver_build_flow_table_t));
2634   if (error)
2635         goto end_function;
2636
2637   /* create flow tables */
2638   error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2639                                         command_args.virt_buff_data_addr,
2640                                         flow_context_ptr,
2641                                         &first_table_data,
2642                                         &last_table_data,
2643                                         command_args.isKernelVirtualAddress);
2644   if (error)
2645         goto end_function_with_error;
2646
2647   /* check if flow is static */
2648   if (!command_args.flow_type)
2649         /* point the info entry of the last to the info entry of the first */
2650         last_table_data = first_table_data;
2651
2652   /* set output params */
2653   command_args.first_table_addr = first_table_data.physical_address;
2654   command_args.first_table_num_entries =
2655         ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) &
2656         SEP_NUM_ENTRIES_MASK);
2657   command_args.first_table_data_size =
2658         (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2659
2660   /* send the parameters to user application */
2661   error = copy_to_user((void *)arg,
2662         &command_args,
2663         sizeof(struct sep_driver_build_flow_table_t));
2664   if (error)
2665         goto end_function_with_error;
2666
2667   /* all the flow created  - update the flow entry with temp id */
2668   flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
2669
2670   /* set the processing tables data in the context */
2671   if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
2672         flow_context_ptr->input_tables_in_process = first_table_data;
2673   else
2674         flow_context_ptr->output_tables_in_process = first_table_data;
2675
2676   goto end_function;
2677
2678 end_function_with_error:
2679
2680   /* free the allocated tables */
2681   sep_deallocated_flow_tables(&first_table_data);
2682
2683 end_function:
2684
2685   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2686         "SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
2687
2688   return error;
2689
2690 }
2691
2692 /*
2693   this functio n handles add tables to flow
2694 */
2695 static int sep_add_flow_tables_handler(unsigned long arg)
2696 {
2697   /* error */
2698   int                                                   error;
2699
2700   /* number of entries */
2701   unsigned long                         num_entries;
2702
2703   /* command arguments */
2704   struct sep_driver_add_flow_table_t    command_args;
2705
2706   /* pointer to the flow data strucutre */
2707   struct sep_flow_context_t             *flow_context_ptr;
2708
2709   /* first dma table data */
2710   struct sep_lli_entry_t                first_table_data;
2711
2712   /* last dma table data */
2713   struct sep_lli_entry_t                last_table_data;
2714
2715   /* pointer to the info entry of the current DMA table */
2716   struct sep_lli_entry_t                *info_entry_ptr;
2717
2718   /*--------------------------
2719         CODE
2720   ----------------------------*/
2721
2722   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2723                 "SEP Driver:--------> sep_add_flow_tables_handler start\n");
2724
2725   /* get input parameters */
2726   error = copy_from_user(&command_args,
2727         (void *)arg,
2728         sizeof(struct sep_driver_add_flow_table_t));
2729   if (error)
2730         goto end_function;
2731
2732   /* find the flow structure for the flow id */
2733   error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2734   if (error)
2735         goto end_function;
2736
2737   /* prepare the flow dma tables */
2738   error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2739                                         command_args.virt_buff_data_addr,
2740                                         flow_context_ptr,
2741                                         &first_table_data,
2742                                         &last_table_data,
2743                                         command_args.isKernelVirtualAddress);
2744   if (error)
2745         goto end_function_with_error;
2746
2747   /* now check if there is already an existing add table for this flow */
2748   if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
2749         /* this buffer was for input buffers */
2750         if (flow_context_ptr->input_tables_flag) {
2751           /* add table already exists - add the new tables to the end
2752                 of the previous */
2753         num_entries = (flow_context_ptr->last_input_table.block_size >>
2754                         SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2755
2756         info_entry_ptr =
2757         (struct sep_lli_entry_t *)
2758         (flow_context_ptr->last_input_table.physical_address +
2759         (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2760
2761           /* connect to list of tables */
2762           *info_entry_ptr = first_table_data;
2763
2764           /* set the first table data */
2765           first_table_data = flow_context_ptr->first_input_table;
2766         } else {
2767           /* set the input flag */
2768           flow_context_ptr->input_tables_flag = 1;
2769
2770           /* set the first table data */
2771           flow_context_ptr->first_input_table = first_table_data;
2772         }
2773         /* set the last table data */
2774         flow_context_ptr->last_input_table = last_table_data;
2775   } else  /* this is output tables */ {
2776         /* this buffer was for input buffers */
2777         if (flow_context_ptr->output_tables_flag) {
2778           /* add table already exists - add the new tables to
2779                 the end of the previous */
2780         num_entries = (flow_context_ptr->last_output_table.block_size >>
2781                 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2782
2783         info_entry_ptr =
2784         (struct sep_lli_entry_t *)
2785         (flow_context_ptr->last_output_table.physical_address +
2786         (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2787
2788           /* connect to list of tables */
2789           *info_entry_ptr = first_table_data;
2790
2791           /* set the first table data */
2792           first_table_data = flow_context_ptr->first_output_table;
2793         } else {
2794           /* set the input flag */
2795           flow_context_ptr->output_tables_flag = 1;
2796
2797           /* set the first table data */
2798           flow_context_ptr->first_output_table = first_table_data;
2799         }
2800         /* set the last table data */
2801         flow_context_ptr->last_output_table = last_table_data;
2802   }
2803
2804   /* set output params */
2805   command_args.first_table_addr = first_table_data.physical_address;
2806   command_args.first_table_num_entries = ((first_table_data.block_size >>
2807   SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
2808   command_args.first_table_data_size =
2809   (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2810
2811   /* send the parameters to user application */
2812   error = copy_to_user((void *)arg,
2813         &command_args,
2814         sizeof(struct sep_driver_add_flow_table_t));
2815   if (error)
2816         goto end_function_with_error;
2817
2818 end_function_with_error:
2819
2820   /* free the allocated tables */
2821   sep_deallocated_flow_tables(&first_table_data);
2822
2823 end_function:
2824
2825   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2826                 "SEP Driver:<-------- sep_add_flow_tables_handler end\n");
2827
2828   return error;
2829 }
2830
2831 /*
2832   this function add the flow add message to the specific flow
2833 */
2834 static int sep_add_flow_tables_message_handler(unsigned long arg)
2835 {
2836   /* error */
2837   int                                           error;
2838
2839   /* arguments */
2840   struct sep_driver_add_message_t  command_args;
2841
2842   /* flow context */
2843   struct sep_flow_context_t             *flow_context_ptr;
2844
2845   /*----------------------------
2846         CODE
2847   ------------------------------*/
2848
2849   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2850         "SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
2851
2852   error = copy_from_user(&command_args,
2853         (void *)arg,
2854         sizeof(struct sep_driver_add_message_t));
2855   if (error)
2856         goto end_function;
2857
2858   /* check input */
2859   if (command_args.message_size_in_bytes >
2860         SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
2861         error = -ENOMEM;
2862         goto end_function;
2863   }
2864
2865   /* find the flow context */
2866   error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2867   if (error)
2868         goto end_function;
2869
2870   /* copy the message into context */
2871   flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
2872
2873   error = copy_from_user(flow_context_ptr->message,
2874         (void *)command_args.message_address,
2875         command_args.message_size_in_bytes);
2876
2877
2878 end_function:
2879
2880   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2881         "SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
2882
2883   return error;
2884 }
2885
2886
2887 /*
2888   this function returns the physical and virtual addresses of the static pool
2889 */
2890 static int sep_get_static_pool_addr_handler(unsigned long arg)
2891 {
2892   /* error */
2893   int                                                   error;
2894
2895   /* command arguments */
2896   struct sep_driver_static_pool_addr_t  command_args;
2897
2898   /*-----------------------------
2899         CODE
2900   ------------------------------*/
2901
2902   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2903         "SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
2904
2905   /*prepare the output parameters in the struct */
2906   command_args.physical_static_address = sep_dev->phys_shared_area_addr +
2907                                 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2908   command_args.virtual_static_address = sep_dev->shared_area_addr +
2909                                 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2910
2911   DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2912  "SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n",
2913         command_args.physical_static_address,
2914         command_args.virtual_static_address);
2915
2916   /* send the parameters to user application */
2917   error = copy_to_user((void *)arg,
2918         &command_args,
2919         sizeof(struct sep_driver_static_pool_addr_t));
2920   if (error)
2921         goto end_function;
2922
2923 end_function:
2924
2925   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2926                 "SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
2927
2928   return error;
2929 }
2930
2931 /*
2932   this address gets the offset of the physical address from the start
2933   of the mapped area
2934 */
2935 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
2936 {
2937   /* error */
2938   int                                                   error;
2939
2940   /* command arguments */
2941   struct sep_driver_get_mapped_offset_t command_args;
2942
2943   /*-----------------------------
2944         CODE
2945   ------------------------------*/
2946
2947   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2948         "SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
2949
2950   error = copy_from_user(&command_args,
2951         (void *)arg,
2952         sizeof(struct sep_driver_get_mapped_offset_t));
2953   if (error)
2954         goto end_function;
2955
2956   if (command_args.physical_address < sep_dev->phys_shared_area_addr) {
2957         error = -ENOTTY;
2958         goto end_function;
2959   }
2960
2961   /*prepare the output parameters in the struct */
2962   command_args.offset = command_args.physical_address -
2963                                         sep_dev->phys_shared_area_addr;
2964
2965   DEBUG_PRINT_2(SEP_DEBUG_LEVEL_EXTENDED,
2966   "SEP Driver:physical_address is %08lx, offset is %lu\n",
2967         command_args.physical_address,
2968         command_args.offset);
2969
2970   /* send the parameters to user application */
2971   error = copy_to_user((void *)arg,
2972         &command_args,
2973         sizeof(struct sep_driver_get_mapped_offset_t));
2974   if (error)
2975         goto end_function;
2976
2977 end_function:
2978
2979   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
2980         "SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
2981
2982   return error;
2983 }
2984
2985
2986 /*
2987   ?
2988 */
2989 static int sep_start_handler(void)
2990 {
2991   /* reg val */
2992   unsigned long reg_val;
2993
2994   /* error */
2995   unsigned long error;
2996
2997   /*-----------------------------
2998         CODE
2999   ------------------------------*/
3000
3001   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3002                 "SEP Driver:--------> sep_start_handler start\n");
3003
3004   error = 0;
3005
3006   /* wait in polling for message from SEP */
3007   do {
3008         reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
3009   } while (!reg_val);
3010
3011   /* check the value */
3012   if (reg_val == 0x1) {
3013         /* fatal error - read erro status from GPRO */
3014         error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
3015         goto end_function;
3016   }
3017
3018 end_function:
3019
3020   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3021                 "SEP Driver:<-------- sep_start_handler end\n");
3022
3023   return error;
3024 }
3025
3026 /*
3027   this function handles the request for SEP initialization
3028 */
3029 static int sep_init_handler(unsigned long arg)
3030 {
3031   /* word from message */
3032   unsigned long  message_word;
3033
3034   /* message ptr */
3035   unsigned long         *message_ptr;
3036
3037   /* command arguments */
3038   struct sep_driver_init_t command_args;
3039
3040   /* counter */
3041   unsigned long counter;
3042
3043   /* error */
3044   unsigned long error;
3045
3046   /* reg val */
3047   unsigned long reg_val;
3048
3049   /*-------------------
3050         CODE
3051   ---------------------*/
3052
3053   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3054                 "SEP Driver:--------> sep_init_handler start\n");
3055
3056   error = 0;
3057
3058   error = copy_from_user(&command_args, (void *)arg,
3059                         sizeof(struct sep_driver_init_t));
3060
3061   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3062                 "SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
3063
3064   if (error)
3065         goto end_function;
3066
3067   /* PATCH - configure the DMA to single -burst instead of multi-burst */
3068   /*sep_configure_dma_burst();*/
3069
3070   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3071                 "SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
3072
3073   message_ptr = (unsigned long *)command_args.message_addr;
3074
3075   /* set the base address of the SRAM  */
3076   sep_write_reg(sep_dev, HW_SRAM_ADDR_REG_ADDR, HW_CC_SRAM_BASE_ADDRESS);
3077
3078   for (counter = 0 ;
3079                 counter < command_args.message_size_in_words;
3080                 counter++, message_ptr++) {
3081         get_user(message_word, message_ptr);
3082
3083         /* write data to SRAM */
3084         sep_write_reg(sep_dev, HW_SRAM_DATA_REG_ADDR,
3085                                                 message_word);
3086
3087         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3088                                         "SEP Driver:message_word is %lu\n",
3089                                         message_word);
3090
3091                 /* wait for write complete */
3092         sep_wait_sram_write(sep_dev);
3093   }
3094
3095   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3096                 "SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
3097
3098   /* signal SEP */
3099   sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR,
3100                                         0x1);
3101
3102   do {
3103         reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
3104   } while (!(reg_val & 0xFFFFFFFD));
3105
3106   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3107                 "SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
3108
3109   /* check the value */
3110   if (reg_val == 0x1) {
3111         DEBUG_PRINT_0(SEP_DEBUG_LEVEL_EXTENDED,
3112                 "SEP Driver:init failed\n");
3113
3114         error = sep_read_reg(sep_dev, 0x8060);
3115         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3116                         "SEP Driver:sw monitor is %lu\n",
3117                         error);
3118
3119         /* fatal error - read erro status from GPRO */
3120         error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
3121         DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3122                         "SEP Driver:error is %lu\n", error);
3123         goto end_function;
3124   }
3125
3126 end_function:
3127
3128   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3129                 "SEP Driver:<-------- sep_init_handler end\n");
3130
3131   return error;
3132
3133 }
3134
3135 /*
3136   this function handles the request cache and resident reallocation
3137 */
3138 static int sep_realloc_cache_resident_handler(unsigned long arg)
3139 {
3140   /* error */
3141   int                   error;
3142
3143   /* physical cache addr */
3144   unsigned long         phys_cache_address;
3145
3146   /* physical resident addr */
3147   unsigned long         phys_resident_address;
3148
3149   /* command arguments */
3150   struct sep_driver_realloc_cache_resident_t command_args;
3151
3152   /*------------------
3153         CODE
3154   ---------------------*/
3155
3156   /* copy the data */
3157   error = copy_from_user(&command_args,
3158         (void *)arg,
3159         sizeof(struct sep_driver_realloc_cache_resident_t));
3160   if (error)
3161         goto end_function;
3162
3163   /* copy cache and resident to the their intended locations */
3164   error = sep_copy_cache_resident_to_area(command_args.cache_addr,
3165                                         command_args.cache_size_in_bytes,
3166                                         command_args.resident_addr,
3167                                         command_args.resident_size_in_bytes,
3168                                         &phys_cache_address,
3169                                         &phys_resident_address);
3170   if (error)
3171         goto end_function;
3172
3173   /* lock the area (if needed) */
3174   sep_lock_cache_resident_area();
3175
3176   command_args.new_base_addr = sep_dev->phys_shared_area_addr;
3177
3178   /* find the new base address according to the lowest address between
3179         cache, resident and shared area */
3180   if (phys_resident_address < command_args.new_base_addr)
3181         command_args.new_base_addr = phys_resident_address;
3182   if (phys_cache_address < command_args.new_base_addr)
3183         command_args.new_base_addr = phys_cache_address;
3184
3185   /* set the return parameters */
3186   command_args.new_cache_addr = phys_cache_address;
3187   command_args.new_resident_addr = phys_resident_address;
3188
3189
3190   /* set the new shared area */
3191   command_args.new_shared_area_addr = sep_dev->phys_shared_area_addr;
3192
3193   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3194         "SEP Driver:command_args.new_shared_area_addr is %08lx\n",
3195         command_args.new_shared_area_addr);
3196   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3197         "SEP Driver:command_args.new_base_addr is %08lx\n",
3198         command_args.new_base_addr);
3199   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3200         "SEP Driver:command_args.new_resident_addr is %08lx\n",
3201         command_args.new_resident_addr);
3202   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3203         "SEP Driver:command_args.new_cache_addr is %08lx\n",
3204         command_args.new_cache_addr);
3205
3206   /* return to user */
3207   error = copy_to_user((void *)arg,
3208         (void *)&command_args,
3209         sizeof(struct sep_driver_realloc_cache_resident_t));
3210
3211 end_function:
3212
3213   return error;
3214 }
3215
3216 /*
3217   this function handles the request for get time
3218 */
3219 static int sep_get_time_handler(unsigned long arg)
3220 {
3221   /* error */
3222   int error;
3223
3224   /* command arguments */
3225   struct sep_driver_get_time_t  command_args;
3226
3227   /*------------------------
3228         CODE
3229   --------------------------*/
3230
3231   error = sep_set_time(&command_args.time_physical_address,
3232                         &command_args.time_value);
3233
3234   /* return to user */
3235   error = copy_to_user((void *)arg,
3236         (void *)&command_args,
3237         sizeof(struct sep_driver_get_time_t));
3238
3239   return error;
3240
3241 }
3242
3243 /*
3244   This api handles the setting of API mode to blocking or non-blocking
3245 */
3246 static int sep_set_api_mode_handler(unsigned long arg)
3247 {
3248   /* error */
3249   int                   error;
3250
3251   /* flag */
3252   unsigned long mode_flag;
3253
3254   /*----------------------------
3255         CODE
3256   -----------------------------*/
3257
3258   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3259                 "SEP Driver:--------> sep_set_api_mode_handler start\n");
3260
3261   error = get_user(
3262           mode_flag, &(((struct sep_driver_set_api_mode_t *)arg)->mode));
3263   if (error)
3264         goto end_function;
3265
3266   /* set the global flag */
3267   sep_dev->block_mode_flag = mode_flag;
3268
3269
3270 end_function:
3271
3272   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3273                 "SEP Driver:<-------- sep_set_api_mode_handler end\n");
3274
3275   return error;
3276 }
3277
3278 /*
3279   This API handles the end transaction request
3280 */
3281 static int sep_end_transaction_handler(unsigned long arg)
3282 {
3283   /*----------------------------
3284         CODE
3285   -----------------------------*/
3286
3287   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3288                 "SEP Driver:--------> sep_end_transaction_handler start\n");
3289
3290 #if 0/*!SEP_DRIVER_POLLING_MODE*/
3291   /* close IMR */
3292   sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
3293
3294   /* release IRQ line */
3295   free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
3296
3297   /* lock the sep mutex */
3298   mutex_unlock(&sep_mutex);
3299 #endif
3300
3301   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3302                 "SEP Driver:<-------- sep_end_transaction_handler end\n");
3303
3304   return 0;
3305 }
3306
3307 /* handler for flow done interrupt */
3308 static void sep_flow_done_handler(struct work_struct            *work)
3309 {
3310   /* flow context_ptr */
3311   struct sep_flow_context_t             *flow_data_ptr;
3312   /*-------------------------
3313         CODE
3314   ---------------------------*/
3315
3316   /* obtain the mutex */
3317   mutex_lock(&sep_mutex);
3318
3319   /* get the pointer to context */
3320   flow_data_ptr = (struct sep_flow_context_t *)work;
3321
3322   /* free all the current input tables in sep */
3323   sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
3324
3325   /* free all the current tables output tables in SEP (if needed) */
3326   if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
3327         sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
3328
3329   /* check if we have additional tables to be sent to SEP only input
3330         flag may be checked */
3331   if (flow_data_ptr->input_tables_flag) {
3332         /* copy the message to the shared RAM and signal SEP */
3333         memcpy((void *)flow_data_ptr->message,
3334         (void *)sep_dev->shared_area_addr,
3335         flow_data_ptr->message_size_in_bytes);
3336
3337         sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2);
3338   }
3339   mutex_unlock(&sep_mutex);
3340 }
3341
3342
3343 /*
3344   This function creates a list of tables for flow and returns the data for
3345         the first and last tables of the list
3346 */
3347 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
3348                         unsigned long   first_buff_addr,
3349                         struct sep_flow_context_t       *flow_data_ptr,
3350                         struct sep_lli_entry_t          *first_table_data_ptr,
3351                         struct sep_lli_entry_t          *last_table_data_ptr,
3352                         bool                    isKernelVirtualAddress)
3353 {
3354   /* error */
3355   int                           error;
3356
3357   /* virtaul address of one buffer */
3358   unsigned long         virt_buff_addr;
3359
3360   /* virtual size of one buffer */
3361   unsigned long         virt_buff_size;
3362
3363   /* table data for each created table */
3364   struct sep_lli_entry_t        table_data;
3365
3366   /* info entry */
3367   struct sep_lli_entry_t                *info_entry_ptr;
3368
3369   /* prevouis info entry */
3370   struct sep_lli_entry_t                *prev_info_entry_ptr;
3371
3372   /* counter */
3373   unsigned long         i;
3374
3375   /*-------------------------------
3376         CODE
3377   ----------------------------------*/
3378
3379   /* init vars */
3380   error = 0;
3381   prev_info_entry_ptr = 0;
3382
3383   /* init the first table to default */
3384   table_data.physical_address = 0xffffffff;
3385   first_table_data_ptr->physical_address = 0xffffffff;
3386   table_data.block_size = 0;
3387
3388   for (i = 0; i < num_virtual_buffers; i++) {
3389         /* get the virtual buffer address */
3390         error = get_user(virt_buff_addr, &first_buff_addr);
3391         if (error)
3392         goto end_function;
3393
3394         /* get the virtual buffer size */
3395         first_buff_addr++;
3396         error = get_user(virt_buff_size, &first_buff_addr);
3397         if (error)
3398         goto end_function;
3399
3400         /* advance the address to point to the next pair of address|size */
3401         first_buff_addr++;
3402
3403         /* now prepare the one flow LLI table from the data */
3404         error = sep_prepare_one_flow_dma_table(virt_buff_addr,
3405                                         virt_buff_size,
3406                                         &table_data,
3407                                         &info_entry_ptr,
3408                                         flow_data_ptr,
3409                                         isKernelVirtualAddress);
3410         if (error)
3411         goto end_function;
3412
3413         if (i == 0) {
3414           /* if this is the first table - save it to return to the user
3415                 application */
3416           *first_table_data_ptr = table_data;
3417
3418           /* set the pointer to info entry */
3419           prev_info_entry_ptr = info_entry_ptr;
3420         } else {
3421           /* not first table - the previous table info entry should
3422                 be updated */
3423           prev_info_entry_ptr->block_size =
3424                 (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) |
3425                 (table_data.block_size);
3426
3427           /* set the pointer to info entry */
3428           prev_info_entry_ptr = info_entry_ptr;
3429         }
3430   }
3431
3432   /* set the last table data */
3433   *last_table_data_ptr = table_data;
3434
3435 end_function:
3436
3437   return error;
3438 }
3439
3440
3441 /*
3442   This function creates one DMA table for flow and returns its data,
3443   and pointer to its info entry
3444 */
3445 static int sep_prepare_one_flow_dma_table(
3446                         unsigned long    virt_buff_addr,
3447                         unsigned long    virt_buff_size,
3448                         struct sep_lli_entry_t          *table_data,
3449                         struct sep_lli_entry_t          **info_entry_ptr,
3450                         struct sep_flow_context_t               *flow_data_ptr,
3451                         bool                    isKernelVirtualAddress)
3452 {
3453   /* error */
3454   int                           error;
3455
3456   /* the range in pages */
3457   unsigned long         lli_array_size;
3458
3459   /* array of pointers ot page */
3460   struct sep_lli_entry_t                *lli_array;
3461
3462   /* pointer to the entry in the dma table */
3463   struct sep_lli_entry_t                *flow_dma_table_entry_ptr;
3464
3465   /* address of the dma table */
3466   unsigned long         *start_dma_table_ptr;
3467
3468   /* total table data counter */
3469   unsigned long         dma_table_data_count;
3470
3471   /* pointer that will keep the pointer t the pages of the virtual buffer */
3472   struct page           **page_array_ptr;
3473
3474   /* counter */
3475   unsigned long         entry_count;
3476
3477   /*-------------------------------
3478         CODE
3479   ----------------------------------*/
3480
3481   /* find the space for the new table */
3482   error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
3483   if (error)
3484         goto end_function;
3485
3486   /* check if the pages are in Kernel Virtual Address layout */
3487   if (isKernelVirtualAddress == true)
3488         /* lock kernel buffer in the memory */
3489         error = sep_lock_kernel_pages(virt_buff_addr,
3490                                   virt_buff_size,
3491                                   &lli_array_size,
3492                                   &lli_array,
3493                                   &page_array_ptr);
3494   else
3495         /* lock user buffer in the memory */
3496         error = sep_lock_user_pages(virt_buff_addr,
3497                                 virt_buff_size,
3498                                 &lli_array_size,
3499                                 &lli_array,
3500                                 &page_array_ptr);
3501
3502   if (error)
3503         goto end_function;
3504
3505   /* set the pointer to page array at the beginning of table - this table is
3506         now considered taken */
3507   *start_dma_table_ptr = lli_array_size;
3508
3509   /* point to the place of the pages pointers of the table */
3510   start_dma_table_ptr++;
3511
3512   /* set the pages pointer */
3513   *start_dma_table_ptr = (unsigned long)page_array_ptr;
3514
3515   /* set the pointer to the first entry */
3516   flow_dma_table_entry_ptr = (struct sep_lli_entry_t *)(++start_dma_table_ptr);
3517
3518   /* now create the entries for table */
3519   for (dma_table_data_count = entry_count = 0;
3520                 entry_count <  lli_array_size;
3521                 entry_count++) {
3522         flow_dma_table_entry_ptr->physical_address =
3523                         lli_array[entry_count].physical_address;
3524
3525         flow_dma_table_entry_ptr->block_size =
3526                 lli_array[entry_count].block_size;
3527
3528         /* set the total data of a table */
3529         dma_table_data_count += lli_array[entry_count].block_size;
3530
3531         flow_dma_table_entry_ptr++;
3532   }
3533
3534   /* set the physical address */
3535   table_data->physical_address = virt_to_phys(start_dma_table_ptr);
3536
3537   /* set the num_entries and total data size */
3538   table_data->block_size = ((lli_array_size + 1) <<
3539                         SEP_NUM_ENTRIES_OFFSET_IN_BITS) |
3540                         (dma_table_data_count);
3541
3542   /* set the info entry */
3543   flow_dma_table_entry_ptr->physical_address = 0xffffffff;
3544   flow_dma_table_entry_ptr->block_size = 0;
3545
3546   /* set the pointer to info entry */
3547   *info_entry_ptr = flow_dma_table_entry_ptr;
3548
3549   /* the array of the lli entries */
3550   kfree(lli_array);
3551
3552 end_function:
3553
3554   return error;
3555 }
3556
3557
3558 /*
3559   This function returns pointer to the  flow data structure
3560   that conatins the given id
3561 */
3562 static int sep_find_flow_context(
3563                                 unsigned long   flow_id,
3564                                 struct sep_flow_context_t **flow_data_ptr)
3565 {
3566   /* count */
3567   unsigned long count;
3568
3569   /* error */
3570   int                   error;
3571
3572   /*-----------------------
3573         CODE
3574   ---------------------------*/
3575
3576   error = 0;
3577
3578   /*
3579          always search for flow with id default first - in case we
3580          already started working on the flow there can be no situation
3581          when 2 flows are with default flag
3582   */
3583   for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
3584         if (sep_dev->flows_data_array[count].flow_id == flow_id) {
3585           *flow_data_ptr = &sep_dev->flows_data_array[count];
3586           break;
3587         }
3588   }
3589
3590   if (count == SEP_DRIVER_NUM_FLOWS)
3591         /* no flow found  */
3592         error = -ENOMEM;
3593
3594   return error;
3595 }
3596
3597 /*
3598   this function find a space for the new flow dma table
3599 */
3600 static int sep_find_free_flow_dma_table_space(
3601                         unsigned long   **table_address_ptr)
3602 {
3603   /* error */
3604   int                   error;
3605
3606   /* pointer to the id field of the flow dma table */
3607   unsigned long         *start_table_ptr;
3608
3609   /* start address of the flow dma area */
3610   unsigned long flow_dma_area_start_addr;
3611
3612   /* end address of the flow dma area */
3613   unsigned long flow_dma_area_end_addr;
3614
3615   /* maximum table size in words */
3616   unsigned long table_size_in_words;
3617
3618   /*---------------------
3619         CODE
3620   -----------------------*/
3621
3622   error = 0;
3623
3624   /* find the start address of the flow DMA table area */
3625   flow_dma_area_start_addr = sep_dev->shared_area_addr +
3626                         SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
3627
3628   /* set end address of the flow table area */
3629   flow_dma_area_end_addr = flow_dma_area_start_addr +
3630                         SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
3631
3632   /* set table size in words */
3633   table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE *
3634                         (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
3635
3636   /* set the pointer to the start address of DMA area */
3637   start_table_ptr = (unsigned long *)flow_dma_area_start_addr;
3638
3639   /* find the space for the next table */
3640   while (((*start_table_ptr & 0x7FFFFFFF) != 0) &&
3641                         ((unsigned long)start_table_ptr <
3642                         flow_dma_area_end_addr))
3643         start_table_ptr += table_size_in_words;
3644
3645   /* check if we reached the end of floa tables area */
3646   if ((unsigned long)start_table_ptr >= flow_dma_area_end_addr)
3647         error = -1;
3648   else
3649         *table_address_ptr = start_table_ptr;
3650
3651   return error;
3652 }
3653
3654 /*
3655   this function goes over all the flow tables connected to the given
3656         table and deallocate them
3657 */
3658 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
3659 {
3660   /* id poiner */
3661   unsigned long         *table_ptr;
3662
3663   /* end address of the flow dma area */
3664   unsigned long num_entries;
3665
3666   unsigned long num_pages;
3667
3668   /* pages ptr */
3669   struct page           **pages_ptr;
3670
3671   /* maximum table size in words */
3672   struct sep_lli_entry_t                *info_entry_ptr;
3673
3674   /*-------------------------------
3675         CODE
3676   ---------------------------------*/
3677
3678   /* set the pointer to the first table */
3679   table_ptr = (unsigned long *)first_table_ptr->physical_address;
3680
3681   /* set the num of entries */
3682   num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
3683                                 & SEP_NUM_ENTRIES_MASK;
3684
3685   /* go over all the connected tables */
3686   while (*table_ptr != 0xffffffff) {
3687         /* get number of pages */
3688         num_pages = *(table_ptr - 2);
3689
3690         /* get the pointer to the pages */
3691         pages_ptr = (struct page **)(*(table_ptr - 1));
3692
3693         /* free the pages */
3694         sep_free_dma_pages(pages_ptr, num_pages, 1);
3695
3696         /* goto to the info entry */
3697         info_entry_ptr = ((struct sep_lli_entry_t *)table_ptr) +
3698                                         (num_entries - 1);
3699
3700         table_ptr = (unsigned long *)info_entry_ptr->physical_address;
3701         num_entries = (info_entry_ptr->block_size >>
3702                 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
3703   }
3704
3705   return;
3706 }
3707
3708 /*
3709   This function handler the set flow id command
3710 */
3711 static int sep_set_flow_id_handler(unsigned long arg)
3712 {
3713   /* error */
3714   int                                   error;
3715
3716   /* flow _id */
3717   unsigned long          flow_id;
3718
3719   /* pointer to flow data structre */
3720   struct sep_flow_context_t             *flow_data_ptr;
3721
3722   /*----------------------
3723         CODE
3724   -----------------------*/
3725
3726   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3727                 "------------>SEP Driver: sep_set_flow_id_handler start\n");
3728
3729   error = get_user(flow_id,
3730         &(((struct sep_driver_set_flow_id_t *)arg)->flow_id));
3731   if (error)
3732         goto end_function;
3733
3734   /* find the flow data structure that was just used for creating new flow
3735         - its id should be default */
3736   error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
3737   if (error)
3738         goto end_function;
3739
3740   /* set flow id */
3741   flow_data_ptr->flow_id = flow_id;
3742
3743 end_function:
3744
3745   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3746                 "SEP Driver:<-------- sep_set_flow_id_handler end\n");
3747
3748
3749   return error;
3750 }
3751
3752
3753 /*
3754   calculates time and sets it at the predefined address
3755 */
3756 static int sep_set_time(unsigned long           *address_ptr,
3757                         unsigned long           *time_in_sec_ptr)
3758 {
3759   /*  time struct */
3760   struct timeval  time;
3761
3762   /* address of time in the kernel */
3763   unsigned long time_addr;
3764
3765
3766   /*------------------------
3767         CODE
3768   --------------------------*/
3769
3770   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3771                 "SEP Driver:--------> sep_set_time start\n");
3772
3773
3774   do_gettimeofday(&time);
3775
3776   /* set value in the SYSTEM MEMORY offset */
3777   time_addr = sep_dev->message_shared_area_addr +
3778                         SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
3779
3780   *(unsigned long *)time_addr = SEP_TIME_VAL_TOKEN;
3781   *(unsigned long *)(time_addr + 4) = time.tv_sec;
3782
3783   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3784                         "SEP Driver:time.tv_sec is %lu\n",
3785                         time.tv_sec);
3786   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3787                         "SEP Driver:time_addr is %lu\n",
3788                         time_addr);
3789   DEBUG_PRINT_1(SEP_DEBUG_LEVEL_EXTENDED,
3790                         "SEP Driver:g_message_shared_area_addr is %lu\n",
3791                         sep_dev->message_shared_area_addr);
3792
3793   /* set the output parameters if needed */
3794   if (address_ptr)
3795         *address_ptr = sep_shared_area_virt_to_phys(time_addr);
3796
3797   if (time_in_sec_ptr)
3798         *time_in_sec_ptr = time.tv_sec;
3799
3800   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3801                 "SEP Driver:<-------- sep_set_time end\n");
3802
3803   return 0;
3804 }
3805
3806 /*
3807   PATCH for configuring the DMA to single burst instead of multi-burst
3808 */
3809 static void sep_configure_dma_burst(void)
3810 {
3811
3812 #define          HW_AHB_RD_WR_BURSTS_REG_ADDR            0x0E10UL
3813
3814   unsigned long regVal;
3815
3816   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3817                 "SEP Driver:<-------- sep_configure_dma_burst start \n");
3818
3819   /* request access to registers from SEP */
3820   sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
3821
3822   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3823                 "SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg)  \n");
3824
3825  regVal = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
3826   while (regVal)
3827         regVal = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
3828
3829   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3830                 "SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop)  \n");
3831
3832   /* set the DMA burst register to single burst*/
3833   sep_write_reg(sep_dev, HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
3834
3835   /* release the sep busy */
3836   sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
3837   regVal = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
3838   while (regVal != 0x0)
3839           regVal = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
3840
3841   DEBUG_PRINT_0(SEP_DEBUG_LEVEL_BASIC,
3842                 "SEP Driver:<-------- sep_configure_dma_burst done  \n");
3843
3844 }
3845
3846 module_init(sep_init);
3847 module_exit(sep_exit);
3848
3849 MODULE_LICENSE("GPL");