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