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