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