52d8bc2788969e1e4f7ad9d3980a1724ec3cbf80
[firefly-linux-kernel-4.4.55.git] / drivers / cmmb / siano / smscoreapi.c
1 /****************************************************************
2
3  Siano Mobile Silicon, Inc.
4  MDTV receiver kernel modules.
5  Copyright (C) 2006-2008, Uri Shkolnik
6
7  This program is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 2 of the License, or
10  (at your option) any later version.
11
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  GNU General Public License for more details.
16
17  You should have received a copy of the GNU General Public License
18  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20  ****************************************************************/
21
22 #include <linux/kernel.h>
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/moduleparam.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/delay.h>
28 #include <linux/io.h>
29 #include <linux/uaccess.h>
30 #if SIANO_HALFDUPLEX
31 #include <asm/semaphore.h>
32 #endif
33 #include <linux/firmware.h>
34 #include <asm/byteorder.h>
35
36 #include "smscoreapi.h"
37 #include "smsendian.h"
38 #include "sms-cards.h"
39 #include <mach/gpio.h>
40
41 #define MAX_GPIO_PIN_NUMBER     31
42
43 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
44 //#define REQUEST_FIRMWARE_SUPPORTED
45 #undef REQUEST_FIRMWARE_SUPPORTED
46 //#define DEFAULT_FW_FILE_PATH "/opl/usr/firmware/"
47 #define DEFAULT_FW_FILE_PATH "/etc/firmware/"
48 #else
49 //#define DEFAULT_FW_FILE_PATH "/lib/firmware"
50 //#define DEFAULT_FW_FILE_PATH "/opl/usr/firmware/"
51 #define DEFAULT_FW_FILE_PATH "/etc/firmware/"
52 #endif
53
54 // to enable log
55 //int sms_debug =7;
56 int sms_debug =0;   //hzb 0526
57 // for loopback
58 char g_LbResBuf[256]={0};
59 //
60 volatile bool g_libdownload = false;
61 module_param_named(debug, sms_debug, int, 0644);
62 MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
63
64 //static int default_mode = 4;
65 static int default_mode = DEVICE_MODE_CMMB;
66
67 #if SIANO_HALFDUPLEX
68 extern int g_IsTokenEnable;
69 extern int g_IsTokenOwned;
70 extern struct semaphore         HalfDuplexSemaphore;
71 #endif
72
73 module_param(default_mode, int, 0644);
74 MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
75
76 struct smscore_device_notifyee_t {
77         struct list_head entry;
78         hotplug_t hotplug;
79 };
80
81 struct smscore_idlist_t {
82         struct list_head entry;
83         int id;
84         int data_type;
85 };
86
87 struct smscore_client_t {
88         struct list_head entry;
89         struct smscore_device_t *coredev;
90         void *context;
91         struct list_head idlist;
92         onresponse_t onresponse_handler;
93         onremove_t onremove_handler;
94 };
95
96 struct smscore_device_t {
97         struct list_head entry;
98
99         struct list_head clients;
100         struct list_head subclients;
101         spinlock_t clientslock;
102
103         struct list_head buffers;
104         spinlock_t bufferslock;
105         int num_buffers;
106
107         void *common_buffer;
108         int common_buffer_size;
109         dma_addr_t common_buffer_phys;
110
111         void *context;
112         struct device *device;
113
114         char devpath[32];
115         unsigned long device_flags;
116
117         setmode_t setmode_handler;
118         detectmode_t detectmode_handler;
119         sendrequest_t sendrequest_handler;
120         preload_t preload_handler;
121         postload_t postload_handler;
122
123         int mode, modes_supported;
124
125         struct completion version_ex_done, data_download_done, trigger_done;
126         struct completion init_device_done, reload_start_done, resume_done;
127         struct completion gpio_configuration_done, gpio_set_level_done;
128         struct completion gpio_get_level_done;
129 // for loopback         
130         struct completion loopback_res_done;
131 // for loopback
132         int gpio_get_res;
133
134         int board_id;
135
136         u8 *fw_buf;
137         u32 fw_buf_size;
138
139         wait_queue_head_t buffer_mng_waitq;
140 };
141
142
143
144
145
146 static struct smscore_device_t* panic_core_dev = NULL ;
147
148 void smscore_panic_print(void)
149 {
150     if(panic_core_dev)
151     {
152         printk("common_buffer_size  = [0x%x]\n", panic_core_dev-> common_buffer_size) ;
153         printk("common_buffer start addr= [0x%x]\n",(unsigned int) panic_core_dev->common_buffer ) ;
154         printk("common_buffer end  addr= [0x%x]\n",
155                    (unsigned int) (panic_core_dev->common_buffer + panic_core_dev-> common_buffer_size -1)) ;
156         printk("common_buffer_phys start addr = [0x%x]\n",(unsigned int) panic_core_dev->common_buffer_phys) ;
157         printk("common_buffer_phys end addr = [0x%x]\n",
158                   (unsigned int)  ( panic_core_dev->common_buffer_phys+ panic_core_dev-> common_buffer_size -1)) ;
159     }
160 }
161
162 // 
163 // for loopback
164
165 int  AdrLoopbackTest( struct smscore_device_t *coredev );
166
167 void smscore_set_board_id(struct smscore_device_t *core, int id)
168 {
169         core->board_id = id;
170 }
171
172 int smscore_get_board_id(struct smscore_device_t *core)
173 {
174         return core->board_id;
175 }
176
177 struct smscore_registry_entry_t {
178         struct list_head entry;
179         char devpath[32];
180         int mode;
181         enum sms_device_type_st type;
182 };
183
184 static struct list_head g_smscore_notifyees;
185 static struct list_head g_smscore_devices;
186 static struct mutex g_smscore_deviceslock;
187 static struct list_head g_smscore_registry;
188 static struct mutex g_smscore_registrylock;
189
190 static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
191 {
192         struct smscore_registry_entry_t *entry;
193         struct list_head *next;
194
195         kmutex_lock(&g_smscore_registrylock);
196         for (next = g_smscore_registry.next; next != &g_smscore_registry; next
197                         = next->next) {
198                 entry = (struct smscore_registry_entry_t *) next;
199                 if (!strcmp(entry->devpath, devpath)) {
200                         kmutex_unlock(&g_smscore_registrylock);
201                         return entry;
202                 }
203         }
204         entry = /* (struct smscore_registry_entry_t *) */kmalloc(
205                         sizeof(struct smscore_registry_entry_t), GFP_KERNEL);
206         if (entry) {
207                 entry->mode = default_mode;
208                 if(strlen(devpath) >= 32)
209                 {
210                         sms_err(" strlen(devpath) >= 32\n");
211                         return NULL;
212                 }
213                 strcpy(entry->devpath, devpath);
214                 list_add(&entry->entry, &g_smscore_registry);
215         } else
216                 sms_err("failed to create smscore_registry.");
217         kmutex_unlock(&g_smscore_registrylock);
218         return entry;
219 }
220
221 int smscore_registry_getmode(char *devpath)
222 {
223         struct smscore_registry_entry_t *entry;
224
225         entry = smscore_find_registry(devpath);
226         if (entry)
227                 return entry->mode;
228         else
229                 sms_err("No registry found.");
230
231         return default_mode;
232 }
233
234 static enum sms_device_type_st smscore_registry_gettype(char *devpath)
235 {
236         struct smscore_registry_entry_t *entry;
237
238         entry = smscore_find_registry(devpath);
239         if (entry)
240                 return entry->type;
241         else
242                 sms_err("No registry found.");
243
244         return -1;
245 }
246
247 void smscore_registry_setmode(char *devpath, int mode)
248 {
249         struct smscore_registry_entry_t *entry;
250
251         entry = smscore_find_registry(devpath);
252         if (entry)
253                 entry->mode = mode;
254         else
255                 sms_err("No registry found.");
256 }
257
258 static void smscore_registry_settype(char *devpath,
259                 enum sms_device_type_st type) {
260         struct smscore_registry_entry_t *entry;
261
262         entry = smscore_find_registry(devpath);
263         if (entry)
264                 entry->type = type;
265         else
266                 sms_err("No registry found.");
267 }
268
269 static void list_add_locked(struct list_head *new, struct list_head *head,
270                 spinlock_t *lock) {
271         unsigned long flags;
272
273         spin_lock_irqsave(lock, flags);
274         list_add(new, head);
275         spin_unlock_irqrestore(lock, flags);
276 }
277
278 /**
279  * register a client callback that called when device plugged in/unplugged
280  * NOTE: if devices exist callback is called immediately for each device
281  *
282  * @param hotplug callback
283  *
284  * @return 0 on success, <0 on error.
285  */
286 int smscore_register_hotplug(hotplug_t hotplug)
287 {
288         struct smscore_device_notifyee_t *notifyee;
289         struct list_head *next, *first;
290         int rc = 0;
291
292         sms_info(" entering... smscore_register_hotplug \n");
293         kmutex_lock(&g_smscore_deviceslock);
294
295         notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
296                 GFP_KERNEL);
297         if (notifyee) {
298                 /* now notify callback about existing devices */
299                 first = &g_smscore_devices;
300                 for (next = first->next; next != first && !rc;
301                         next = next->next) {
302                         struct smscore_device_t *coredev =
303                                 (struct smscore_device_t *) next;
304                         rc = hotplug(coredev, coredev->device, 1);
305                 }
306
307                 if (rc >= 0) {
308                         notifyee->hotplug = hotplug;
309                         list_add(&notifyee->entry, &g_smscore_notifyees);
310                 } else
311                         kfree(notifyee);
312         } else
313                 rc = -ENOMEM;
314
315         kmutex_unlock(&g_smscore_deviceslock);
316
317         return rc;
318 }
319
320 /**
321  * unregister a client callback that called when device plugged in/unplugged
322  *
323  * @param hotplug callback
324  *
325  */
326 void smscore_unregister_hotplug(hotplug_t hotplug)
327 {
328         struct list_head *next, *first;
329
330         kmutex_lock(&g_smscore_deviceslock);
331
332         first = &g_smscore_notifyees;
333
334         for (next = first->next; next != first;) {
335                 struct smscore_device_notifyee_t *notifyee =
336                                 (struct smscore_device_notifyee_t *) next;
337                 next = next->next;
338
339                 if (notifyee->hotplug == hotplug) {
340                         list_del(&notifyee->entry);
341                         kfree(notifyee);
342                 }
343         }
344
345         kmutex_unlock(&g_smscore_deviceslock);
346 }
347
348 static void smscore_notify_clients(struct smscore_device_t *coredev)
349 {
350         struct smscore_client_t *client;
351
352         /* the client must call smscore_unregister_client from remove handler */
353         while (!list_empty(&coredev->clients)) {
354                 client = (struct smscore_client_t *) coredev->clients.next;
355                 client->onremove_handler(client->context);
356         }
357 }
358
359 static int smscore_notify_callbacks(struct smscore_device_t *coredev,
360                 struct device *device, int arrival) {
361         struct list_head *next, *first;
362         int rc = 0;
363
364         /* note: must be called under g_deviceslock */
365
366         first = &g_smscore_notifyees;
367
368         for (next = first->next; next != first; next = next->next) {
369                 rc = ((struct smscore_device_notifyee_t *) next)->
370                          hotplug(coredev, device, arrival);
371                 if (rc < 0)
372                         break;
373         }
374
375         return rc;
376 }
377
378 static struct smscore_buffer_t *smscore_createbuffer(u8 *buffer,
379                 void *common_buffer, dma_addr_t common_buffer_phys) {
380         struct smscore_buffer_t *cb = kmalloc(sizeof(struct smscore_buffer_t),
381                         GFP_KERNEL);
382         if (!cb) {
383                 sms_info("kmalloc(...) failed");
384                 return NULL;
385         }
386
387         cb->p = buffer;
388         cb->offset_in_common = buffer - (u8 *) common_buffer;
389         cb->phys = common_buffer_phys + cb->offset_in_common;
390
391         return cb;
392 }
393
394 /**
395  * creates coredev object for a device, prepares buffers,
396  * creates buffer mappings, notifies registered hotplugs about new device.
397  *
398  * @param params device pointer to struct with device specific parameters
399  *               and handlers
400  * @param coredev pointer to a value that receives created coredev object
401  *
402  * @return 0 on success, <0 on error.
403  */
404 int smscore_register_device(struct smsdevice_params_t *params,
405                 struct smscore_device_t **coredev) {
406         struct smscore_device_t *dev;
407         u8 *buffer;
408
409         sms_info(" entering....smscore_register_device \n");
410         dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
411         if (!dev) {
412                 sms_info("kzalloc(...) failed");
413                 return -ENOMEM;
414         }
415
416         /* init list entry so it could be safe in smscore_unregister_device */
417         INIT_LIST_HEAD(&dev->entry);
418
419         /* init queues */
420         INIT_LIST_HEAD(&dev->clients);
421         INIT_LIST_HEAD(&dev->buffers);
422
423         /* init locks */
424         spin_lock_init(&dev->clientslock);
425         spin_lock_init(&dev->bufferslock);
426
427         /* init completion events */
428         init_completion(&dev->version_ex_done);
429         init_completion(&dev->data_download_done);
430         init_completion(&dev->trigger_done);
431         init_completion(&dev->init_device_done);
432         init_completion(&dev->reload_start_done);
433         init_completion(&dev->resume_done);
434         init_completion(&dev->gpio_configuration_done);
435         init_completion(&dev->gpio_set_level_done);
436         init_completion(&dev->gpio_get_level_done);
437     // for loopback test
438     init_completion(&dev->loopback_res_done);
439         init_waitqueue_head(&dev->buffer_mng_waitq);
440
441         /* alloc common buffer */
442         sms_info(" entering...alloc common buffer \n");
443         dev->common_buffer_size = params->buffer_size * params->num_buffers;
444 #if 0    
445     dev->common_buffer = kmalloc(dev->common_buffer_size, GFP_KERNEL|GFP_DMA);
446     dev->common_buffer_phys =  __pa(dev->common_buffer);
447     sms_debug("dev->common_buffer_phys=0x%x",dev->common_buffer_phys);
448 #else
449         dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
450                         &dev->common_buffer_phys, GFP_KERNEL | GFP_DMA);
451 #endif
452
453         if (!dev->common_buffer) {
454                 smscore_unregister_device(dev);
455                 return -ENOMEM;
456         }
457
458
459         /* prepare dma buffers */
460         sms_info(" entering...prepare dma buffers \n");
461
462
463         for (buffer = dev->common_buffer ; dev->num_buffers <
464                         params->num_buffers ; dev->num_buffers++, buffer
465                         += params->buffer_size) {
466                 struct smscore_buffer_t *cb = smscore_createbuffer(buffer,
467                                 dev->common_buffer, dev->common_buffer_phys);
468                 if (!cb) {
469                         smscore_unregister_device(dev);
470                         return -ENOMEM;
471                 }
472
473                 smscore_putbuffer(dev, cb);
474         }
475
476         sms_info("allocated %d buffers", dev->num_buffers);
477
478         dev->mode = DEVICE_MODE_NONE;
479         dev->context = params->context;
480         dev->device = params->device;
481         dev->setmode_handler = params->setmode_handler;
482         dev->detectmode_handler = params->detectmode_handler;
483         dev->sendrequest_handler = params->sendrequest_handler;
484         dev->preload_handler = params->preload_handler;
485         dev->postload_handler = params->postload_handler;
486
487         dev->device_flags = params->flags;
488         strcpy(dev->devpath, params->devpath);
489
490         smscore_registry_settype(dev->devpath, params->device_type);
491
492         /* add device to devices list */
493         kmutex_lock(&g_smscore_deviceslock);
494         list_add(&dev->entry, &g_smscore_devices);
495         kmutex_unlock(&g_smscore_deviceslock);
496
497         *coredev = dev;
498         panic_core_dev = dev ;
499         sms_info("device %p created", dev);
500
501         return 0;
502 }
503
504 /**
505  * sets initial device mode and notifies client hotplugs that device is ready
506  *
507  * @param coredev pointer to a coredev object returned by
508  *                smscore_register_device
509  *
510  * @return 0 on success, <0 on error.
511  */
512 int smscore_start_device(struct smscore_device_t *coredev)
513 {
514         int rc;
515
516 #ifdef REQUEST_FIRMWARE_SUPPORTED
517         rc = smscore_set_device_mode(coredev, smscore_registry_getmode(
518                         coredev->devpath));
519         if (rc < 0) {
520                 sms_info("set device mode faile , rc %d", rc);
521                 return rc;
522         }
523 #endif
524
525         kmutex_lock(&g_smscore_deviceslock);
526
527         rc = smscore_notify_callbacks(coredev, coredev->device, 1);
528
529         sms_info("device %p started, rc %d", coredev, rc);
530
531         kmutex_unlock(&g_smscore_deviceslock);
532
533         return rc;
534 }
535
536 static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
537                 void *buffer, size_t size, struct completion *completion) {
538         int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
539         if (rc < 0) {
540                 sms_info("sendrequest returned error %d", rc);
541                 return rc;
542         }
543
544         return wait_for_completion_timeout(completion,
545                         msecs_to_jiffies(30000)) ? 0 : -ETIME;//10000
546 }
547
548 static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
549                 void *buffer, size_t size) {
550         struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;
551         struct SmsMsgHdr_ST *msg;
552         u32 mem_address;
553         u8 *payload = firmware->Payload;
554         int rc = 0;
555
556         firmware->StartAddress = le32_to_cpu(firmware->StartAddress);
557         firmware->Length = le32_to_cpu(firmware->Length);
558
559         mem_address = firmware->StartAddress;
560     
561     sms_info("loading FW to addr 0x%x size %d",
562             mem_address, firmware->Length);
563     if (coredev->preload_handler) {
564         rc = coredev->preload_handler(coredev->context);
565         if (rc < 0)
566         {
567            sms_err("sms preload handler fail !!!");      
568            return rc;
569         }
570     }
571
572     sms_info("preload handle after");
573
574
575         /* PAGE_SIZE buffer shall be enough and dma aligned */
576         msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
577         if (!msg)
578                 return -ENOMEM;
579     
580     //while (1)//hzb test 0527
581     {
582
583         //if (coredev->mode != DEVICE_MODE_NONE) //hzb test 0527
584         {
585                 sms_info("sending MSG_SMS_GET_VERSION_EX_REQ command.");
586                 SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
587                                 sizeof(struct SmsMsgHdr_ST));
588                 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)msg);
589                 rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
590                                 &coredev->version_ex_done);
591     //          mem_address = *(u32 *) &payload[20];
592                 sms_info("sms get version req ret=0x%x",rc);
593                 //mdelay(5);
594         }
595     }//hzb test 0527
596    // msleep(200);
597     g_libdownload = true;
598         
599         //      msleep(200);
600         while (size && rc >= 0) {
601                 struct SmsDataDownload_ST *DataMsg =
602                                 (struct SmsDataDownload_ST *) msg;
603                 int payload_size = min((int)size, SMS_MAX_PAYLOAD_SIZE);
604
605                 SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,
606                                 (u16) (sizeof(struct SmsMsgHdr_ST) +
607                                                 sizeof(u32) + payload_size));
608
609                 DataMsg->MemAddr = mem_address;
610                 memcpy(DataMsg->Payload, payload, payload_size);
611
612                 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)msg);
613                 if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&
614                                 (coredev->mode  == DEVICE_MODE_NONE))
615                         rc = coredev->sendrequest_handler(coredev->context,DataMsg,DataMsg->xMsgHeader.msgLength);
616                 else
617                         {
618                         
619 //                      complete(&coredev->data_download_done);
620 //                      msleep(200);
621 //                      g_libdownload = false;
622                         
623 //                      msleep(200);
624                         rc = smscore_sendrequest_and_wait(coredev, DataMsg,DataMsg->xMsgHeader.msgLength,&coredev->data_download_done);
625                         }
626                 payload += payload_size;
627                 size -= payload_size;
628                 mem_address += payload_size;
629
630                 sms_debug("size=%d \n", size);
631         }
632         
633         sms_info("transfer over!!!!!!!!!!!!!!!!!!\n");
634
635         
636         complete(&coredev->data_download_done);
637         //msleep(200);
638         g_libdownload = false;
639 //      msleep(200);
640 // Â¼Ã“ÈëÑÓʱ£¬·ÀÖ¹³õʼ»¯Ê§°Ü£¬ZYC
641         msleep(2000);
642 //printk("firmware is downloaded\n!!!!");
643 //msleep(1000);
644         if (rc >= 0) {
645                 sms_info("firmware is loaded over 1111111111\n");
646                 if (coredev->mode == DEVICE_MODE_NONE) {
647                         struct SmsMsgData_ST *TriggerMsg =
648                                         (struct SmsMsgData_ST *) msg;
649
650                         SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
651                                         sizeof(struct SmsMsgHdr_ST) +
652                                         sizeof(u32) * 5);
653
654                         TriggerMsg->msgData[0] = firmware->StartAddress;
655                         /* Entry point */
656                         TriggerMsg->msgData[1] = 5; /* Priority */
657                         TriggerMsg->msgData[2] = 0x200; /* Stack size */
658                         TriggerMsg->msgData[3] = 0; /* Parameter */
659                         TriggerMsg->msgData[4] = 4; /* Task ID */
660
661                         smsendian_handle_tx_message((struct SmsMsgHdr_ST *)msg);
662                         if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {
663                                 
664                                 sms_info("firmware is loaded over , but no response,222222222\n");
665                                 rc = coredev->sendrequest_handler(coredev->
666                                         context, TriggerMsg,
667                                         TriggerMsg->xMsgHeader.msgLength);
668                                 msleep(300);
669                         } else
670                                 rc = smscore_sendrequest_and_wait(coredev,
671                                         TriggerMsg,
672                                         TriggerMsg->xMsgHeader.msgLength,
673                                         &coredev->trigger_done);
674                 } else {
675                         sms_info("firmware is loaded over , but mode is none,333333333333\n");
676
677                         SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,
678                                         sizeof(struct SmsMsgHdr_ST));
679                         smsendian_handle_tx_message((struct SmsMsgHdr_ST *)msg);
680                         rc = coredev->sendrequest_handler(coredev->context, msg,
681                                         msg->msgLength);
682                 }
683                 msleep(500);
684         }
685
686         else
687                 sms_info("firmware is not loaded over , it is wrong,4444444444444\n");
688                 
689         sms_debug("rc=%d, postload=%p ", rc, coredev->postload_handler);
690
691         kfree(msg);
692
693         return ((rc >= 0) && coredev->postload_handler) ?
694                         coredev->postload_handler(coredev->context) : rc;
695 }
696
697 /**
698  * loads specified firmware into a buffer and calls device loadfirmware_handler
699  *
700  * @param coredev pointer to a coredev object returned by
701  *                smscore_register_device
702  * @param filename null-terminated string specifies firmware file name
703  * @param loadfirmware_handler device handler that loads firmware
704  *
705  * @return 0 on success, <0 on error.
706  */
707 static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
708                 char *filename, loadfirmware_t loadfirmware_handler) {
709         int rc = -ENOENT;
710         u8 *fw_buf;
711         u32 fw_buf_size;
712
713 #ifdef REQUEST_FIRMWARE_SUPPORTED
714         const struct firmware *fw;
715
716         if (loadfirmware_handler == NULL && !(coredev->device_flags
717                         & SMS_DEVICE_FAMILY2))
718                 return -EINVAL;
719
720         rc = request_firmware(&fw, filename, coredev->device);
721         if (rc < 0) {
722                 sms_info("failed to open \"%s\"", filename);
723                 return rc;
724         }
725         sms_info("read FW %s, size=%zd", filename, fw->size);
726         fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
727                                 GFP_KERNEL | GFP_DMA);
728         if (!fw_buf) {
729                 sms_info("failed to allocate firmware buffer");
730                 return -ENOMEM;
731         }
732         memcpy(fw_buf, fw->data, fw->size);
733         fw_buf_size = fw->size;
734 #else
735         if (!coredev->fw_buf) {
736                 sms_info("missing fw file buffer");
737                 return -EINVAL;
738         }
739         fw_buf = coredev->fw_buf;
740         fw_buf_size = coredev->fw_buf_size;
741 #endif
742         rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
743                 smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
744                 : /*loadfirmware_handler(coredev->context, fw_buf,
745                 fw_buf_size);*/printk(" error - should not be here\n");
746         kfree(fw_buf);
747
748 #ifdef REQUEST_FIRMWARE_SUPPORTED
749         release_firmware(fw);
750 #else
751         coredev->fw_buf = NULL;
752         coredev->fw_buf_size = 0;
753 #endif
754         return rc;
755 }
756
757 /**
758  * notifies all clients registered with the device, notifies hotplugs,
759  * frees all buffers and coredev object
760  *
761  * @param coredev pointer to a coredev object returned by
762  *                smscore_register_device
763  *
764  * @return 0 on success, <0 on error.
765  */
766 void smscore_unregister_device(struct smscore_device_t *coredev)
767 {
768         struct smscore_buffer_t *cb;
769         int num_buffers = 0;
770         int retry = 0;
771
772         kmutex_lock(&g_smscore_deviceslock);
773
774         smscore_notify_clients(coredev);
775         smscore_notify_callbacks(coredev, NULL, 0);
776
777         /* at this point all buffers should be back
778          * onresponse must no longer be called */
779
780         while (1) {
781                 while(!list_empty(&coredev->buffers))
782                 {
783                         cb = (struct smscore_buffer_t *) coredev->buffers.next;
784                         list_del(&cb->entry);
785                         kfree(cb);
786                         num_buffers++;
787                 }
788                 if (num_buffers == coredev->num_buffers ) 
789                         break;
790                 if (++retry > 10) {
791                         sms_info("exiting although "
792                                         "not all buffers released.");
793                         break;
794                 }
795
796                 sms_info("waiting for %d buffer(s)",
797                                 coredev->num_buffers - num_buffers);
798                 msleep(300);
799         }
800
801         sms_info("freed %d buffers", num_buffers);
802
803     if(coredev->common_buffer)
804     {
805 #if 0   //spi kmalloc
806         kfree(coredev->common_buffer);
807 #else
808                 dma_free_coherent(NULL, coredev->common_buffer_size,coredev->common_buffer, coredev->common_buffer_phys); 
809 #endif                  
810     }
811         if (coredev->fw_buf != NULL)
812                 kfree(coredev->fw_buf);
813         
814         list_del(&coredev->entry);
815         kfree(coredev);
816     panic_core_dev = NULL ;
817         kmutex_unlock(&g_smscore_deviceslock);
818
819         sms_info("device %p destroyed", coredev);
820 }
821
822 static int smscore_detect_mode(struct smscore_device_t *coredev)
823 {
824         void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,
825                         GFP_KERNEL | GFP_DMA);
826         struct SmsMsgHdr_ST *msg =
827                         (struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
828         int rc;
829
830         if (!buffer)
831                 return -ENOMEM;
832
833         SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
834                         sizeof(struct SmsMsgHdr_ST));
835
836         smsendian_handle_tx_message((struct SmsMsgHdr_ST *)msg);
837         rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,
838                         &coredev->version_ex_done);
839         if (rc == -ETIME) {
840                 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
841
842                 if (wait_for_completion_timeout(&coredev->resume_done,
843                                 msecs_to_jiffies(5000))) {
844                         rc = smscore_sendrequest_and_wait(coredev, msg,
845                                 msg->msgLength, &coredev->version_ex_done);
846                         if (rc < 0)
847                                 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
848                                                 "second try, rc %d", rc);
849                 } else
850                         rc = -ETIME;
851         }
852
853         kfree(buffer);
854
855         return rc;
856 }
857
858 static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {
859 /*Stellar               NOVA A0         Nova B0         VEGA */
860 /*DVBT*/
861 { "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none" },
862 /*DVBH*/
863 { "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none" },
864 /*TDMB*/
865 { "none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none" },
866 /*DABIP*/{ "none", "none", "none", "none" },
867 /*BDA*/
868 { "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none" },
869 /*ISDBT*/
870 { "none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none" },
871 /*ISDBTBDA*/
872 { "none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none" },
873 /*CMMB*/{ "none", "none", "none", "cmmb_vega_12mhz.inp" } };
874
875 static inline char *sms_get_fw_name(struct smscore_device_t *coredev, int mode,
876                 enum sms_device_type_st type) {
877         char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;
878         return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];
879 }
880
881
882 int smscore_reset_device_drvs(struct smscore_device_t *coredev)
883
884 {
885         int rc = 0;
886         sms_debug("currnet  device mode to %d", coredev->mode);
887                 coredev->mode = DEVICE_MODE_NONE;
888                 coredev->device_flags =                     SMS_DEVICE_FAMILY2 | SMS_DEVICE_NOT_READY |
889                     SMS_ROM_NO_RESPONSE;
890                 
891    return rc;
892 }
893
894
895 /**
896  * calls device handler to change mode of operation
897  * NOTE: stellar/usb may disconnect when changing mode
898  *
899  * @param coredev pointer to a coredev object returned by
900  *                smscore_register_device
901  * @param mode requested mode of operation
902  *
903  * @return 0 on success, <0 on error.
904  */
905 int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
906 {
907         void *buffer;
908         int rc = 0;
909         enum sms_device_type_st type;
910
911
912         sms_info("set device mode to %d", mode);
913     //sms_debug("current device mode, device flags, modes_supported  to %d", coredev->mode, coredev->device_flags, coredev->modes_supported);
914
915         sms_debug("set device mode to %d", mode);
916         if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
917                 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) {
918                         sms_err("invalid mode specified %d", mode);
919                         return -EINVAL;
920                 }
921
922                 smscore_registry_setmode(coredev->devpath, mode);
923
924                 if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
925                         rc = smscore_detect_mode(coredev);
926                         if (rc < 0) {
927                                 sms_err("mode detect failed %d", rc);
928                                 return rc;
929                         }
930                 }
931
932                 if (coredev->mode == mode) {
933                         sms_info("device mode %d already set", mode);
934                         return 0;
935                 }
936
937                 if (!(coredev->modes_supported & (1 << mode))) {
938                         char *fw_filename;
939
940                         type = smscore_registry_gettype(coredev->devpath);
941                         fw_filename = sms_get_fw_name(coredev, mode, type);
942
943                         if(NULL == fw_filename)
944                         {
945                                 sms_err("wrong filename");
946                                 return rc;
947                         }
948
949                         rc = smscore_load_firmware_from_file(coredev,
950                                         fw_filename, NULL);
951                         if (rc < 0) {
952                                 sms_warn("error %d loading firmware: %s, "
953                                         "trying again with default firmware",
954                                         rc, fw_filename);
955
956                                 /* try again with the default firmware */
957                                 fw_filename = smscore_fw_lkup[mode][type];
958                                 rc = smscore_load_firmware_from_file(coredev,
959                                                 fw_filename, NULL);
960
961                                 if (rc < 0) {
962                                         sms_warn("error %d loading "
963                                                         "firmware: %s", rc,
964                                                         fw_filename);
965                                         return rc;
966                                 }
967                         }
968                         sms_info("firmware download success: %s", fw_filename);
969                 } else
970                 sms_info("mode %d supported by running "
971                                         "firmware", mode);
972
973                 buffer = kmalloc(sizeof(struct SmsMsgData_ST) +
974                                 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
975                 if (buffer) {
976                         struct SmsMsgData_ST *msg =
977                                         (struct SmsMsgData_ST *)
978                                         SMS_ALIGN_ADDRESS(buffer);
979
980                         SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,
981                                         sizeof(struct SmsMsgData_ST));
982                         msg->msgData[0] = mode;
983                         //for test,zyc
984                         msleep(200);
985                         
986                         smsendian_handle_tx_message((struct SmsMsgHdr_ST *)msg);
987                         rc = smscore_sendrequest_and_wait(coredev, msg,
988                                         msg->xMsgHeader.msgLength,
989                                         &coredev->init_device_done);
990                         sms_info("send MSG_SMS_INIT_DEVICE_REQ res = %d\n ",rc);
991                         kfree(buffer);
992                 } else {
993                         sms_err("Could not allocate buffer for "
994                                         "init device message.");
995                         rc = -ENOMEM;
996                 }
997
998                 // start to do loopback test
999         // rc = AdrLoopbackTest(coredev);
1000                 //
1001
1002         } else {
1003                 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {
1004                         sms_err("invalid mode specified %d", mode);
1005                         return -EINVAL;
1006                 }
1007
1008                 smscore_registry_setmode(coredev->devpath, mode);
1009
1010                 if (coredev->detectmode_handler)
1011                         coredev->detectmode_handler(coredev->context,
1012                                         &coredev->mode);
1013
1014                 if (coredev->mode != mode && coredev->setmode_handler)
1015                         rc = coredev->setmode_handler(coredev->context, mode);
1016         }
1017
1018         if (rc >= 0) {
1019                 sms_info("device is ready");
1020                 {
1021                         struct SmsMsgHdr_ST *msg;
1022                         
1023                         msg = kmalloc(sizeof(struct SmsMsgHdr_ST), GFP_KERNEL | GFP_DMA);
1024                         
1025                         sms_debug("sending MSG_SMS_GET_VERSION_EX_REQ command.");
1026                         SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,sizeof(struct SmsMsgHdr_ST));
1027                         smsendian_handle_tx_message((struct SmsMsgHdr_ST *)msg);
1028                         rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength, &coredev->version_ex_done);   
1029                         kfree(msg);
1030                 }       
1031 #if SIANO_HALFDUPLEX
1032                g_IsTokenEnable = true;
1033                 g_IsTokenOwned = true;
1034                 up(&HalfDuplexSemaphore);
1035                 sms_debug("g_IsTokenEnable = true  \n");
1036 #endif          
1037                 coredev->mode = mode;
1038                 coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
1039         }
1040
1041         if (rc < 0)
1042                 sms_err("return error code %d.", rc);
1043         return rc;
1044 }
1045
1046 /**
1047  * calls device handler to get fw file name
1048  *
1049  * @param coredev pointer to a coredev object returned by
1050  *                smscore_register_device
1051  * @param filename pointer to user buffer to fill the file name
1052  *
1053  * @return 0 on success, <0 on error.
1054  */
1055 int smscore_get_fw_filename(struct smscore_device_t *coredev, int mode,
1056                 char *filename) {
1057         int rc = 0;
1058         enum sms_device_type_st type;
1059         char tmpname[200];
1060
1061         type = smscore_registry_gettype(coredev->devpath);
1062
1063 #ifdef REQUEST_FIRMWARE_SUPPORTED
1064         /* driver not need file system services */
1065         tmpname[0] = '\0';
1066 #else
1067         sprintf(tmpname, "%s/%s", DEFAULT_FW_FILE_PATH,
1068                         smscore_fw_lkup[mode][type]);
1069 #endif
1070         if (copy_to_user(filename, tmpname, strlen(tmpname) + 1)) {
1071                 sms_err("Failed copy file path to user buffer\n");
1072                 return -EFAULT;
1073         }
1074         return rc;
1075 }
1076
1077 /**
1078  * calls device handler to keep fw buff for later use
1079  *
1080  * @param coredev pointer to a coredev object returned by
1081  *                smscore_register_device
1082  * @param ufwbuf  pointer to user fw buffer
1083  * @param size    size in bytes of buffer
1084  *
1085  * @return 0 on success, <0 on error.
1086  */
1087 int smscore_send_fw_file(struct smscore_device_t *coredev, u8 *ufwbuf,
1088                 int size) {
1089         int rc = 0;
1090
1091         /* free old buffer */
1092         if (coredev->fw_buf != NULL) {
1093                 kfree(coredev->fw_buf);
1094                 coredev->fw_buf = NULL;
1095         }
1096
1097         coredev->fw_buf = kmalloc(ALIGN(size, SMS_ALLOC_ALIGNMENT), GFP_KERNEL | GFP_DMA);
1098         if (!coredev->fw_buf) {
1099                 sms_err("Failed allocate FW buffer memory\n");
1100                 return -EFAULT;
1101         }
1102
1103         if (copy_from_user(coredev->fw_buf, ufwbuf, size)) {
1104                 sms_err("Failed copy FW from user buffer\n");
1105                 kfree(coredev->fw_buf);
1106                 return -EFAULT;
1107         }
1108         coredev->fw_buf_size = size;
1109
1110         return rc;
1111 }
1112
1113 /**
1114  * calls device handler to get current mode of operation
1115  *
1116  * @param coredev pointer to a coredev object returned by
1117  *                smscore_register_device
1118  *
1119  * @return current mode
1120  */
1121 int smscore_get_device_mode(struct smscore_device_t *coredev)
1122 {
1123         return coredev->mode;
1124 }
1125
1126 /**
1127  * find client by response id & type within the clients list.
1128  * return client handle or NULL.
1129  *
1130  * @param coredev pointer to a coredev object returned by
1131  *                smscore_register_device
1132  * @param data_type client data type (SMS_DONT_CARE for all types)
1133  * @param id client id (SMS_DONT_CARE for all id)
1134  *
1135  */
1136 static struct smscore_client_t *smscore_find_client(
1137                 struct smscore_device_t *coredev, int data_type, int id) {
1138         struct smscore_client_t *client = NULL;
1139         struct list_head *next, *first;
1140         unsigned long flags;
1141         struct list_head *firstid, *nextid;
1142
1143         spin_lock_irqsave(&coredev->clientslock, flags);
1144         first = &coredev->clients;
1145         for (next = first->next; (next != first) && !client;
1146                         next = next->next) {
1147                 firstid = &((struct smscore_client_t *) next)->idlist;
1148                 for (nextid = firstid->next; nextid != firstid;
1149                                 nextid = nextid->next) {
1150                         if ((((struct smscore_idlist_t *) nextid)->id == id)
1151                                         && (((struct smscore_idlist_t *)
1152                                                  nextid)->data_type
1153                                                 == data_type
1154                                                 || (((struct smscore_idlist_t *)
1155                                                 nextid)->data_type == 0))) {
1156                                 client = (struct smscore_client_t *) next;
1157                                 break;
1158                         }
1159                 }
1160         }
1161         spin_unlock_irqrestore(&coredev->clientslock, flags);
1162         return client;
1163 }
1164
1165 /**
1166  * find client by response id/type, call clients onresponse handler
1167  * return buffer to pool on error
1168  *
1169  * @param coredev pointer to a coredev object returned by
1170  *                smscore_register_device
1171  * @param cb pointer to response buffer descriptor
1172  *
1173  */
1174 void smscore_onresponse(struct smscore_device_t *coredev,
1175                 struct smscore_buffer_t *cb) {
1176         struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p
1177                         + cb->offset);
1178         struct smscore_client_t *client = smscore_find_client(coredev,
1179                         phdr->msgType, phdr->msgDstId);
1180         int rc = -EBUSY;
1181
1182         static unsigned long last_sample_time; /* = 0; */
1183         static int data_total; /* = 0; */
1184         unsigned long time_now = jiffies_to_msecs(jiffies);
1185
1186         if (!last_sample_time)
1187                 last_sample_time = time_now;
1188
1189         if (time_now - last_sample_time > 10000) {
1190                 sms_debug("\ndata rate %d bytes/secs",
1191                                 (int)((data_total * 1000) /
1192                                                 (time_now - last_sample_time)));
1193
1194                 last_sample_time = time_now;
1195                 data_total = 0;
1196         }
1197         
1198   
1199         data_total += cb->size;
1200         /* If no client registered for type & id,
1201          * check for control client where type is not registered */
1202          
1203         if (client)
1204         {
1205                 sms_debug("client=0x %x\n", client);
1206                 rc = client->onresponse_handler(client->context, cb);
1207         }       
1208         sms_debug("onresponse_handler ret = 0x%x\n", rc);
1209         sms_debug("phdr->msgType %d\n", phdr->msgType);
1210 #if SIANO_HALFDUPLEX
1211         if (phdr->msgType==MSG_SMS_SPI_HALFDUPLEX_TOKEN_DEVICE_TO_HOST){
1212                 g_IsTokenOwned = true;
1213                 sms_debug("MSG_SMS_SPI_HALFDUPLEX_TOKEN_DEVICE_TO_HOST \n");
1214                 return;
1215         }
1216 #endif
1217         if (rc < 0){
1218                 smsendian_handle_rx_message((struct SmsMsgData_ST *)phdr);
1219
1220                 switch (phdr->msgType) {
1221                 case MSG_SMS_GET_VERSION_EX_RES: {
1222                         struct SmsVersionRes_ST *ver = (struct SmsVersionRes_ST *) phdr;
1223             
1224                         sms_debug("MSG_SMS_GET_VERSION_EX_RES "
1225                                         "id %d prots 0x%x ver %d.%d",
1226                                         ver->FirmwareId,
1227                                         ver->SupportedProtocols,
1228                                         ver->RomVersionMajor,
1229                                         ver->RomVersionMinor);
1230                         
1231                         printk("MSG_SMS_GET_VERSION_EX_RES "
1232                                         "id %d prots 0x%x ver %d.%d\n",
1233                                         ver->FirmwareId,
1234                                         ver->SupportedProtocols,
1235                                         ver->RomVersionMajor,
1236                                         ver->RomVersionMinor);
1237                         
1238                         ver->TextLabel[33] = 0x0;
1239                         
1240                      printk("fw version is  %s\n",ver->TextLabel);
1241                                          
1242                         coredev->mode = ver->FirmwareId == 255 ? DEVICE_MODE_NONE : ver->FirmwareId;
1243                         coredev->modes_supported = ver->SupportedProtocols;
1244
1245                         complete(&coredev->version_ex_done);
1246                         break;
1247                 }
1248                 case MSG_SMS_INIT_DEVICE_RES:
1249                         sms_debug("MSG_SMS_INIT_DEVICE_RES");
1250                         complete(&coredev->init_device_done);
1251                         break;
1252                 case MSG_SW_RELOAD_START_RES:
1253                         sms_debug("MSG_SW_RELOAD_START_RES");
1254                         complete(&coredev->reload_start_done);
1255                         break;
1256                 case MSG_SMS_DATA_DOWNLOAD_RES:
1257                         complete(&coredev->data_download_done);
1258                         break;
1259                 case MSG_SW_RELOAD_EXEC_RES:
1260                         sms_debug("MSG_SW_RELOAD_EXEC_RES");
1261                         break;
1262                 case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
1263                         sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
1264                         complete(&coredev->trigger_done);
1265                         break;
1266                 case MSG_SMS_SLEEP_RESUME_COMP_IND:
1267                         complete(&coredev->resume_done);
1268                         break;
1269                 case MSG_SMS_GPIO_CONFIG_EX_RES:
1270                         sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
1271                         complete(&coredev->gpio_configuration_done);
1272                         break;
1273                 case MSG_SMS_GPIO_SET_LEVEL_RES:
1274                         sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
1275                         complete(&coredev->gpio_set_level_done);
1276                         break;
1277                 case MSG_SMS_GPIO_GET_LEVEL_RES:
1278                 {
1279                         u32 *msgdata = (u32 *) phdr;
1280                         coredev->gpio_get_res = msgdata[1];
1281                         sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d", coredev->gpio_get_res);
1282                         complete(&coredev->gpio_get_level_done);
1283                         break;
1284                 }
1285
1286 // loopback in the drv
1287
1288                 case MSG_SMS_LOOPBACK_RES:
1289                 {
1290                     //u32 *msgdata = (u32 *) phdr;
1291                         memcpy( g_LbResBuf, (u8 *)phdr, phdr->msgLength );
1292                         sms_debug("MSG_SMS_LOOPBACK_RES \n");
1293                         complete(&coredev->loopback_res_done);
1294                         break;
1295                 }
1296
1297                 default:
1298 #if 0
1299                         sms_info("no client (%p) or error (%d), "
1300                                         "type:%d dstid:%d", client, rc,
1301                                         phdr->msgType, phdr->msgDstId);
1302 #endif
1303                         break;
1304                 }
1305
1306                 smscore_putbuffer(coredev, cb);
1307                 //sms_debug("after putbuffer \n");
1308
1309                 
1310         }
1311 }
1312
1313 /**
1314  * return pointer to next free buffer descriptor from core pool
1315  *
1316  * @param coredev pointer to a coredev object returned by
1317  *                smscore_register_device
1318  *
1319  * @return pointer to descriptor on success, NULL on error.
1320  */
1321 struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
1322 {
1323         struct smscore_buffer_t *cb = NULL;
1324         unsigned long flags;
1325
1326         DEFINE_WAIT(wait);
1327
1328         spin_lock_irqsave(&coredev->bufferslock, flags);
1329
1330         /* This function must return a valid buffer, since the buffer list is
1331          * finite, we check that there is an available buffer, if not, we wait
1332          * until such buffer become available.
1333          */
1334
1335         prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE);
1336
1337         if (list_empty(&coredev->buffers))
1338         {
1339         //to avoid rx buffers hung
1340         printk("eladr: smscore_getbuffer scheduled caus list is empty\n");
1341         spin_unlock_irqrestore(&coredev->bufferslock, flags);
1342         schedule();
1343         spin_lock_irqsave(&coredev->bufferslock, flags);
1344         }
1345
1346     //printk("smscore_getbuffer call finish_wait\n");
1347         finish_wait(&coredev->buffer_mng_waitq, &wait);
1348
1349 // if list is still empty we will return null
1350         if (list_empty(&coredev->buffers))
1351         {
1352                 //buffer is null
1353                 printk("eladr: smscore_getbuffer fail to allocate buffer, returning null \n");          
1354         }
1355         else
1356         {
1357                 cb = (struct smscore_buffer_t *) coredev->buffers.next;
1358                 if(cb->entry.prev==LIST_POISON1 || cb->entry.next==LIST_POISON1 || cb->entry.prev==LIST_POISON2 || cb->entry.next==LIST_POISON2 )
1359                 {
1360                         printk("smscore_getbuffer list is no good\n");  
1361                         spin_unlock_irqrestore(&coredev->bufferslock, flags); 
1362                         return NULL;
1363                 }
1364
1365         //printk("smscore_getbuffer buffer was allocated cb=0x%x\n", cb);
1366                 list_del(&cb->entry);
1367         }
1368
1369         spin_unlock_irqrestore(&coredev->bufferslock, flags);
1370
1371         return cb;
1372 }
1373
1374 /**
1375  * return buffer descriptor to a pool
1376  *
1377  * @param coredev pointer to a coredev object returned by
1378  *                smscore_register_device
1379  * @param cb pointer buffer descriptor
1380  *
1381  */
1382 void smscore_putbuffer(struct smscore_device_t *coredev,
1383     struct smscore_buffer_t *cb) {
1384     wake_up_interruptible(&coredev->buffer_mng_waitq);
1385     list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
1386 }
1387
1388 static int smscore_validate_client(struct smscore_device_t *coredev,
1389                 struct smscore_client_t *client, int data_type, int id) {
1390         struct smscore_idlist_t *listentry;
1391         struct smscore_client_t *registered_client;
1392
1393         if (!client) {
1394                 sms_err("bad parameter.");
1395                 return -EFAULT;
1396         }
1397         registered_client = smscore_find_client(coredev, data_type, id);
1398         if (registered_client == client)
1399                 return 0;
1400
1401         if (registered_client) {
1402                 sms_err("The msg ID already registered to another client.");
1403                 return -EEXIST;
1404         }
1405         listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
1406         if (!listentry) {
1407                 sms_err("Can't allocate memory for client id.");
1408                 return -ENOMEM;
1409         }
1410         listentry->id = id;
1411         listentry->data_type = data_type;
1412         list_add_locked(&listentry->entry, &client->idlist,
1413                         &coredev->clientslock);
1414         return 0;
1415 }
1416
1417 /**
1418  * creates smsclient object, check that id is taken by another client
1419  *
1420  * @param coredev pointer to a coredev object from clients hotplug
1421  * @param initial_id all messages with this id would be sent to this client
1422  * @param data_type all messages of this type would be sent to this client
1423  * @param onresponse_handler client handler that is called to
1424  *                           process incoming messages
1425  * @param onremove_handler client handler that is called when device is removed
1426  * @param context client-specific context
1427  * @param client pointer to a value that receives created smsclient object
1428  *
1429  * @return 0 on success, <0 on error.
1430  */
1431 int smscore_register_client(struct smscore_device_t *coredev,
1432                 struct smsclient_params_t *params,
1433                                 struct smscore_client_t **client) {
1434         struct smscore_client_t *newclient;
1435     
1436         /* check that no other channel with same parameters exists */
1437     
1438         sms_info("entering....smscore_register_client \n");
1439
1440         if (smscore_find_client(coredev, params->data_type,     params->initial_id)) {
1441                 sms_err("Client already exist.");
1442                 return -EEXIST;
1443         }
1444
1445         newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
1446         if (!newclient) {
1447                 sms_err("Failed to allocate memory for client.");
1448                 return -ENOMEM;
1449         }
1450
1451         INIT_LIST_HEAD(&newclient->idlist);
1452         newclient->coredev = coredev;
1453         newclient->onresponse_handler = params->onresponse_handler;
1454         newclient->onremove_handler = params->onremove_handler;
1455         newclient->context = params->context;
1456         list_add_locked(&newclient->entry, &coredev->clients,&coredev->clientslock);
1457         smscore_validate_client(coredev, newclient, params->data_type,params->initial_id);
1458         *client = newclient;
1459         sms_debug("Register new client %p DT=%d ID=%d",
1460                 params->context, params->data_type, params->initial_id);
1461
1462         return 0;
1463 }
1464
1465 /**
1466  * frees smsclient object and all subclients associated with it
1467  *
1468  * @param client pointer to smsclient object returned by
1469  *               smscore_register_client
1470  *
1471  */
1472 void smscore_unregister_client(struct smscore_client_t *client)
1473 {
1474         struct smscore_device_t *coredev = client->coredev;
1475         unsigned long flags;
1476
1477         spin_lock_irqsave(&coredev->clientslock, flags);
1478
1479         while (!list_empty(&client->idlist)) {
1480                 struct smscore_idlist_t *identry =
1481                                 (struct smscore_idlist_t *) client->idlist.next;
1482                 list_del(&identry->entry);
1483                 kfree(identry);
1484         }
1485
1486         sms_info("%p", client->context);
1487
1488         list_del(&client->entry);
1489         kfree(client);
1490
1491         spin_unlock_irqrestore(&coredev->clientslock, flags);
1492 }
1493
1494 /**
1495  * verifies that source id is not taken by another client,
1496  * calls device handler to send requests to the device
1497  *
1498  * @param client pointer to smsclient object returned by
1499  *               smscore_register_client
1500  * @param buffer pointer to a request buffer
1501  * @param size size (in bytes) of request buffer
1502  *
1503  * @return 0 on success, <0 on error.
1504  */
1505 int smsclient_sendrequest(struct smscore_client_t *client, void *buffer,
1506                 size_t size) {
1507         struct smscore_device_t *coredev;
1508         struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer;
1509         int rc;
1510
1511         if (client == NULL) {
1512                 sms_err("Got NULL client");
1513                 return -EINVAL;
1514         }
1515
1516         coredev = client->coredev;
1517
1518         /* check that no other channel with same id exists */
1519         if (coredev == NULL) {
1520                 sms_err("Got NULL coredev");
1521                 return -EINVAL;
1522         }
1523
1524         rc = smscore_validate_client(client->coredev, client, 0,
1525                         phdr->msgSrcId);
1526         if (rc < 0)
1527                 return rc;
1528
1529         return coredev->sendrequest_handler(coredev->context, buffer, size);
1530 }
1531
1532 #ifdef SMS_HOSTLIB_SUBSYS
1533 /**
1534  * return the size of large (common) buffer
1535  *
1536  * @param coredev pointer to a coredev object from clients hotplug
1537  *
1538  * @return size (in bytes) of the buffer
1539  */
1540 int smscore_get_common_buffer_size(struct smscore_device_t *coredev)
1541 {
1542         return coredev->common_buffer_size;
1543 }
1544
1545 /**
1546  * maps common buffer (if supported by platform)
1547  *
1548  * @param coredev pointer to a coredev object from clients hotplug
1549  * @param vma pointer to vma struct from mmap handler
1550  *
1551  * @return 0 on success, <0 on error.
1552  */
1553 int smscore_map_common_buffer(struct smscore_device_t *coredev,
1554                 struct vm_area_struct *vma)
1555 {
1556         unsigned long end = vma->vm_end,
1557         start = vma->vm_start,
1558         size = PAGE_ALIGN(coredev->common_buffer_size);
1559
1560         if (!(vma->vm_flags & (VM_READ | VM_SHARED)) ||
1561                         (vma->vm_flags & VM_WRITE)) {
1562                 sms_err("invalid vm flags");
1563                 return -EINVAL;
1564         }
1565
1566         if ((end - start) != size) {
1567                 sms_err("invalid size %d expected %d",
1568                                 (int)(end - start), (int)size);
1569                 return -EINVAL;
1570         }
1571
1572         if (remap_pfn_range(vma, start,
1573                         coredev->common_buffer_phys >> PAGE_SHIFT,
1574                         size, pgprot_noncached(vma->vm_page_prot))) {
1575                 sms_err("remap_page_range failed");
1576                 return -EAGAIN;
1577         }
1578
1579         return 0;
1580 }
1581 #endif /* SMS_HOSTLIB_SUBSYS */
1582
1583 static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
1584                 u32 *pGroupNum, u32 *pGroupCfg) {
1585
1586         *pGroupCfg = 1;
1587
1588         if (PinNum >= 0 && PinNum <= 1) {
1589                 *pTranslatedPinNum = 0;
1590                 *pGroupNum = 9;
1591                 *pGroupCfg = 2;
1592         } else if (PinNum >= 2 && PinNum <= 6) {
1593                 *pTranslatedPinNum = 2;
1594                 *pGroupNum = 0;
1595                 *pGroupCfg = 2;
1596         } else if (PinNum >= 7 && PinNum <= 11) {
1597                 *pTranslatedPinNum = 7;
1598                 *pGroupNum = 1;
1599         } else if (PinNum >= 12 && PinNum <= 15) {
1600                 *pTranslatedPinNum = 12;
1601                 *pGroupNum = 2;
1602                 *pGroupCfg = 3;
1603         } else if (PinNum == 16) {
1604                 *pTranslatedPinNum = 16;
1605                 *pGroupNum = 23;
1606         } else if (PinNum >= 17 && PinNum <= 24) {
1607                 *pTranslatedPinNum = 17;
1608                 *pGroupNum = 3;
1609         } else if (PinNum == 25) {
1610                 *pTranslatedPinNum = 25;
1611                 *pGroupNum = 6;
1612         } else if (PinNum >= 26 && PinNum <= 28) {
1613                 *pTranslatedPinNum = 26;
1614                 *pGroupNum = 4;
1615         } else if (PinNum == 29) {
1616                 *pTranslatedPinNum = 29;
1617                 *pGroupNum = 5;
1618                 *pGroupCfg = 2;
1619         } else if (PinNum == 30) {
1620                 *pTranslatedPinNum = 30;
1621                 *pGroupNum = 8;
1622         } else if (PinNum == 31) {
1623                 *pTranslatedPinNum = 31;
1624                 *pGroupNum = 17;
1625         } else
1626                 return -1;
1627
1628         *pGroupCfg <<= 24;
1629
1630         return 0;
1631 }
1632
1633 int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
1634                 struct smscore_gpio_config *pGpioConfig) {
1635
1636         u32 totalLen;
1637         u32 TranslatedPinNum;
1638         u32 GroupNum;
1639         u32 ElectricChar;
1640         u32 groupCfg;
1641         void *buffer;
1642         int rc;
1643
1644         struct SetGpioMsg {
1645                 struct SmsMsgHdr_ST xMsgHeader;
1646                 u32 msgData[6];
1647         } *pMsg;
1648
1649
1650         if (PinNum > MAX_GPIO_PIN_NUMBER)
1651                 return -EINVAL;
1652
1653         if (pGpioConfig == NULL)
1654                 return -EINVAL;
1655
1656         totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
1657
1658         buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
1659                         GFP_KERNEL | GFP_DMA);
1660         if (!buffer)
1661                 return -ENOMEM;
1662
1663         pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
1664
1665         pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
1666         pMsg->xMsgHeader.msgDstId = HIF_TASK;
1667         pMsg->xMsgHeader.msgFlags = 0;
1668         pMsg->xMsgHeader.msgLength = (u16) totalLen;
1669         pMsg->msgData[0] = PinNum;
1670
1671         if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
1672                 pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
1673                 if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
1674                                 &groupCfg) != 0)
1675                         return -EINVAL;
1676
1677                 pMsg->msgData[1] = TranslatedPinNum;
1678                 pMsg->msgData[2] = GroupNum;
1679                 ElectricChar = (pGpioConfig->PullUpDown)
1680                                 | (pGpioConfig->InputCharacteristics << 2)
1681                                 | (pGpioConfig->OutputSlewRate << 3)
1682                                 | (pGpioConfig->OutputDriving << 4);
1683                 pMsg->msgData[3] = ElectricChar;
1684                 pMsg->msgData[4] = pGpioConfig->Direction;
1685                 pMsg->msgData[5] = groupCfg;
1686         } else {
1687                 pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
1688                 pMsg->msgData[1] = pGpioConfig->PullUpDown;
1689                 pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
1690                 pMsg->msgData[3] = pGpioConfig->OutputDriving;
1691                 pMsg->msgData[4] = pGpioConfig->Direction;
1692                 pMsg->msgData[5] = 0;
1693         }
1694
1695         smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
1696         rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
1697                         &coredev->gpio_configuration_done);
1698
1699         if (rc != 0) {
1700                 if (rc == -ETIME)
1701                         sms_err("smscore_gpio_configure timeout");
1702                 else
1703                         sms_err("smscore_gpio_configure error");
1704         }
1705         kfree(buffer);
1706
1707         return rc;
1708 }
1709
1710 int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
1711                 u8 NewLevel) {
1712
1713         u32 totalLen;
1714         int rc;
1715         void *buffer;
1716
1717         struct SetGpioMsg {
1718                 struct SmsMsgHdr_ST xMsgHeader;
1719                 u32 msgData[3]; /* keep it 3 ! */
1720         } *pMsg;
1721
1722         if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER) ||
1723                         (PinNum > MAX_GPIO_PIN_NUMBER))
1724                 return -EINVAL;
1725
1726         totalLen = sizeof(struct SmsMsgHdr_ST) +
1727                         (3 * sizeof(u32)); /* keep it 3 ! */
1728
1729         buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
1730                         GFP_KERNEL | GFP_DMA);
1731         if (!buffer)
1732                 return -ENOMEM;
1733
1734         pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
1735
1736         pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
1737         pMsg->xMsgHeader.msgDstId = HIF_TASK;
1738         pMsg->xMsgHeader.msgFlags = 0;
1739         pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
1740         pMsg->xMsgHeader.msgLength = (u16) totalLen;
1741         pMsg->msgData[0] = PinNum;
1742         pMsg->msgData[1] = NewLevel;
1743
1744         /* Send message to SMS */
1745         smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
1746         rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
1747                         &coredev->gpio_set_level_done);
1748
1749         if (rc != 0) {
1750                 if (rc == -ETIME)
1751                         sms_err("smscore_gpio_set_level timeout");
1752                 else
1753                         sms_err("smscore_gpio_set_level error");
1754         }
1755         kfree(buffer);
1756
1757         return rc;
1758 }
1759
1760 int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
1761                 u8 *level) {
1762
1763         u32 totalLen;
1764         int rc;
1765         void *buffer;
1766
1767         struct SetGpioMsg {
1768                 struct SmsMsgHdr_ST xMsgHeader;
1769                 u32 msgData[2];
1770         } *pMsg;
1771
1772
1773         if (PinNum > MAX_GPIO_PIN_NUMBER)
1774                 return -EINVAL;
1775
1776         totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
1777
1778         buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
1779                         GFP_KERNEL | GFP_DMA);
1780         if (!buffer)
1781                 return -ENOMEM;
1782
1783         pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
1784
1785         pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
1786         pMsg->xMsgHeader.msgDstId = HIF_TASK;
1787         pMsg->xMsgHeader.msgFlags = 0;
1788         pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
1789         pMsg->xMsgHeader.msgLength = (u16) totalLen;
1790         pMsg->msgData[0] = PinNum;
1791         pMsg->msgData[1] = 0;
1792
1793         /* Send message to SMS */
1794         smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
1795         rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
1796                         &coredev->gpio_get_level_done);
1797
1798         if (rc != 0) {
1799                 if (rc == -ETIME)
1800                         sms_err("smscore_gpio_get_level timeout");
1801                 else
1802                         sms_err("smscore_gpio_get_level error");
1803         }
1804         kfree(buffer);
1805
1806         /* Its a race between other gpio_get_level() and the copy of the single
1807          * global 'coredev->gpio_get_res' to  the function's variable 'level'
1808          */
1809         *level = coredev->gpio_get_res;
1810
1811         return rc;
1812 }
1813
1814
1815
1816
1817 static int __init smscore_module_init(void)
1818 {
1819         int rc = 0;
1820
1821         printk("smsmdtv module init...\n");
1822         sms_info("entering... smscore_module_init....\n");
1823         INIT_LIST_HEAD(&g_smscore_notifyees);
1824         INIT_LIST_HEAD(&g_smscore_devices);
1825         kmutex_init(&g_smscore_deviceslock);
1826
1827         INIT_LIST_HEAD(&g_smscore_registry);
1828         kmutex_init(&g_smscore_registrylock);
1829
1830 //request the gpio used by cmmb
1831         //request_cmmb_gpio();
1832         /* Register sub system adapter objects */
1833 //      request_cmmb_gpio();
1834
1835 #ifdef SMS_NET_SUBSYS
1836         /* NET Register */
1837         rc = smsnet_register();
1838         if (rc) {
1839                 sms_err("Error registering Siano's network client.\n");
1840                 goto smsnet_error;
1841         }
1842 #endif
1843
1844 #ifdef SMS_HOSTLIB_SUBSYS
1845         /* Char interface Register */
1846         rc = smschar_register();
1847         if (rc) {
1848                 sms_err("Error registering Siano's char device client.\n");
1849                 goto smschar_error;
1850         }
1851 #endif
1852
1853 #ifdef SMS_DVB3_SUBSYS
1854         /* DVB v.3 Register */
1855         rc = smsdvb_register();
1856         if (rc) {
1857                 sms_err("Error registering DVB client.\n");
1858                 goto smsdvb_error;
1859         }
1860 #endif
1861
1862         /* Register interfaces objects */
1863
1864 #ifdef SMS_USB_DRV
1865         /* USB Register */
1866         rc = smsusb_register();
1867         if (rc) {
1868                 sms_err("Error registering USB bus driver.\n");
1869                 goto sms_bus_drv_error;
1870         }
1871 #endif
1872
1873 #ifdef SMS_SDIO_DRV
1874         /* SDIO Register */
1875         rc = smssdio_register();
1876         if (rc) {
1877                 sms_err("Error registering SDIO bus driver.\n");
1878                 goto sms_bus_drv_error;
1879         }
1880 #endif
1881
1882
1883 #ifdef SMS_SPI_ROCKCHIP
1884     sms_debug(KERN_INFO "smsspi_register\n");
1885         rc = smsspi_register();  
1886         if (rc) {
1887                 sms_err("Error registering Intel PXA310 SPI bus driver.\n");
1888                 goto sms_bus_drv_error;
1889         }
1890 #endif
1891
1892         return rc;
1893
1894 sms_bus_drv_error:
1895 #ifdef SMS_DVB3_SUBSYS
1896         smsdvb_unregister();
1897 smsdvb_error:
1898 #endif
1899
1900 #ifdef SMS_HOSTLIB_SUBSYS
1901         smschar_unregister();
1902 smschar_error:
1903 #endif
1904
1905 #ifdef SMS_NET_SUBSYS
1906         smsnet_unregister();
1907 smsnet_error:
1908 #endif
1909
1910         sms_err("rc %d", rc);
1911         printk(KERN_INFO "%s, rc %d\n", __func__, rc);
1912
1913         return rc;
1914 }
1915
1916 static void __exit smscore_module_exit(void)
1917 {
1918
1919
1920
1921 #ifdef SMS_NET_SUBSYS
1922         /* Net Unregister */
1923         smsnet_unregister();
1924 #endif
1925
1926 #ifdef SMS_HOSTLIB_SUBSYS
1927         /* Char interface Unregister */
1928         smschar_unregister();
1929 #endif
1930
1931 #ifdef SMS_DVB3_SUBSYS
1932         /* DVB v.3 unregister */
1933         smsdvb_unregister();
1934 #endif
1935
1936         /* Unegister interfaces objects */
1937 #ifdef SMS_USB_DRV
1938         /* USB unregister */
1939         smsusb_unregister();
1940 #endif
1941
1942 #ifdef SMS_SDIO_DRV
1943         /* SDIO unegister */
1944         smssdio_unregister();
1945 #endif
1946
1947 #ifdef SMS_SPI_ROCKCHIP
1948         /* Intel PXA310 SPI unegister */
1949         smsspi_unregister();
1950 #endif
1951
1952         kmutex_lock(&g_smscore_deviceslock);
1953         while (!list_empty(&g_smscore_notifyees)) {
1954                 struct smscore_device_notifyee_t *notifyee =
1955                 (struct smscore_device_notifyee_t *)
1956                 g_smscore_notifyees.next;
1957
1958                 list_del(&notifyee->entry);
1959                 kfree(notifyee);
1960         }
1961         kmutex_unlock(&g_smscore_deviceslock);
1962
1963         kmutex_lock(&g_smscore_registrylock);
1964         while (!list_empty(&g_smscore_registry)) {
1965                 struct smscore_registry_entry_t *entry =
1966                 (struct smscore_registry_entry_t *)
1967                 g_smscore_registry.next;
1968
1969                 list_del(&entry->entry);
1970                 kfree(entry);
1971         }
1972         kmutex_unlock(&g_smscore_registrylock);
1973         
1974 //      release_cmmb_gpio();
1975
1976         sms_debug("");
1977 }
1978
1979 // for loopback test
1980 // for loopback
1981
1982 int  AdrLoopbackTest( struct smscore_device_t *coredev )
1983 {
1984         char msgbuff[252];
1985         struct SmsMsgData_ST* pLoopbackMsg = (struct SmsMsgData_ST*)msgbuff;
1986         struct SmsMsgData_ST* pLoopbackRes = (struct SmsMsgData_ST*)g_LbResBuf;
1987         int i , j;
1988         int g_Loopback_failCounters= 0; 
1989         int Len = 252 - sizeof(struct SmsMsgData_ST);
1990         char* pPtr;
1991         int rc =0;
1992
1993         pLoopbackMsg->xMsgHeader.msgType = MSG_SMS_LOOPBACK_REQ;
1994         pLoopbackMsg->xMsgHeader.msgSrcId = 151;
1995         pLoopbackMsg->xMsgHeader.msgDstId = 11;
1996         pLoopbackMsg->xMsgHeader.msgFlags = 0;
1997         pLoopbackMsg->xMsgHeader.msgLength = 252;
1998         
1999         sms_info("Loobpack test start.");
2000         
2001
2002         for ( i = 0 ; i < 1000 ; i++ )
2003         {
2004
2005                 pPtr = (u8*) &pLoopbackMsg->msgData[1];
2006                 for ( j = 0 ; j < Len ; j ++ )
2007                 {
2008                         pPtr[j] = i+j;
2009                 }
2010                 pLoopbackMsg->msgData[0] = i+1;
2011         
2012                 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pLoopbackMsg);
2013                         rc = smscore_sendrequest_and_wait(coredev, pLoopbackMsg,
2014                                         pLoopbackMsg->xMsgHeader.msgLength,
2015                                         &coredev->loopback_res_done);
2016
2017
2018                 if (rc)
2019                         return  rc; 
2020
2021         
2022                 pPtr = (u8*) &pLoopbackRes->msgData[1];
2023
2024                 for ( j = 0 ; j < Len ; j ++ )
2025                 {
2026                         if ( pPtr[j] != (u8)(j + i))
2027                         {
2028                                         sms_err("Loopback data error at byte %u. Exp %u, Got %u", j, (u8)(j+i), pPtr[j] );
2029                                         g_Loopback_failCounters++;
2030                                         break;
2031                         }
2032                 } //for ( j = 0 ; j < Len ; j ++ )
2033         } //for ( i = 0 ; i < 100 ; i++ )
2034         sms_info( "Loobpack test end. RUN  times: %d; fail times : %d", i, g_Loopback_failCounters);
2035         return rc ;
2036 }
2037
2038
2039 module_init(smscore_module_init);
2040 module_exit(smscore_module_exit);
2041
2042 MODULE_DESCRIPTION("Siano MDTV Core module");
2043 MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
2044 MODULE_LICENSE("GPL");