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