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