V4L/DVB (8278): sms1xxx: more codingstyle cleanups
[linux-2.6] / drivers / media / dvb / siano / smscoreapi.c
1 /*
2  *  Siano core API module
3  *
4  *  This file contains implementation for the interface to sms core component
5  *
6  *  author: Anatoly Greenblat
7  *
8  *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License version 3 as
12  *  published by the Free Software Foundation;
13  *
14  *  Software distributed under the License is distributed on an "AS IS"
15  *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
16  *
17  *  See the GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/moduleparam.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/delay.h>
30 #include <asm/io.h>
31
32 #include <linux/firmware.h>
33
34 #include "smscoreapi.h"
35
36 #define PERROR(fmt, args...) printk( KERN_ERR "smscore error: line %d- %s(): " fmt,__LINE__,  __func__, ## args)
37
38 #ifdef SMSCORE_DEBUG
39
40 #undef PWARNING
41 #  define PWARNING(fmt, args...) printk( KERN_INFO "smscore warning: line %d- %s(): " fmt,__LINE__,  __func__, ## args)
42 #undef PDEBUG                                   /* undef it, just in case */
43 #  define PDEBUG(fmt, args...)  printk( KERN_INFO "smscore - %s(): " fmt, __func__, ## args)
44
45 #else /*SMSCORE_DEBUG*/
46
47 #define PDEBUG(fmt, args...)
48 #define PWARNING(fmt, args...)
49
50 #endif
51
52
53 typedef struct _smscore_device_notifyee
54 {
55         struct list_head entry;
56         hotplug_t hotplug;
57 } smscore_device_notifyee_t;
58
59 typedef struct _smscore_subclient
60 {
61         struct list_head entry;
62         int             id;
63         int             data_type;
64 } smscore_idlist_t;
65
66 typedef struct _smscore_client
67 {
68         struct list_head entry;
69         smscore_device_t *coredev;
70         void                    *context;
71         struct list_head        idlist;
72         onresponse_t    onresponse_handler;
73         onremove_t              onremove_handler;
74 } *psmscore_client_t;
75
76
77
78 typedef struct _smscore_device
79 {
80         struct list_head entry;
81
82         struct list_head clients;
83         struct list_head subclients;
84         spinlock_t              clientslock;
85
86         struct list_head buffers;
87         spinlock_t              bufferslock;
88         int                             num_buffers;
89
90         void                    *common_buffer;
91         int                             common_buffer_size;
92         dma_addr_t              common_buffer_phys;
93
94         void                    *context;
95         struct device   *device;
96
97         char                    devpath[32];
98         unsigned long   device_flags;
99
100         setmode_t               setmode_handler;
101         detectmode_t    detectmode_handler;
102         sendrequest_t   sendrequest_handler;
103         preload_t               preload_handler;
104         postload_t              postload_handler;
105
106         int                             mode, modes_supported;
107
108         struct completion version_ex_done, data_download_done, trigger_done;
109         struct completion init_device_done, reload_start_done, resume_done;
110 } *psmscore_device_t;
111
112 typedef struct _smscore_registry_entry
113 {
114         struct list_head entry;
115         char                    devpath[32];
116         int                             mode;
117         sms_device_type_st      type;
118 } smscore_registry_entry_t;
119
120 struct list_head g_smscore_notifyees;
121 struct list_head g_smscore_devices;
122 kmutex_t g_smscore_deviceslock;
123
124 struct list_head g_smscore_registry;
125 kmutex_t g_smscore_registrylock;
126
127 static int default_mode = 1;
128
129 module_param(default_mode, int, 0644);
130 MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
131
132 static smscore_registry_entry_t *smscore_find_registry ( char *devpath )
133 {
134         smscore_registry_entry_t *entry;
135         struct list_head *next;
136
137         kmutex_lock(&g_smscore_registrylock);
138         for (next = g_smscore_registry.next; next != &g_smscore_registry; next = next->next)
139         {
140                 entry = (smscore_registry_entry_t *) next;
141                 if (!strcmp(entry->devpath, devpath))
142                 {
143                         kmutex_unlock(&g_smscore_registrylock);
144                         return entry;
145                 }
146         }
147         entry = (smscore_registry_entry_t *) kmalloc(sizeof(smscore_registry_entry_t), GFP_KERNEL);
148         if (entry)
149         {
150                 entry->mode = default_mode;
151                 strcpy(entry->devpath, devpath);
152                 list_add(&entry->entry, &g_smscore_registry);
153         }
154         else
155                 printk ( KERN_ERR "%s failed to create smscore_registry.\n", __func__ );
156         kmutex_unlock(&g_smscore_registrylock);
157         return entry;
158 }
159
160 int smscore_registry_getmode ( char *devpath )
161 {
162         smscore_registry_entry_t *entry;
163
164         entry = smscore_find_registry ( devpath );
165         if ( entry )
166         {
167                 return entry->mode;
168         }
169         else
170         {
171                 printk ( KERN_ERR "%s No registry found.\n", __func__ );
172         }
173         return default_mode;
174 }
175
176 sms_device_type_st smscore_registry_gettype ( char *devpath )
177 {
178         smscore_registry_entry_t *entry;
179
180         entry = smscore_find_registry ( devpath );
181         if ( entry )
182         {
183                 return entry->type;
184         }
185         else
186         {
187                 printk ( KERN_ERR "%s No registry found.\n", __func__ );
188         }
189         return -1;
190 }
191
192 void smscore_registry_setmode ( char *devpath, int mode )
193         {
194         smscore_registry_entry_t *entry;
195
196         entry = smscore_find_registry ( devpath );
197         if ( entry )
198                 {
199                         entry->mode = mode;
200         }
201         else
202         {
203                 printk ( KERN_ERR "%s No registry found.\n", __func__ );
204                 }
205         }
206
207 void smscore_registry_settype ( char *devpath, sms_device_type_st type )
208 {
209         smscore_registry_entry_t *entry;
210
211         entry = smscore_find_registry ( devpath );
212         if ( entry )
213         {
214                 entry->type = type;
215         }
216         else
217         {
218                 printk ( KERN_ERR "%s No registry found.\n", __func__ );
219 }
220 }
221
222
223
224 void list_add_locked(struct list_head *new, struct list_head *head,
225                       spinlock_t *lock)
226 {
227         unsigned long flags;
228
229         spin_lock_irqsave(lock, flags);
230
231         list_add(new, head);
232
233         spin_unlock_irqrestore(lock, flags);
234 }
235
236 /**
237  * register a client callback that called when device plugged in/unplugged
238  * NOTE: if devices exist callback is called immediately for each device
239  *
240  * @param hotplug callback
241  *
242  * @return 0 on success, <0 on error.
243  */
244 int smscore_register_hotplug(hotplug_t hotplug)
245 {
246         smscore_device_notifyee_t *notifyee;
247         struct list_head *next, *first;
248         int rc = 0;
249
250         kmutex_lock(&g_smscore_deviceslock);
251
252         notifyee = kmalloc(sizeof(smscore_device_notifyee_t), GFP_KERNEL);
253         if (notifyee)
254         {
255                 // now notify callback about existing devices
256                 first = &g_smscore_devices;
257                 for (next = first->next; next != first && !rc; next = next->next)
258                 {
259                         smscore_device_t *coredev = (smscore_device_t *) next;
260                         rc = hotplug(coredev, coredev->device, 1);
261                 }
262
263                 if (rc >= 0)
264                 {
265                         notifyee->hotplug = hotplug;
266                         list_add(&notifyee->entry, &g_smscore_notifyees);
267                 }
268                 else
269                         kfree(notifyee);
270         }
271         else
272                 rc = -ENOMEM;
273
274         kmutex_unlock(&g_smscore_deviceslock);
275
276         return rc;
277 }
278
279 /**
280  * unregister a client callback that called when device plugged in/unplugged
281  *
282  * @param hotplug callback
283  *
284  */
285 void smscore_unregister_hotplug(hotplug_t hotplug)
286 {
287         struct list_head *next, *first;
288
289         kmutex_lock(&g_smscore_deviceslock);
290
291         first = &g_smscore_notifyees;
292
293         for (next = first->next; next != first;)
294         {
295                 smscore_device_notifyee_t *notifyee = (smscore_device_notifyee_t *) next;
296                 next = next->next;
297
298                 if (notifyee->hotplug == hotplug)
299                 {
300                         list_del(&notifyee->entry);
301                         kfree(notifyee);
302                 }
303         }
304
305         kmutex_unlock(&g_smscore_deviceslock);
306 }
307
308 void smscore_notify_clients(smscore_device_t *coredev)
309 {
310         smscore_client_t *client;
311
312         // the client must call smscore_unregister_client from remove handler
313         while (!list_empty(&coredev->clients))
314         {
315                 client = (smscore_client_t *) coredev->clients.next;
316                 client->onremove_handler(client->context);
317         }
318 }
319
320 int smscore_notify_callbacks(smscore_device_t *coredev, struct device *device, int arrival)
321 {
322         struct list_head *next, *first;
323         int rc = 0;
324
325         // note: must be called under g_deviceslock
326
327         first = &g_smscore_notifyees;
328
329         for (next = first->next; next != first; next = next->next)
330         {
331                 rc = ((smscore_device_notifyee_t *) next)->hotplug(coredev, device, arrival);
332                 if (rc < 0)
333                         break;
334         }
335
336         return rc;
337 }
338
339 smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
340                                        dma_addr_t common_buffer_phys)
341 {
342         smscore_buffer_t *cb = kmalloc(sizeof(smscore_buffer_t), GFP_KERNEL);
343         if (!cb)
344         {
345                 printk(KERN_INFO "%s kmalloc(...) failed\n", __func__);
346                 return NULL;
347         }
348
349         cb->p = buffer;
350         cb->offset_in_common = buffer - (u8 *) common_buffer;
351         cb->phys = common_buffer_phys + cb->offset_in_common;
352
353         return cb;
354 }
355
356 /**
357  * creates coredev object for a device, prepares buffers, creates buffer mappings, notifies
358  * registered hotplugs about new device.
359  *
360  * @param params device pointer to struct with device specific parameters and handlers
361  * @param coredev pointer to a value that receives created coredev object
362  *
363  * @return 0 on success, <0 on error.
364  */
365 int smscore_register_device(smsdevice_params_t *params, smscore_device_t **coredev)
366 {
367         smscore_device_t *dev;
368         u8 *buffer;
369
370         dev = kzalloc(sizeof(smscore_device_t), GFP_KERNEL);
371         if (!dev)
372         {
373                 printk(KERN_INFO "%s kzalloc(...) failed\n", __func__);
374                 return -ENOMEM;
375         }
376
377         // init list entry so it could be safe in smscore_unregister_device
378         INIT_LIST_HEAD(&dev->entry);
379
380         // init queues
381         INIT_LIST_HEAD(&dev->clients);
382         INIT_LIST_HEAD(&dev->buffers);
383
384         // init locks
385         spin_lock_init(&dev->clientslock);
386         spin_lock_init(&dev->bufferslock);
387
388         // init completion events
389         init_completion(&dev->version_ex_done);
390         init_completion(&dev->data_download_done);
391         init_completion(&dev->trigger_done);
392         init_completion(&dev->init_device_done);
393         init_completion(&dev->reload_start_done);
394         init_completion(&dev->resume_done);
395
396         // alloc common buffer
397         dev->common_buffer_size = params->buffer_size * params->num_buffers;
398         dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size, &dev->common_buffer_phys, GFP_KERNEL | GFP_DMA);
399         if (!dev->common_buffer)
400         {
401                 smscore_unregister_device(dev);
402                 return -ENOMEM;
403         }
404
405         // prepare dma buffers
406         for (buffer = dev->common_buffer; dev->num_buffers < params->num_buffers; dev->num_buffers ++, buffer += params->buffer_size)
407         {
408                 smscore_buffer_t *cb = smscore_createbuffer(buffer, dev->common_buffer, dev->common_buffer_phys);
409                 if (!cb)
410                 {
411                         smscore_unregister_device(dev);
412                         return -ENOMEM;
413                 }
414
415                 smscore_putbuffer(dev, cb);
416         }
417
418         printk(KERN_INFO "%s allocated %d buffers\n", __func__, dev->num_buffers);
419
420         dev->mode = DEVICE_MODE_NONE;
421         dev->context = params->context;
422         dev->device = params->device;
423         dev->setmode_handler = params->setmode_handler;
424         dev->detectmode_handler = params->detectmode_handler;
425         dev->sendrequest_handler = params->sendrequest_handler;
426         dev->preload_handler = params->preload_handler;
427         dev->postload_handler = params->postload_handler;
428
429         dev->device_flags = params->flags;
430         strcpy(dev->devpath, params->devpath);
431
432         smscore_registry_settype ( dev->devpath, params->device_type );
433
434         // add device to devices list
435         kmutex_lock(&g_smscore_deviceslock);
436         list_add(&dev->entry, &g_smscore_devices);
437         kmutex_unlock(&g_smscore_deviceslock);
438
439         *coredev = dev;
440
441         printk(KERN_INFO "%s device %p created\n", __func__, dev);
442
443         return 0;
444 }
445
446 /**
447  * sets initial device mode and notifies client hotplugs that device is ready
448  *
449  * @param coredev pointer to a coredev object returned by smscore_register_device
450  *
451  * @return 0 on success, <0 on error.
452  */
453 int smscore_start_device(smscore_device_t *coredev)
454 {
455         int rc = smscore_set_device_mode(coredev, smscore_registry_getmode(coredev->devpath));
456         if (rc < 0)
457         {
458                 printk ( KERN_INFO "%s set device mode faile , rc %d\n", __func__, rc );
459                 return rc;
460         }
461
462         kmutex_lock(&g_smscore_deviceslock);
463
464         rc = smscore_notify_callbacks(coredev, coredev->device, 1);
465
466         printk(KERN_INFO "%s device %p started, rc %d\n", __func__, coredev, rc);
467
468         kmutex_unlock(&g_smscore_deviceslock);
469
470         return rc;
471 }
472
473 int smscore_sendrequest_and_wait(smscore_device_t *coredev, void *buffer,
474                                   size_t size, struct completion *completion)
475 {
476         int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
477         if (rc < 0)
478         {
479                 printk(KERN_INFO "%s sendrequest returned error %d\n", __func__, rc);
480                 return rc;
481         }
482
483         return wait_for_completion_timeout(completion, msecs_to_jiffies(10000)) ? 0 : -ETIME;
484 }
485
486 int smscore_load_firmware_family2(smscore_device_t *coredev, void *buffer, size_t size)
487 {
488         SmsFirmware_ST* firmware = (SmsFirmware_ST*) buffer;
489         SmsMsgHdr_ST *msg;
490         UINT32 mem_address = firmware->StartAddress;
491         u8 *payload = firmware->Payload;
492         int rc = 0;
493
494         printk(KERN_INFO "%s loading FW to addr 0x%x size %d\n", __func__, mem_address,firmware->Length);
495         if (coredev->preload_handler)
496         {
497                 rc = coredev->preload_handler(coredev->context);
498                 if (rc < 0)
499                         return rc;
500         }
501
502         // PAGE_SIZE buffer shall be enough and dma aligned
503         msg = (SmsMsgHdr_ST *) kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
504         if (!msg)
505                 return -ENOMEM;
506
507         if (coredev->mode != DEVICE_MODE_NONE)
508         {
509                 PDEBUG("Sending reload command\n");
510                 SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ, sizeof(SmsMsgHdr_ST));
511                 rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength, &coredev->reload_start_done);
512                 mem_address = *(UINT32*) &payload[20];
513         }
514
515         while (size && rc >= 0)
516         {
517                 SmsDataDownload_ST *DataMsg = (SmsDataDownload_ST *) msg;
518                 int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
519
520                 SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ, (UINT16)(sizeof(SmsMsgHdr_ST) + sizeof(UINT32) + payload_size));
521
522                 DataMsg->MemAddr = mem_address;
523                 memcpy(DataMsg->Payload, payload, payload_size);
524
525                 if (coredev->device_flags & SMS_ROM_NO_RESPONSE && coredev->mode == DEVICE_MODE_NONE)
526                         rc = coredev->sendrequest_handler(coredev->context, DataMsg, DataMsg->xMsgHeader.msgLength);
527                 else
528                         rc = smscore_sendrequest_and_wait(coredev, DataMsg, DataMsg->xMsgHeader.msgLength, &coredev->data_download_done);
529
530                 payload += payload_size;
531                 size -= payload_size;
532                 mem_address += payload_size;
533         }
534
535         if (rc >= 0)
536         {
537                 if (coredev->mode == DEVICE_MODE_NONE)
538                 {
539                         SmsMsgData_ST* TriggerMsg = (SmsMsgData_ST*) msg;
540
541                         SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ, sizeof(SmsMsgHdr_ST) + sizeof(UINT32) * 5);
542
543                         TriggerMsg->msgData[0] = firmware->StartAddress;        // Entry point
544                         TriggerMsg->msgData[1] = 5;                                                     // Priority
545                         TriggerMsg->msgData[2] = 0x200;                                         // Stack size
546                         TriggerMsg->msgData[3] = 0;                                                     // Parameter
547                         TriggerMsg->msgData[4] = 4;                                                     // Task ID
548
549                         if (coredev->device_flags & SMS_ROM_NO_RESPONSE)
550                         {
551                                 rc = coredev->sendrequest_handler(coredev->context, TriggerMsg, TriggerMsg->xMsgHeader.msgLength);
552                                 msleep(100);
553                         }
554                         else
555                                 rc = smscore_sendrequest_and_wait(coredev, TriggerMsg, TriggerMsg->xMsgHeader.msgLength, &coredev->trigger_done);
556                 }
557                 else
558                 {
559                         SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ, sizeof(SmsMsgHdr_ST));
560
561                         rc = coredev->sendrequest_handler(coredev->context, msg, msg->msgLength);
562                 }
563                 msleep ( 500 );
564         }
565
566         printk("%s rc=%d, postload=%p \n", __func__, rc, coredev->postload_handler);
567
568         kfree(msg);
569
570         return ((rc >= 0) && coredev->postload_handler) ?
571                 coredev->postload_handler(coredev->context) :
572                 rc;
573 }
574
575 /**
576  * loads specified firmware into a buffer and calls device loadfirmware_handler
577  *
578  * @param coredev pointer to a coredev object returned by smscore_register_device
579  * @param filename null-terminated string specifies firmware file name
580  * @param loadfirmware_handler device handler that loads firmware
581  *
582  * @return 0 on success, <0 on error.
583  */
584 int smscore_load_firmware_from_file(smscore_device_t *coredev, char *filename, loadfirmware_t loadfirmware_handler)
585 {
586         int rc = -ENOENT;
587
588         const struct firmware *fw;
589         u8 *fw_buffer;
590
591         if (loadfirmware_handler == NULL && !(coredev->device_flags & SMS_DEVICE_FAMILY2))
592                 return -EINVAL;
593
594         rc = request_firmware(&fw, filename, coredev->device);
595         if (rc < 0)
596         {
597                 printk(KERN_INFO "%s failed to open \"%s\"\n", __func__, filename);
598                 return rc;
599         }
600         printk(KERN_INFO "%s read FW %s, size=%d\"\n", __func__, filename, fw->size);
601         fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), GFP_KERNEL | GFP_DMA);
602         if (fw_buffer)
603         {
604                 memcpy(fw_buffer, fw->data, fw->size);
605
606                 rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
607                         smscore_load_firmware_family2(coredev, fw_buffer, fw->size) :
608                         loadfirmware_handler(coredev->context, fw_buffer, fw->size);
609
610                 kfree(fw_buffer);
611         }
612         else
613         {
614                 printk(KERN_INFO "%s failed to allocate firmware buffer\n", __func__);
615                 rc = -ENOMEM;
616         }
617
618         release_firmware(fw);
619
620         return rc;
621 }
622
623 int smscore_load_firmware_from_buffer(smscore_device_t *coredev, u8 *buffer, int size, int new_mode)
624 {
625         PERROR("Feature not implemented yet\n");
626         return -EFAULT;
627 }
628
629 /**
630  * notifies all clients registered with the device, notifies hotplugs, frees all buffers and coredev object
631  *
632  * @param coredev pointer to a coredev object returned by smscore_register_device
633  *
634  * @return 0 on success, <0 on error.
635  */
636 void smscore_unregister_device(smscore_device_t *coredev)
637 {
638         smscore_buffer_t *cb;
639         int num_buffers = 0;
640         int retry = 0;
641
642         kmutex_lock(&g_smscore_deviceslock);
643
644         smscore_notify_clients(coredev);
645         smscore_notify_callbacks(coredev, NULL, 0);
646
647         // at this point all buffers should be back
648         // onresponse must no longer be called
649
650         while (1)
651         {
652                 while ((cb = smscore_getbuffer(coredev)))
653                 {
654                         kfree(cb);
655                         num_buffers ++;
656                 }
657                 if (num_buffers == coredev->num_buffers)
658                         break;
659                 if (++retry > 10)
660                 {
661                         printk(KERN_INFO "%s exiting although not all buffers released.\n", __func__);
662                         break;
663                 }
664
665                 printk(KERN_INFO "%s waiting for %d buffer(s)\n", __func__, coredev->num_buffers - num_buffers);
666                 msleep(100);
667         }
668
669         printk(KERN_INFO "%s freed %d buffers\n", __func__, num_buffers);
670
671         if (coredev->common_buffer)
672                 dma_free_coherent(NULL, coredev->common_buffer_size, coredev->common_buffer, coredev->common_buffer_phys);
673
674         list_del(&coredev->entry);
675         kfree(coredev);
676
677         kmutex_unlock(&g_smscore_deviceslock);
678
679         printk(KERN_INFO "%s device %p destroyed\n", __func__, coredev);
680 }
681
682 int smscore_detect_mode(smscore_device_t *coredev)
683 {
684         void *buffer = kmalloc(sizeof(SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
685         SmsMsgHdr_ST *msg = (SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
686         int rc;
687
688         if (!buffer)
689                 return -ENOMEM;
690
691         SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ, sizeof(SmsMsgHdr_ST));
692
693         rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength, &coredev->version_ex_done);
694         if (rc == -ETIME)
695         {
696                 printk("%s: MSG_SMS_GET_VERSION_EX_REQ failed first try\n", __func__);
697
698                 if (wait_for_completion_timeout(&coredev->resume_done, msecs_to_jiffies(5000)))
699                 {
700                         rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength, &coredev->version_ex_done);
701                         if (rc < 0)
702                         {
703                                 printk("%s: MSG_SMS_GET_VERSION_EX_REQ failed second try, rc %d\n", __func__, rc);
704                         }
705                 }
706                 else
707                         rc = -ETIME;
708         }
709
710         kfree(buffer);
711
712         return rc;
713 }
714
715 char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] =
716 {
717         /*Stellar                       NOVA A0                 Nova B0                         VEGA*/
718         /*DVBT*/  {"none",                      "dvb_nova_12mhz.inp",   "dvb_nova_12mhz_b0.inp",        "none"},
719         /*DVBH*/  {"none",                      "dvb_nova_12mhz.inp",   "dvb_nova_12mhz_b0.inp",        "none"},
720         /*TDMB*/  {"none",                      "tdmb_nova_12mhz.inp",  "none"                          "none"},
721         /*DABIP*/ {"none",                      "none",                 "none",                         "none"},
722         /*BDA*/   {"none",                      "dvb_nova_12mhz.inp",   "dvb_nova_12mhz_b0.inp",        "none"},
723         /*ISDBT*/ {"none",                      "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp",           "none"},
724         /*ISDBTBDA*/{"none",                    "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp",      "none"},
725         /*CMMB*/  {"none",                      "none",                 "none",                         "cmmb_vega_12mhz.inp"}
726 };
727
728
729 /**
730  * calls device handler to change mode of operation
731  * NOTE: stellar/usb may disconnect when changing mode
732  *
733  * @param coredev pointer to a coredev object returned by smscore_register_device
734  * @param mode requested mode of operation
735  *
736  * @return 0 on success, <0 on error.
737  */
738 int smscore_set_device_mode(smscore_device_t *coredev, int mode)
739 {
740         void *buffer;
741         int rc = 0;
742         sms_device_type_st type;
743
744         PDEBUG("set device mode to %d\n", mode );
745         if (coredev->device_flags & SMS_DEVICE_FAMILY2)
746         {
747                 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER)
748                 {
749                         printk(KERN_INFO "%s invalid mode specified %d\n", __func__, mode);
750                         return -EINVAL;
751                 }
752
753                 smscore_registry_setmode(coredev->devpath, mode);
754
755                 if (!(coredev->device_flags & SMS_DEVICE_NOT_READY))
756                 {
757                         rc = smscore_detect_mode(coredev);
758                         if (rc < 0)
759                         {
760                                 printk(KERN_INFO "%s mode detect failed %d\n", __func__, rc);
761                                 return rc;
762                 }
763                 }
764
765                 if (coredev->mode == mode)
766                 {
767                         printk(KERN_INFO "%s device mode %d already set\n", __func__, mode);
768                         return 0;
769                 }
770
771                 if (!(coredev->modes_supported & (1 << mode)))
772                 {
773                         type = smscore_registry_gettype ( coredev->devpath );
774                         rc = smscore_load_firmware_from_file ( coredev, smscore_fw_lkup[mode][type], NULL );
775                         if (rc < 0)
776                         {
777                                 printk(KERN_INFO "%s load firmware failed %d\n", __func__, rc);
778                                 return rc;
779                 }
780                 }
781                 else
782                 {
783                         printk(KERN_INFO "%s mode %d supported by running firmware\n", __func__, mode);
784                 }
785
786                 buffer = kmalloc(sizeof(SmsMsgData_ST) + SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
787                 if (buffer)
788                 {
789                         SmsMsgData_ST *msg = (SmsMsgData_ST *) SMS_ALIGN_ADDRESS(buffer);
790
791                         SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ, sizeof(SmsMsgData_ST));
792                         msg->msgData[0] = mode;
793
794                         rc = smscore_sendrequest_and_wait(coredev, msg, msg->xMsgHeader.msgLength, &coredev->init_device_done);
795
796                         kfree(buffer);
797                 }
798                 else
799                 {
800                         printk(KERN_INFO "%s Could not allocate buffer for init device message.\n", __func__);
801                         rc = -ENOMEM;
802         }
803         }
804         else
805         {
806                 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA)
807                 {
808                         printk(KERN_INFO "%s invalid mode specified %d\n", __func__, mode);
809                         return -EINVAL;
810                 }
811
812                 smscore_registry_setmode(coredev->devpath, mode);
813
814                 if (coredev->detectmode_handler)
815                         coredev->detectmode_handler(coredev->context, &coredev->mode);
816
817                 if (coredev->mode != mode && coredev->setmode_handler)
818                         rc = coredev->setmode_handler(coredev->context, mode);
819         }
820
821         if (rc >= 0)
822         {
823                 coredev->mode = mode;
824                 coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
825         }
826
827         if (rc != 0)
828                 printk(KERN_INFO "%s return error code %d.\n", __func__, rc);
829         return rc;
830 }
831
832 /**
833  * calls device handler to get current mode of operation
834  *
835  * @param coredev pointer to a coredev object returned by smscore_register_device
836  *
837  * @return current mode
838  */
839 int smscore_get_device_mode(smscore_device_t *coredev)
840 {
841         return coredev->mode;
842 }
843
844 /**
845  * find client by response id & type within the clients list.
846  * return client handle or NULL.
847  *
848  * @param coredev pointer to a coredev object returned by smscore_register_device
849  * @param data_type client data type (SMS_DONT_CARE for all types)
850  * @param id client id (SMS_DONT_CARE for all id )
851  *
852  */
853 smscore_client_t *smscore_find_client(smscore_device_t *coredev, int data_type, int id)
854 {
855         smscore_client_t *client = NULL;
856         struct list_head *next, *first;
857         unsigned long flags;
858         struct list_head *firstid, *nextid;
859
860
861         spin_lock_irqsave(&coredev->clientslock, flags);
862         first = &coredev->clients;
863         for (next = first->next; (next != first) && !client; next = next->next)
864         {
865                 firstid = &((smscore_client_t*)next )->idlist;
866                 for (nextid = firstid->next ; nextid != firstid ; nextid = nextid->next)
867         {
868                         if ((((smscore_idlist_t*)nextid)->id  == id) &&
869                             (((smscore_idlist_t*)nextid)->data_type  == data_type ||
870                             (((smscore_idlist_t*)nextid)->data_type  == 0)))
871                 {
872                         client = (smscore_client_t*) next;
873                         break;
874                 }
875         }
876         }
877         spin_unlock_irqrestore(&coredev->clientslock, flags);
878         return client;
879 }
880
881 /**
882  * find client by response id/type, call clients onresponse handler
883  * return buffer to pool on error
884  *
885  * @param coredev pointer to a coredev object returned by smscore_register_device
886  * @param cb pointer to response buffer descriptor
887  *
888  */
889 void smscore_onresponse(smscore_device_t *coredev, smscore_buffer_t *cb)
890 {
891         SmsMsgHdr_ST *phdr = (SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset);
892         smscore_client_t *client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId);
893         int rc = -EBUSY;
894
895         static unsigned long last_sample_time = 0;
896         static int data_total = 0;
897         unsigned long time_now = jiffies_to_msecs(jiffies);
898
899         if (!last_sample_time)
900                 last_sample_time = time_now;
901
902         if (time_now - last_sample_time > 10000)
903         {
904                 printk("\n%s data rate %d bytes/secs\n", __func__, (int)((data_total * 1000) / (time_now - last_sample_time)));
905
906                 last_sample_time = time_now;
907                 data_total = 0;
908         }
909
910         data_total += cb->size;
911         /* If no client registered for type & id, check for control client where type is not registered*/
912 //      if (!client)
913 //              client = smscore_find_client( coredev, 0, phdr->msgDstId);
914         if (client)
915                 rc = client->onresponse_handler(client->context, cb);
916
917         if (rc < 0)
918         {
919                 switch (phdr->msgType)
920                 {
921                         case MSG_SMS_GET_VERSION_EX_RES:
922                         {
923                                 SmsVersionRes_ST *ver = (SmsVersionRes_ST*) phdr;
924                                 printk("%s: MSG_SMS_GET_VERSION_EX_RES id %d prots 0x%x ver %d.%d\n", __func__, ver->FirmwareId, ver->SupportedProtocols, ver->RomVersionMajor, ver->RomVersionMinor);
925
926                                 coredev->mode = ver->FirmwareId == 255 ? DEVICE_MODE_NONE : ver->FirmwareId;
927                                 coredev->modes_supported = ver->SupportedProtocols;
928
929                                 complete(&coredev->version_ex_done);
930                                 break;
931                         }
932
933                         case MSG_SMS_INIT_DEVICE_RES:
934                                 printk("%s: MSG_SMS_INIT_DEVICE_RES\n", __func__);
935                                 complete(&coredev->init_device_done);
936                                 break;
937
938                         case MSG_SW_RELOAD_START_RES:
939                                 printk("%s: MSG_SW_RELOAD_START_RES\n", __func__);
940                                 complete(&coredev->reload_start_done);
941                                 break;
942
943                         case MSG_SMS_DATA_DOWNLOAD_RES:
944                                 complete(&coredev->data_download_done);
945                                 break;
946
947                         case MSG_SW_RELOAD_EXEC_RES:
948                                 printk("%s: MSG_SW_RELOAD_EXEC_RES\n", __func__);
949                                 break;
950
951                         case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
952                                 printk("%s: MSG_SMS_SWDOWNLOAD_TRIGGER_RES\n", __func__);
953                                 complete(&coredev->trigger_done);
954                                 break;
955
956                         case MSG_SMS_SLEEP_RESUME_COMP_IND:
957                                 complete(&coredev->resume_done);
958                                 break;
959
960                         default:
961                                 //printk(KERN_INFO "%s no client (%p) or error (%d), type:%d dstid:%d\n", __func__, client, rc, phdr->msgType, phdr->msgDstId);
962                                 break;
963                 }
964
965                 smscore_putbuffer(coredev, cb);
966         }
967 }
968
969 /**
970  * return pointer to next free buffer descriptor from core pool
971  *
972  * @param coredev pointer to a coredev object returned by smscore_register_device
973  *
974  * @return pointer to descriptor on success, NULL on error.
975  */
976 smscore_buffer_t *smscore_getbuffer(smscore_device_t *coredev)
977 {
978         smscore_buffer_t *cb = NULL;
979         unsigned long flags;
980
981         spin_lock_irqsave(&coredev->bufferslock, flags);
982
983         if (!list_empty(&coredev->buffers))
984         {
985                 cb = (smscore_buffer_t *) coredev->buffers.next;
986                 list_del(&cb->entry);
987         }
988
989         spin_unlock_irqrestore(&coredev->bufferslock, flags);
990
991         return cb;
992 }
993
994 /**
995  * return buffer descriptor to a pool
996  *
997  * @param coredev pointer to a coredev object returned by smscore_register_device
998  * @param cb pointer buffer descriptor
999  *
1000  */
1001 void smscore_putbuffer(smscore_device_t *coredev, smscore_buffer_t *cb)
1002 {
1003         list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
1004 }
1005
1006 int smscore_validate_client(smscore_device_t *coredev, smscore_client_t *client, int data_type, int id)
1007 {
1008         smscore_idlist_t *listentry;
1009         smscore_client_t *registered_client;
1010
1011         if ( !client )
1012         {
1013                 PERROR("bad parameter.\n");
1014                 return -EFAULT;
1015         }
1016         registered_client = smscore_find_client(coredev, data_type, id);
1017         if (registered_client == client)
1018         {
1019                 return 0;
1020         }
1021         if (registered_client)
1022         {
1023                 PERROR("The msg ID already registered to another client.\n");
1024                 return -EEXIST;
1025         }
1026         listentry = kzalloc ( sizeof ( smscore_idlist_t ), GFP_KERNEL );
1027         if ( !listentry )
1028         {
1029                 PERROR("Can't allocate memory for client id.\n");
1030                 return -ENOMEM;
1031         }
1032         listentry->id = id;
1033         listentry->data_type = data_type;
1034         list_add_locked ( &listentry->entry, &client->idlist, &coredev->clientslock );
1035         return 0;
1036 }
1037
1038 /**
1039  * creates smsclient object, check that id is taken by another client
1040  *
1041  * @param coredev pointer to a coredev object from clients hotplug
1042  * @param initial_id all messages with this id would be sent to this client
1043  * @param data_type all messages of this type would be sent to this client
1044  * @param onresponse_handler client handler that is called to process incoming messages
1045  * @param onremove_handler client handler that is called when device is removed
1046  * @param context client-specific context
1047  * @param client pointer to a value that receives created smsclient object
1048  *
1049  * @return 0 on success, <0 on error.
1050  */
1051 int smscore_register_client(smscore_device_t *coredev, smsclient_params_t *params, smscore_client_t **client)
1052 {
1053         smscore_client_t *newclient;
1054         // check that no other channel with same parameters exists
1055         if (smscore_find_client(coredev, params->data_type, params->initial_id))
1056         {
1057                 PERROR("Client already exist.\n");
1058                 return -EEXIST;
1059         }
1060
1061         newclient = kzalloc(sizeof(smscore_client_t), GFP_KERNEL);
1062         if (!newclient)
1063         {
1064                 PERROR("Failed to allocate memory for client.\n");
1065                 return -ENOMEM;
1066         }
1067
1068         INIT_LIST_HEAD ( &newclient->idlist);
1069         newclient->coredev = coredev;
1070         newclient->onresponse_handler = params->onresponse_handler;
1071         newclient->onremove_handler = params->onremove_handler;
1072         newclient->context = params->context;
1073         list_add_locked(&newclient->entry, &coredev->clients, &coredev->clientslock);
1074         smscore_validate_client(coredev, newclient, params->data_type, params->initial_id);
1075         *client = newclient;
1076         PDEBUG ( "%p %d %d\n", params->context, params->data_type, params->initial_id );
1077
1078         return 0;
1079 }
1080
1081 /**
1082  * frees smsclient object and all subclients associated with it
1083  *
1084  * @param client pointer to smsclient object returned by smscore_register_client
1085  *
1086  */
1087 void smscore_unregister_client(smscore_client_t *client)
1088 {
1089         smscore_device_t *coredev = client->coredev;
1090         unsigned long flags;
1091
1092         spin_lock_irqsave(&coredev->clientslock, flags);
1093
1094
1095         while (!list_empty( &client->idlist))
1096                 {
1097                 smscore_idlist_t *identry = (smscore_idlist_t*)client->idlist.next;
1098                 list_del ( &identry->entry );
1099                 kfree ( identry );
1100         }
1101
1102         printk(KERN_INFO "%s %p\n", __func__, client->context);
1103
1104         list_del(&client->entry);
1105         kfree(client);
1106
1107         spin_unlock_irqrestore(&coredev->clientslock, flags);
1108 }
1109
1110 /**
1111  * verifies that source id is not taken by another client,
1112  * calls device handler to send requests to the device
1113  *
1114  * @param client pointer to smsclient object returned by smscore_register_client
1115  * @param buffer pointer to a request buffer
1116  * @param size size (in bytes) of request buffer
1117  *
1118  * @return 0 on success, <0 on error.
1119  */
1120 int smsclient_sendrequest(smscore_client_t *client, void *buffer, size_t size)
1121 {
1122         smscore_device_t *coredev;
1123         SmsMsgHdr_ST *phdr = (SmsMsgHdr_ST *) buffer;
1124         int rc;
1125
1126         if ( client == NULL )
1127         {
1128                 printk(KERN_ERR "%s Got NULL client\n", __func__ );
1129                 return -EINVAL;
1130         }
1131
1132         coredev = client->coredev;
1133
1134         // check that no other channel with same id exists
1135         if ( coredev == NULL )
1136         {
1137                 printk(KERN_ERR "%s Got NULL coredev\n", __func__ );
1138                 return -EINVAL;
1139         }
1140
1141         rc = smscore_validate_client(client->coredev, client, 0, phdr->msgSrcId);
1142         if (rc < 0)
1143                 return rc;
1144
1145         return coredev->sendrequest_handler(coredev->context, buffer, size);
1146 }
1147
1148 /**
1149  * return the size of large (common) buffer
1150  *
1151  * @param coredev pointer to a coredev object from clients hotplug
1152  *
1153  * @return size (in bytes) of the buffer
1154  */
1155 int smscore_get_common_buffer_size(smscore_device_t *coredev)
1156 {
1157         return coredev->common_buffer_size;
1158 }
1159
1160 /**
1161  * maps common buffer (if supported by platform)
1162  *
1163  * @param coredev pointer to a coredev object from clients hotplug
1164  * @param vma pointer to vma struct from mmap handler
1165  *
1166  * @return 0 on success, <0 on error.
1167  */
1168 int smscore_map_common_buffer(smscore_device_t *coredev,
1169                                struct vm_area_struct *vma)
1170 {
1171         unsigned long end = vma->vm_end, start = vma->vm_start, size = PAGE_ALIGN(coredev->common_buffer_size);
1172
1173         if (!(vma->vm_flags & (VM_READ | VM_SHARED)) || (vma->vm_flags & VM_WRITE))
1174         {
1175                 printk(KERN_INFO "%s invalid vm flags\n", __func__);
1176                 return -EINVAL;
1177         }
1178
1179         if ((end - start) != size)
1180         {
1181                 printk(KERN_INFO "%s invalid size %d expected %d\n", __func__, (int)(end - start), (int) size);
1182                 return -EINVAL;
1183         }
1184
1185         if (remap_pfn_range(vma, start, coredev->common_buffer_phys >> PAGE_SHIFT, size, pgprot_noncached(vma->vm_page_prot)))
1186         {
1187                 printk(KERN_INFO "%s remap_page_range failed\n", __func__);
1188                 return -EAGAIN;
1189         }
1190
1191         return 0;
1192 }
1193
1194 int smscore_module_init(void)
1195 {
1196         int rc = 0;
1197
1198         INIT_LIST_HEAD(&g_smscore_notifyees);
1199         INIT_LIST_HEAD(&g_smscore_devices);
1200         kmutex_init(&g_smscore_deviceslock);
1201
1202         INIT_LIST_HEAD(&g_smscore_registry);
1203         kmutex_init(&g_smscore_registrylock);
1204
1205         /* USB Register */
1206         rc = smsusb_register();
1207
1208         /* DVB Register */
1209         rc = smsdvb_register();
1210
1211         printk(KERN_INFO "%s, rc %d\n", __func__, rc);
1212
1213         return rc;
1214 }
1215
1216 void smscore_module_exit(void)
1217 {
1218
1219         kmutex_lock(&g_smscore_deviceslock);
1220         while (!list_empty(&g_smscore_notifyees))
1221         {
1222                 smscore_device_notifyee_t *notifyee = (smscore_device_notifyee_t *) g_smscore_notifyees.next;
1223
1224                 list_del(&notifyee->entry);
1225                 kfree(notifyee);
1226         }
1227         kmutex_unlock(&g_smscore_deviceslock);
1228
1229         kmutex_lock(&g_smscore_registrylock);
1230         while (!list_empty(&g_smscore_registry))
1231         {
1232                 smscore_registry_entry_t *entry = (smscore_registry_entry_t *) g_smscore_registry.next;
1233
1234                 list_del(&entry->entry);
1235                 kfree(entry);
1236         }
1237         kmutex_unlock(&g_smscore_registrylock);
1238
1239         /* DVB UnRegister */
1240         smsdvb_unregister();
1241
1242         /* Unregister USB */
1243         smsusb_unregister();
1244
1245         printk(KERN_INFO "%s\n", __func__);
1246 }
1247
1248 module_init(smscore_module_init);
1249 module_exit(smscore_module_exit);
1250
1251 MODULE_DESCRIPTION("smscore");
1252 MODULE_AUTHOR ( "Siano Mobile Silicon,,, (doronc@siano-ms.com)" );
1253 MODULE_LICENSE("GPL");
1254