2 * Siano core API module
4 * This file contains implementation for the interface to sms core component
8 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation;
14 * Software distributed under the License is distributed on an "AS IS"
15 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
17 * See the GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/moduleparam.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/delay.h>
32 #include <linux/firmware.h>
33 #include <linux/wait.h>
34 #include <asm/byteorder.h>
36 #include "smscoreapi.h"
37 #include "sms-cards.h"
39 #include "smsendian.h"
42 module_param_named(debug
, sms_dbg
, int, 0644);
43 MODULE_PARM_DESC(debug
, "set debug level (info=1, adv=2 (or-able))");
45 struct smscore_device_notifyee_t
{
46 struct list_head entry
;
50 struct smscore_idlist_t
{
51 struct list_head entry
;
56 struct smscore_client_t
{
57 struct list_head entry
;
58 struct smscore_device_t
*coredev
;
60 struct list_head idlist
;
61 onresponse_t onresponse_handler
;
62 onremove_t onremove_handler
;
65 void smscore_set_board_id(struct smscore_device_t
*core
, int id
)
70 int smscore_led_state(struct smscore_device_t
*core
, int led
)
73 core
->led_state
= led
;
74 return core
->led_state
;
76 EXPORT_SYMBOL_GPL(smscore_set_board_id
);
78 int smscore_get_board_id(struct smscore_device_t
*core
)
80 return core
->board_id
;
82 EXPORT_SYMBOL_GPL(smscore_get_board_id
);
84 struct smscore_registry_entry_t
{
85 struct list_head entry
;
88 enum sms_device_type_st type
;
91 static struct list_head g_smscore_notifyees
;
92 static struct list_head g_smscore_devices
;
93 static struct mutex g_smscore_deviceslock
;
95 static struct list_head g_smscore_registry
;
96 static struct mutex g_smscore_registrylock
;
98 static int default_mode
= 4;
100 module_param(default_mode
, int, 0644);
101 MODULE_PARM_DESC(default_mode
, "default firmware id (device mode)");
103 static struct smscore_registry_entry_t
*smscore_find_registry(char *devpath
)
105 struct smscore_registry_entry_t
*entry
;
106 struct list_head
*next
;
108 kmutex_lock(&g_smscore_registrylock
);
109 for (next
= g_smscore_registry
.next
;
110 next
!= &g_smscore_registry
;
112 entry
= (struct smscore_registry_entry_t
*) next
;
113 if (!strcmp(entry
->devpath
, devpath
)) {
114 kmutex_unlock(&g_smscore_registrylock
);
118 entry
= (struct smscore_registry_entry_t
*)
119 kmalloc(sizeof(struct smscore_registry_entry_t
),
122 entry
->mode
= default_mode
;
123 strcpy(entry
->devpath
, devpath
);
124 list_add(&entry
->entry
, &g_smscore_registry
);
126 sms_err("failed to create smscore_registry.");
127 kmutex_unlock(&g_smscore_registrylock
);
131 int smscore_registry_getmode(char *devpath
)
133 struct smscore_registry_entry_t
*entry
;
135 entry
= smscore_find_registry(devpath
);
139 sms_err("No registry found.");
143 EXPORT_SYMBOL_GPL(smscore_registry_getmode
);
145 static enum sms_device_type_st
smscore_registry_gettype(char *devpath
)
147 struct smscore_registry_entry_t
*entry
;
149 entry
= smscore_find_registry(devpath
);
153 sms_err("No registry found.");
158 void smscore_registry_setmode(char *devpath
, int mode
)
160 struct smscore_registry_entry_t
*entry
;
162 entry
= smscore_find_registry(devpath
);
166 sms_err("No registry found.");
169 static void smscore_registry_settype(char *devpath
,
170 enum sms_device_type_st type
)
172 struct smscore_registry_entry_t
*entry
;
174 entry
= smscore_find_registry(devpath
);
178 sms_err("No registry found.");
182 static void list_add_locked(struct list_head
*new, struct list_head
*head
,
187 spin_lock_irqsave(lock
, flags
);
191 spin_unlock_irqrestore(lock
, flags
);
195 * register a client callback that called when device plugged in/unplugged
196 * NOTE: if devices exist callback is called immediately for each device
198 * @param hotplug callback
200 * @return 0 on success, <0 on error.
202 int smscore_register_hotplug(hotplug_t hotplug
)
204 struct smscore_device_notifyee_t
*notifyee
;
205 struct list_head
*next
, *first
;
208 kmutex_lock(&g_smscore_deviceslock
);
210 notifyee
= kmalloc(sizeof(struct smscore_device_notifyee_t
),
213 /* now notify callback about existing devices */
214 first
= &g_smscore_devices
;
215 for (next
= first
->next
;
216 next
!= first
&& !rc
;
218 struct smscore_device_t
*coredev
=
219 (struct smscore_device_t
*) next
;
220 rc
= hotplug(coredev
, coredev
->device
, 1);
224 notifyee
->hotplug
= hotplug
;
225 list_add(¬ifyee
->entry
, &g_smscore_notifyees
);
231 kmutex_unlock(&g_smscore_deviceslock
);
235 EXPORT_SYMBOL_GPL(smscore_register_hotplug
);
238 * unregister a client callback that called when device plugged in/unplugged
240 * @param hotplug callback
243 void smscore_unregister_hotplug(hotplug_t hotplug
)
245 struct list_head
*next
, *first
;
247 kmutex_lock(&g_smscore_deviceslock
);
249 first
= &g_smscore_notifyees
;
251 for (next
= first
->next
; next
!= first
;) {
252 struct smscore_device_notifyee_t
*notifyee
=
253 (struct smscore_device_notifyee_t
*) next
;
256 if (notifyee
->hotplug
== hotplug
) {
257 list_del(¬ifyee
->entry
);
262 kmutex_unlock(&g_smscore_deviceslock
);
264 EXPORT_SYMBOL_GPL(smscore_unregister_hotplug
);
266 static void smscore_notify_clients(struct smscore_device_t
*coredev
)
268 struct smscore_client_t
*client
;
270 /* the client must call smscore_unregister_client from remove handler */
271 while (!list_empty(&coredev
->clients
)) {
272 client
= (struct smscore_client_t
*) coredev
->clients
.next
;
273 client
->onremove_handler(client
->context
);
277 static int smscore_notify_callbacks(struct smscore_device_t
*coredev
,
278 struct device
*device
, int arrival
)
280 struct list_head
*next
, *first
;
283 /* note: must be called under g_deviceslock */
285 first
= &g_smscore_notifyees
;
287 for (next
= first
->next
; next
!= first
; next
= next
->next
) {
288 rc
= ((struct smscore_device_notifyee_t
*) next
)->
289 hotplug(coredev
, device
, arrival
);
298 smscore_buffer_t
*smscore_createbuffer(u8
*buffer
, void *common_buffer
,
299 dma_addr_t common_buffer_phys
)
301 struct smscore_buffer_t
*cb
=
302 kmalloc(sizeof(struct smscore_buffer_t
), GFP_KERNEL
);
304 sms_info("kmalloc(...) failed");
309 cb
->offset_in_common
= buffer
- (u8
*) common_buffer
;
310 cb
->phys
= common_buffer_phys
+ cb
->offset_in_common
;
316 * creates coredev object for a device, prepares buffers,
317 * creates buffer mappings, notifies registered hotplugs about new device.
319 * @param params device pointer to struct with device specific parameters
321 * @param coredev pointer to a value that receives created coredev object
323 * @return 0 on success, <0 on error.
325 int smscore_register_device(struct smsdevice_params_t
*params
,
326 struct smscore_device_t
**coredev
)
328 struct smscore_device_t
*dev
;
331 dev
= kzalloc(sizeof(struct smscore_device_t
), GFP_KERNEL
);
333 sms_info("kzalloc(...) failed");
337 /* init list entry so it could be safe in smscore_unregister_device */
338 INIT_LIST_HEAD(&dev
->entry
);
341 INIT_LIST_HEAD(&dev
->clients
);
342 INIT_LIST_HEAD(&dev
->buffers
);
345 spin_lock_init(&dev
->clientslock
);
346 spin_lock_init(&dev
->bufferslock
);
348 /* init completion events */
349 init_completion(&dev
->version_ex_done
);
350 init_completion(&dev
->data_download_done
);
351 init_completion(&dev
->trigger_done
);
352 init_completion(&dev
->init_device_done
);
353 init_completion(&dev
->reload_start_done
);
354 init_completion(&dev
->resume_done
);
355 init_completion(&dev
->gpio_configuration_done
);
356 init_completion(&dev
->gpio_set_level_done
);
357 init_completion(&dev
->gpio_get_level_done
);
358 init_completion(&dev
->ir_init_done
);
360 /* Buffer management */
361 init_waitqueue_head(&dev
->buffer_mng_waitq
);
363 /* alloc common buffer */
364 dev
->common_buffer_size
= params
->buffer_size
* params
->num_buffers
;
365 dev
->common_buffer
= dma_alloc_coherent(NULL
, dev
->common_buffer_size
,
366 &dev
->common_buffer_phys
,
367 GFP_KERNEL
| GFP_DMA
);
368 if (!dev
->common_buffer
) {
369 smscore_unregister_device(dev
);
373 /* prepare dma buffers */
374 for (buffer
= dev
->common_buffer
;
375 dev
->num_buffers
< params
->num_buffers
;
376 dev
->num_buffers
++, buffer
+= params
->buffer_size
) {
377 struct smscore_buffer_t
*cb
=
378 smscore_createbuffer(buffer
, dev
->common_buffer
,
379 dev
->common_buffer_phys
);
381 smscore_unregister_device(dev
);
385 smscore_putbuffer(dev
, cb
);
388 sms_info("allocated %d buffers", dev
->num_buffers
);
390 dev
->mode
= DEVICE_MODE_NONE
;
391 dev
->context
= params
->context
;
392 dev
->device
= params
->device
;
393 dev
->setmode_handler
= params
->setmode_handler
;
394 dev
->detectmode_handler
= params
->detectmode_handler
;
395 dev
->sendrequest_handler
= params
->sendrequest_handler
;
396 dev
->preload_handler
= params
->preload_handler
;
397 dev
->postload_handler
= params
->postload_handler
;
399 dev
->device_flags
= params
->flags
;
400 strcpy(dev
->devpath
, params
->devpath
);
402 smscore_registry_settype(dev
->devpath
, params
->device_type
);
404 /* add device to devices list */
405 kmutex_lock(&g_smscore_deviceslock
);
406 list_add(&dev
->entry
, &g_smscore_devices
);
407 kmutex_unlock(&g_smscore_deviceslock
);
411 sms_info("device %p created", dev
);
415 EXPORT_SYMBOL_GPL(smscore_register_device
);
418 static int smscore_sendrequest_and_wait(struct smscore_device_t
*coredev
,
419 void *buffer
, size_t size
, struct completion
*completion
) {
420 int rc
= coredev
->sendrequest_handler(coredev
->context
, buffer
, size
);
422 sms_info("sendrequest returned error %d", rc
);
426 return wait_for_completion_timeout(completion
,
427 msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS
)) ?
432 * Starts & enables IR operations
434 * @return 0 on success, < 0 on error.
436 static int smscore_init_ir(struct smscore_device_t
*coredev
)
442 coredev
->ir
.input_dev
= NULL
;
443 ir_io
= sms_get_board(smscore_get_board_id(coredev
))->board_cfg
.ir
;
444 if (ir_io
) {/* only if IR port exist we use IR sub-module */
445 sms_info("IR loading");
446 rc
= sms_ir_init(coredev
);
449 sms_err("Error initialization DTV IR sub-module");
451 buffer
= kmalloc(sizeof(struct SmsMsgData_ST2
) +
453 GFP_KERNEL
| GFP_DMA
);
455 struct SmsMsgData_ST2
*msg
=
456 (struct SmsMsgData_ST2
*)
457 SMS_ALIGN_ADDRESS(buffer
);
459 SMS_INIT_MSG(&msg
->xMsgHeader
,
460 MSG_SMS_START_IR_REQ
,
461 sizeof(struct SmsMsgData_ST2
));
462 msg
->msgData
[0] = coredev
->ir
.controller
;
463 msg
->msgData
[1] = coredev
->ir
.timeout
;
465 smsendian_handle_tx_message(
466 (struct SmsMsgHdr_ST2
*)msg
);
467 rc
= smscore_sendrequest_and_wait(coredev
, msg
,
468 msg
->xMsgHeader
. msgLength
,
469 &coredev
->ir_init_done
);
474 ("Sending IR initialization message failed");
477 sms_info("IR port has not been detected");
483 * sets initial device mode and notifies client hotplugs that device is ready
485 * @param coredev pointer to a coredev object returned by
486 * smscore_register_device
488 * @return 0 on success, <0 on error.
490 int smscore_start_device(struct smscore_device_t
*coredev
)
492 int rc
= smscore_set_device_mode(
493 coredev
, smscore_registry_getmode(coredev
->devpath
));
495 sms_info("set device mode faile , rc %d", rc
);
499 kmutex_lock(&g_smscore_deviceslock
);
501 rc
= smscore_notify_callbacks(coredev
, coredev
->device
, 1);
502 smscore_init_ir(coredev
);
504 sms_info("device %p started, rc %d", coredev
, rc
);
506 kmutex_unlock(&g_smscore_deviceslock
);
510 EXPORT_SYMBOL_GPL(smscore_start_device
);
513 static int smscore_load_firmware_family2(struct smscore_device_t
*coredev
,
514 void *buffer
, size_t size
)
516 struct SmsFirmware_ST
*firmware
= (struct SmsFirmware_ST
*) buffer
;
517 struct SmsMsgHdr_ST
*msg
;
519 u8
*payload
= firmware
->Payload
;
521 firmware
->StartAddress
= le32_to_cpu(firmware
->StartAddress
);
522 firmware
->Length
= le32_to_cpu(firmware
->Length
);
524 mem_address
= firmware
->StartAddress
;
526 sms_info("loading FW to addr 0x%x size %d",
527 mem_address
, firmware
->Length
);
528 if (coredev
->preload_handler
) {
529 rc
= coredev
->preload_handler(coredev
->context
);
534 /* PAGE_SIZE buffer shall be enough and dma aligned */
535 msg
= kmalloc(PAGE_SIZE
, GFP_KERNEL
| GFP_DMA
);
539 if (coredev
->mode
!= DEVICE_MODE_NONE
) {
540 sms_debug("sending reload command.");
541 SMS_INIT_MSG(msg
, MSG_SW_RELOAD_START_REQ
,
542 sizeof(struct SmsMsgHdr_ST
));
543 rc
= smscore_sendrequest_and_wait(coredev
, msg
,
545 &coredev
->reload_start_done
);
546 mem_address
= *(u32
*) &payload
[20];
549 while (size
&& rc
>= 0) {
550 struct SmsDataDownload_ST
*DataMsg
=
551 (struct SmsDataDownload_ST
*) msg
;
552 int payload_size
= min((int) size
, SMS_MAX_PAYLOAD_SIZE
);
554 SMS_INIT_MSG(msg
, MSG_SMS_DATA_DOWNLOAD_REQ
,
555 (u16
)(sizeof(struct SmsMsgHdr_ST
) +
556 sizeof(u32
) + payload_size
));
558 DataMsg
->MemAddr
= mem_address
;
559 memcpy(DataMsg
->Payload
, payload
, payload_size
);
561 if ((coredev
->device_flags
& SMS_ROM_NO_RESPONSE
) &&
562 (coredev
->mode
== DEVICE_MODE_NONE
))
563 rc
= coredev
->sendrequest_handler(
564 coredev
->context
, DataMsg
,
565 DataMsg
->xMsgHeader
.msgLength
);
567 rc
= smscore_sendrequest_and_wait(
569 DataMsg
->xMsgHeader
.msgLength
,
570 &coredev
->data_download_done
);
572 payload
+= payload_size
;
573 size
-= payload_size
;
574 mem_address
+= payload_size
;
578 if (coredev
->mode
== DEVICE_MODE_NONE
) {
579 struct SmsMsgData_ST
*TriggerMsg
=
580 (struct SmsMsgData_ST
*) msg
;
582 SMS_INIT_MSG(msg
, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ
,
583 sizeof(struct SmsMsgHdr_ST
) +
586 TriggerMsg
->msgData
[0] = firmware
->StartAddress
;
588 TriggerMsg
->msgData
[1] = 5; /* Priority */
589 TriggerMsg
->msgData
[2] = 0x200; /* Stack size */
590 TriggerMsg
->msgData
[3] = 0; /* Parameter */
591 TriggerMsg
->msgData
[4] = 4; /* Task ID */
593 if (coredev
->device_flags
& SMS_ROM_NO_RESPONSE
) {
594 rc
= coredev
->sendrequest_handler(
595 coredev
->context
, TriggerMsg
,
596 TriggerMsg
->xMsgHeader
.msgLength
);
599 rc
= smscore_sendrequest_and_wait(
601 TriggerMsg
->xMsgHeader
.msgLength
,
602 &coredev
->trigger_done
);
604 SMS_INIT_MSG(msg
, MSG_SW_RELOAD_EXEC_REQ
,
605 sizeof(struct SmsMsgHdr_ST
));
607 rc
= coredev
->sendrequest_handler(coredev
->context
,
608 msg
, msg
->msgLength
);
613 sms_debug("rc=%d, postload=%p ", rc
,
614 coredev
->postload_handler
);
618 return ((rc
>= 0) && coredev
->postload_handler
) ?
619 coredev
->postload_handler(coredev
->context
) :
624 * loads specified firmware into a buffer and calls device loadfirmware_handler
626 * @param coredev pointer to a coredev object returned by
627 * smscore_register_device
628 * @param filename null-terminated string specifies firmware file name
629 * @param loadfirmware_handler device handler that loads firmware
631 * @return 0 on success, <0 on error.
633 static int smscore_load_firmware_from_file(struct smscore_device_t
*coredev
,
635 loadfirmware_t loadfirmware_handler
)
638 const struct firmware
*fw
;
641 if (loadfirmware_handler
== NULL
&& !(coredev
->device_flags
&
645 rc
= request_firmware(&fw
, filename
, coredev
->device
);
647 sms_info("failed to open \"%s\"", filename
);
650 sms_info("read FW %s, size=%zd", filename
, fw
->size
);
651 fw_buffer
= kmalloc(ALIGN(fw
->size
, SMS_ALLOC_ALIGNMENT
),
652 GFP_KERNEL
| GFP_DMA
);
654 memcpy(fw_buffer
, fw
->data
, fw
->size
);
656 rc
= (coredev
->device_flags
& SMS_DEVICE_FAMILY2
) ?
657 smscore_load_firmware_family2(coredev
,
660 loadfirmware_handler(coredev
->context
,
661 fw_buffer
, fw
->size
);
665 sms_info("failed to allocate firmware buffer");
669 release_firmware(fw
);
675 * notifies all clients registered with the device, notifies hotplugs,
676 * frees all buffers and coredev object
678 * @param coredev pointer to a coredev object returned by
679 * smscore_register_device
681 * @return 0 on success, <0 on error.
683 void smscore_unregister_device(struct smscore_device_t
*coredev
)
685 struct smscore_buffer_t
*cb
;
689 kmutex_lock(&g_smscore_deviceslock
);
691 /* Release input device (IR) resources */
692 sms_ir_exit(coredev
);
694 smscore_notify_clients(coredev
);
695 smscore_notify_callbacks(coredev
, NULL
, 0);
697 /* at this point all buffers should be back
698 * onresponse must no longer be called */
701 while (!list_empty(&coredev
->buffers
)) {
702 cb
= (struct smscore_buffer_t
*) coredev
->buffers
.next
;
703 list_del(&cb
->entry
);
707 if (num_buffers
== coredev
->num_buffers
)
710 sms_info("exiting although "
711 "not all buffers released.");
715 sms_info("waiting for %d buffer(s)",
716 coredev
->num_buffers
- num_buffers
);
720 sms_info("freed %d buffers", num_buffers
);
722 if (coredev
->common_buffer
)
723 dma_free_coherent(NULL
, coredev
->common_buffer_size
,
724 coredev
->common_buffer
, coredev
->common_buffer_phys
);
726 if (coredev
->fw_buf
!= NULL
)
727 kfree(coredev
->fw_buf
);
729 list_del(&coredev
->entry
);
732 kmutex_unlock(&g_smscore_deviceslock
);
734 sms_info("device %p destroyed", coredev
);
736 EXPORT_SYMBOL_GPL(smscore_unregister_device
);
738 static int smscore_detect_mode(struct smscore_device_t
*coredev
)
740 void *buffer
= kmalloc(sizeof(struct SmsMsgHdr_ST
) + SMS_DMA_ALIGNMENT
,
741 GFP_KERNEL
| GFP_DMA
);
742 struct SmsMsgHdr_ST
*msg
=
743 (struct SmsMsgHdr_ST
*) SMS_ALIGN_ADDRESS(buffer
);
749 SMS_INIT_MSG(msg
, MSG_SMS_GET_VERSION_EX_REQ
,
750 sizeof(struct SmsMsgHdr_ST
));
752 rc
= smscore_sendrequest_and_wait(coredev
, msg
, msg
->msgLength
,
753 &coredev
->version_ex_done
);
755 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
757 if (wait_for_completion_timeout(&coredev
->resume_done
,
758 msecs_to_jiffies(5000))) {
759 rc
= smscore_sendrequest_and_wait(
760 coredev
, msg
, msg
->msgLength
,
761 &coredev
->version_ex_done
);
763 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "
764 "second try, rc %d", rc
);
774 static char *smscore_fw_lkup
[][SMS_NUM_OF_DEVICE_TYPES
] = {
775 /*Stellar NOVA A0 Nova B0 VEGA*/
777 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
779 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
781 {"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"},
783 {"none", "none", "none", "none"},
785 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},
787 {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
789 {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},
791 {"none", "none", "none", "cmmb_vega_12mhz.inp"}
794 static inline char *sms_get_fw_name(struct smscore_device_t
*coredev
,
795 int mode
, enum sms_device_type_st type
)
797 char **fw
= sms_get_board(smscore_get_board_id(coredev
))->fw
;
798 return (fw
&& fw
[mode
]) ? fw
[mode
] : smscore_fw_lkup
[mode
][type
];
802 * calls device handler to change mode of operation
803 * NOTE: stellar/usb may disconnect when changing mode
805 * @param coredev pointer to a coredev object returned by
806 * smscore_register_device
807 * @param mode requested mode of operation
809 * @return 0 on success, <0 on error.
811 int smscore_set_device_mode(struct smscore_device_t
*coredev
, int mode
)
815 enum sms_device_type_st type
;
817 sms_debug("set device mode to %d", mode
);
818 if (coredev
->device_flags
& SMS_DEVICE_FAMILY2
) {
819 if (mode
< DEVICE_MODE_DVBT
|| mode
>= DEVICE_MODE_RAW_TUNER
) {
820 sms_err("invalid mode specified %d", mode
);
824 smscore_registry_setmode(coredev
->devpath
, mode
);
826 if (!(coredev
->device_flags
& SMS_DEVICE_NOT_READY
)) {
827 rc
= smscore_detect_mode(coredev
);
829 sms_err("mode detect failed %d", rc
);
834 if (coredev
->mode
== mode
) {
835 sms_info("device mode %d already set", mode
);
839 if (!(coredev
->modes_supported
& (1 << mode
))) {
842 type
= smscore_registry_gettype(coredev
->devpath
);
843 fw_filename
= sms_get_fw_name(coredev
, mode
, type
);
845 rc
= smscore_load_firmware_from_file(coredev
,
848 sms_warn("error %d loading firmware: %s, "
849 "trying again with default firmware",
852 /* try again with the default firmware */
853 fw_filename
= smscore_fw_lkup
[mode
][type
];
854 rc
= smscore_load_firmware_from_file(coredev
,
858 sms_warn("error %d loading "
864 sms_log("firmware download success: %s", fw_filename
);
866 sms_info("mode %d supported by running "
869 buffer
= kmalloc(sizeof(struct SmsMsgData_ST
) +
870 SMS_DMA_ALIGNMENT
, GFP_KERNEL
| GFP_DMA
);
872 struct SmsMsgData_ST
*msg
=
873 (struct SmsMsgData_ST
*)
874 SMS_ALIGN_ADDRESS(buffer
);
876 SMS_INIT_MSG(&msg
->xMsgHeader
, MSG_SMS_INIT_DEVICE_REQ
,
877 sizeof(struct SmsMsgData_ST
));
878 msg
->msgData
[0] = mode
;
880 rc
= smscore_sendrequest_and_wait(
881 coredev
, msg
, msg
->xMsgHeader
.msgLength
,
882 &coredev
->init_device_done
);
886 sms_err("Could not allocate buffer for "
887 "init device message.");
891 if (mode
< DEVICE_MODE_DVBT
|| mode
> DEVICE_MODE_DVBT_BDA
) {
892 sms_err("invalid mode specified %d", mode
);
896 smscore_registry_setmode(coredev
->devpath
, mode
);
898 if (coredev
->detectmode_handler
)
899 coredev
->detectmode_handler(coredev
->context
,
902 if (coredev
->mode
!= mode
&& coredev
->setmode_handler
)
903 rc
= coredev
->setmode_handler(coredev
->context
, mode
);
907 coredev
->mode
= mode
;
908 coredev
->device_flags
&= ~SMS_DEVICE_NOT_READY
;
912 sms_err("return error code %d.", rc
);
917 * calls device handler to get current mode of operation
919 * @param coredev pointer to a coredev object returned by
920 * smscore_register_device
922 * @return current mode
924 int smscore_get_device_mode(struct smscore_device_t
*coredev
)
926 return coredev
->mode
;
928 EXPORT_SYMBOL_GPL(smscore_get_device_mode
);
931 * find client by response id & type within the clients list.
932 * return client handle or NULL.
934 * @param coredev pointer to a coredev object returned by
935 * smscore_register_device
936 * @param data_type client data type (SMS_DONT_CARE for all types)
937 * @param id client id (SMS_DONT_CARE for all id)
941 smscore_client_t
*smscore_find_client(struct smscore_device_t
*coredev
,
942 int data_type
, int id
)
944 struct smscore_client_t
*client
= NULL
;
945 struct list_head
*next
, *first
;
947 struct list_head
*firstid
, *nextid
;
950 spin_lock_irqsave(&coredev
->clientslock
, flags
);
951 first
= &coredev
->clients
;
952 for (next
= first
->next
;
953 (next
!= first
) && !client
;
955 firstid
= &((struct smscore_client_t
*)next
)->idlist
;
956 for (nextid
= firstid
->next
;
958 nextid
= nextid
->next
) {
959 if ((((struct smscore_idlist_t
*)nextid
)->id
== id
) &&
960 (((struct smscore_idlist_t
*)nextid
)->data_type
== data_type
||
961 (((struct smscore_idlist_t
*)nextid
)->data_type
== 0))) {
962 client
= (struct smscore_client_t
*) next
;
967 spin_unlock_irqrestore(&coredev
->clientslock
, flags
);
972 * find client by response id/type, call clients onresponse handler
973 * return buffer to pool on error
975 * @param coredev pointer to a coredev object returned by
976 * smscore_register_device
977 * @param cb pointer to response buffer descriptor
980 void smscore_onresponse(struct smscore_device_t
*coredev
,
981 struct smscore_buffer_t
*cb
) {
982 struct SmsMsgHdr_ST
*phdr
= (struct SmsMsgHdr_ST
*) ((u8
*) cb
->p
984 struct smscore_client_t
*client
;
986 static unsigned long last_sample_time
; /* = 0; */
987 static int data_total
; /* = 0; */
988 unsigned long time_now
= jiffies_to_msecs(jiffies
);
990 if (!last_sample_time
)
991 last_sample_time
= time_now
;
993 if (time_now
- last_sample_time
> 10000) {
994 sms_debug("\ndata rate %d bytes/secs",
995 (int)((data_total
* 1000) /
996 (time_now
- last_sample_time
)));
998 last_sample_time
= time_now
;
1002 data_total
+= cb
->size
;
1003 /* Do we need to re-route? */
1004 if ((phdr
->msgType
== MSG_SMS_HO_PER_SLICES_IND
) ||
1005 (phdr
->msgType
== MSG_SMS_TRANSMISSION_IND
)) {
1006 if (coredev
->mode
== DEVICE_MODE_DVBT_BDA
)
1007 phdr
->msgDstId
= DVBT_BDA_CONTROL_MSG_ID
;
1011 client
= smscore_find_client(coredev
, phdr
->msgType
, phdr
->msgDstId
);
1013 /* If no client registered for type & id,
1014 * check for control client where type is not registered */
1016 rc
= client
->onresponse_handler(client
->context
, cb
);
1019 switch (phdr
->msgType
) {
1020 case MSG_SMS_GET_VERSION_EX_RES
:
1022 struct SmsVersionRes_ST
*ver
=
1023 (struct SmsVersionRes_ST
*) phdr
;
1024 sms_debug("MSG_SMS_GET_VERSION_EX_RES "
1025 "id %d prots 0x%x ver %d.%d",
1026 ver
->FirmwareId
, ver
->SupportedProtocols
,
1027 ver
->RomVersionMajor
, ver
->RomVersionMinor
);
1029 coredev
->mode
= ver
->FirmwareId
== 255 ?
1030 DEVICE_MODE_NONE
: ver
->FirmwareId
;
1031 coredev
->modes_supported
= ver
->SupportedProtocols
;
1033 complete(&coredev
->version_ex_done
);
1036 case MSG_SMS_INIT_DEVICE_RES
:
1037 sms_debug("MSG_SMS_INIT_DEVICE_RES");
1038 complete(&coredev
->init_device_done
);
1040 case MSG_SW_RELOAD_START_RES
:
1041 sms_debug("MSG_SW_RELOAD_START_RES");
1042 complete(&coredev
->reload_start_done
);
1044 case MSG_SMS_DATA_DOWNLOAD_RES
:
1045 complete(&coredev
->data_download_done
);
1047 case MSG_SW_RELOAD_EXEC_RES
:
1048 sms_debug("MSG_SW_RELOAD_EXEC_RES");
1050 case MSG_SMS_SWDOWNLOAD_TRIGGER_RES
:
1051 sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES");
1052 complete(&coredev
->trigger_done
);
1054 case MSG_SMS_SLEEP_RESUME_COMP_IND
:
1055 complete(&coredev
->resume_done
);
1057 case MSG_SMS_GPIO_CONFIG_EX_RES
:
1058 sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES");
1059 complete(&coredev
->gpio_configuration_done
);
1061 case MSG_SMS_GPIO_SET_LEVEL_RES
:
1062 sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES");
1063 complete(&coredev
->gpio_set_level_done
);
1065 case MSG_SMS_GPIO_GET_LEVEL_RES
:
1067 u32
*msgdata
= (u32
*) phdr
;
1068 coredev
->gpio_get_res
= msgdata
[1];
1069 sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d",
1070 coredev
->gpio_get_res
);
1071 complete(&coredev
->gpio_get_level_done
);
1074 case MSG_SMS_START_IR_RES
:
1075 complete(&coredev
->ir_init_done
);
1077 case MSG_SMS_IR_SAMPLES_IND
:
1078 sms_ir_event(coredev
,
1081 + sizeof(struct SmsMsgHdr_ST
)),
1082 (int)phdr
->msgLength
1083 - sizeof(struct SmsMsgHdr_ST
));
1089 smscore_putbuffer(coredev
, cb
);
1092 EXPORT_SYMBOL_GPL(smscore_onresponse
);
1095 * return pointer to next free buffer descriptor from core pool
1097 * @param coredev pointer to a coredev object returned by
1098 * smscore_register_device
1100 * @return pointer to descriptor on success, NULL on error.
1102 struct smscore_buffer_t
*smscore_getbuffer(struct smscore_device_t
*coredev
)
1104 struct smscore_buffer_t
*cb
= NULL
;
1105 unsigned long flags
;
1109 spin_lock_irqsave(&coredev
->bufferslock
, flags
);
1111 /* This function must return a valid buffer, since the buffer list is
1112 * finite, we check that there is an available buffer, if not, we wait
1113 * until such buffer become available.
1116 prepare_to_wait(&coredev
->buffer_mng_waitq
, &wait
, TASK_INTERRUPTIBLE
);
1118 if (list_empty(&coredev
->buffers
))
1121 finish_wait(&coredev
->buffer_mng_waitq
, &wait
);
1123 cb
= (struct smscore_buffer_t
*) coredev
->buffers
.next
;
1124 list_del(&cb
->entry
);
1126 spin_unlock_irqrestore(&coredev
->bufferslock
, flags
);
1130 EXPORT_SYMBOL_GPL(smscore_getbuffer
);
1133 * return buffer descriptor to a pool
1135 * @param coredev pointer to a coredev object returned by
1136 * smscore_register_device
1137 * @param cb pointer buffer descriptor
1140 void smscore_putbuffer(struct smscore_device_t
*coredev
,
1141 struct smscore_buffer_t
*cb
) {
1142 wake_up_interruptible(&coredev
->buffer_mng_waitq
);
1143 list_add_locked(&cb
->entry
, &coredev
->buffers
, &coredev
->bufferslock
);
1145 EXPORT_SYMBOL_GPL(smscore_putbuffer
);
1147 static int smscore_validate_client(struct smscore_device_t
*coredev
,
1148 struct smscore_client_t
*client
,
1149 int data_type
, int id
)
1151 struct smscore_idlist_t
*listentry
;
1152 struct smscore_client_t
*registered_client
;
1155 sms_err("bad parameter.");
1158 registered_client
= smscore_find_client(coredev
, data_type
, id
);
1159 if (registered_client
== client
)
1162 if (registered_client
) {
1163 sms_err("The msg ID already registered to another client.");
1166 listentry
= kzalloc(sizeof(struct smscore_idlist_t
), GFP_KERNEL
);
1168 sms_err("Can't allocate memory for client id.");
1172 listentry
->data_type
= data_type
;
1173 list_add_locked(&listentry
->entry
, &client
->idlist
,
1174 &coredev
->clientslock
);
1179 * creates smsclient object, check that id is taken by another client
1181 * @param coredev pointer to a coredev object from clients hotplug
1182 * @param initial_id all messages with this id would be sent to this client
1183 * @param data_type all messages of this type would be sent to this client
1184 * @param onresponse_handler client handler that is called to
1185 * process incoming messages
1186 * @param onremove_handler client handler that is called when device is removed
1187 * @param context client-specific context
1188 * @param client pointer to a value that receives created smsclient object
1190 * @return 0 on success, <0 on error.
1192 int smscore_register_client(struct smscore_device_t
*coredev
,
1193 struct smsclient_params_t
*params
,
1194 struct smscore_client_t
**client
)
1196 struct smscore_client_t
*newclient
;
1197 /* check that no other channel with same parameters exists */
1198 if (smscore_find_client(coredev
, params
->data_type
,
1199 params
->initial_id
)) {
1200 sms_err("Client already exist.");
1204 newclient
= kzalloc(sizeof(struct smscore_client_t
), GFP_KERNEL
);
1206 sms_err("Failed to allocate memory for client.");
1210 INIT_LIST_HEAD(&newclient
->idlist
);
1211 newclient
->coredev
= coredev
;
1212 newclient
->onresponse_handler
= params
->onresponse_handler
;
1213 newclient
->onremove_handler
= params
->onremove_handler
;
1214 newclient
->context
= params
->context
;
1215 list_add_locked(&newclient
->entry
, &coredev
->clients
,
1216 &coredev
->clientslock
);
1217 smscore_validate_client(coredev
, newclient
, params
->data_type
,
1218 params
->initial_id
);
1219 *client
= newclient
;
1220 sms_debug("%p %d %d", params
->context
, params
->data_type
,
1221 params
->initial_id
);
1225 EXPORT_SYMBOL_GPL(smscore_register_client
);
1228 * frees smsclient object and all subclients associated with it
1230 * @param client pointer to smsclient object returned by
1231 * smscore_register_client
1234 void smscore_unregister_client(struct smscore_client_t
*client
)
1236 struct smscore_device_t
*coredev
= client
->coredev
;
1237 unsigned long flags
;
1239 spin_lock_irqsave(&coredev
->clientslock
, flags
);
1242 while (!list_empty(&client
->idlist
)) {
1243 struct smscore_idlist_t
*identry
=
1244 (struct smscore_idlist_t
*) client
->idlist
.next
;
1245 list_del(&identry
->entry
);
1249 sms_info("%p", client
->context
);
1251 list_del(&client
->entry
);
1254 spin_unlock_irqrestore(&coredev
->clientslock
, flags
);
1256 EXPORT_SYMBOL_GPL(smscore_unregister_client
);
1259 * verifies that source id is not taken by another client,
1260 * calls device handler to send requests to the device
1262 * @param client pointer to smsclient object returned by
1263 * smscore_register_client
1264 * @param buffer pointer to a request buffer
1265 * @param size size (in bytes) of request buffer
1267 * @return 0 on success, <0 on error.
1269 int smsclient_sendrequest(struct smscore_client_t
*client
,
1270 void *buffer
, size_t size
)
1272 struct smscore_device_t
*coredev
;
1273 struct SmsMsgHdr_ST
*phdr
= (struct SmsMsgHdr_ST
*) buffer
;
1276 if (client
== NULL
) {
1277 sms_err("Got NULL client");
1281 coredev
= client
->coredev
;
1283 /* check that no other channel with same id exists */
1284 if (coredev
== NULL
) {
1285 sms_err("Got NULL coredev");
1289 rc
= smscore_validate_client(client
->coredev
, client
, 0,
1294 return coredev
->sendrequest_handler(coredev
->context
, buffer
, size
);
1296 EXPORT_SYMBOL_GPL(smsclient_sendrequest
);
1299 /* old GPIO managments implementation */
1300 int smscore_configure_gpio(struct smscore_device_t
*coredev
, u32 pin
,
1301 struct smscore_config_gpio
*pinconfig
)
1304 struct SmsMsgHdr_ST hdr
;
1308 if (coredev
->device_flags
& SMS_DEVICE_FAMILY2
) {
1309 msg
.hdr
.msgSrcId
= DVBT_BDA_CONTROL_MSG_ID
;
1310 msg
.hdr
.msgDstId
= HIF_TASK
;
1311 msg
.hdr
.msgFlags
= 0;
1312 msg
.hdr
.msgType
= MSG_SMS_GPIO_CONFIG_EX_REQ
;
1313 msg
.hdr
.msgLength
= sizeof(msg
);
1316 msg
.data
[1] = pinconfig
->pullupdown
;
1318 /* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */
1319 msg
.data
[2] = pinconfig
->outputslewrate
== 0 ? 3 : 0;
1321 switch (pinconfig
->outputdriving
) {
1322 case SMS_GPIO_OUTPUTDRIVING_16mA
:
1323 msg
.data
[3] = 7; /* Nova - 16mA */
1325 case SMS_GPIO_OUTPUTDRIVING_12mA
:
1326 msg
.data
[3] = 5; /* Nova - 11mA */
1328 case SMS_GPIO_OUTPUTDRIVING_8mA
:
1329 msg
.data
[3] = 3; /* Nova - 7mA */
1331 case SMS_GPIO_OUTPUTDRIVING_4mA
:
1333 msg
.data
[3] = 2; /* Nova - 4mA */
1337 msg
.data
[4] = pinconfig
->direction
;
1339 } else /* TODO: SMS_DEVICE_FAMILY1 */
1342 return coredev
->sendrequest_handler(coredev
->context
,
1346 int smscore_set_gpio(struct smscore_device_t
*coredev
, u32 pin
, int level
)
1349 struct SmsMsgHdr_ST hdr
;
1353 if (pin
> MAX_GPIO_PIN_NUMBER
)
1356 msg
.hdr
.msgSrcId
= DVBT_BDA_CONTROL_MSG_ID
;
1357 msg
.hdr
.msgDstId
= HIF_TASK
;
1358 msg
.hdr
.msgFlags
= 0;
1359 msg
.hdr
.msgType
= MSG_SMS_GPIO_SET_LEVEL_REQ
;
1360 msg
.hdr
.msgLength
= sizeof(msg
);
1363 msg
.data
[1] = level
? 1 : 0;
1366 return coredev
->sendrequest_handler(coredev
->context
,
1370 /* new GPIO management implementation */
1371 static int GetGpioPinParams(u32 PinNum
, u32
*pTranslatedPinNum
,
1372 u32
*pGroupNum
, u32
*pGroupCfg
) {
1376 if (PinNum
>= 0 && PinNum
<= 1) {
1377 *pTranslatedPinNum
= 0;
1380 } else if (PinNum
>= 2 && PinNum
<= 6) {
1381 *pTranslatedPinNum
= 2;
1384 } else if (PinNum
>= 7 && PinNum
<= 11) {
1385 *pTranslatedPinNum
= 7;
1387 } else if (PinNum
>= 12 && PinNum
<= 15) {
1388 *pTranslatedPinNum
= 12;
1391 } else if (PinNum
== 16) {
1392 *pTranslatedPinNum
= 16;
1394 } else if (PinNum
>= 17 && PinNum
<= 24) {
1395 *pTranslatedPinNum
= 17;
1397 } else if (PinNum
== 25) {
1398 *pTranslatedPinNum
= 25;
1400 } else if (PinNum
>= 26 && PinNum
<= 28) {
1401 *pTranslatedPinNum
= 26;
1403 } else if (PinNum
== 29) {
1404 *pTranslatedPinNum
= 29;
1407 } else if (PinNum
== 30) {
1408 *pTranslatedPinNum
= 30;
1410 } else if (PinNum
== 31) {
1411 *pTranslatedPinNum
= 31;
1421 int smscore_gpio_configure(struct smscore_device_t
*coredev
, u8 PinNum
,
1422 struct smscore_gpio_config
*pGpioConfig
) {
1425 u32 TranslatedPinNum
= 0;
1433 struct SmsMsgHdr_ST xMsgHeader
;
1438 if (PinNum
> MAX_GPIO_PIN_NUMBER
)
1441 if (pGpioConfig
== NULL
)
1444 totalLen
= sizeof(struct SmsMsgHdr_ST
) + (sizeof(u32
) * 6);
1446 buffer
= kmalloc(totalLen
+ SMS_DMA_ALIGNMENT
,
1447 GFP_KERNEL
| GFP_DMA
);
1451 pMsg
= (struct SetGpioMsg
*) SMS_ALIGN_ADDRESS(buffer
);
1453 pMsg
->xMsgHeader
.msgSrcId
= DVBT_BDA_CONTROL_MSG_ID
;
1454 pMsg
->xMsgHeader
.msgDstId
= HIF_TASK
;
1455 pMsg
->xMsgHeader
.msgFlags
= 0;
1456 pMsg
->xMsgHeader
.msgLength
= (u16
) totalLen
;
1457 pMsg
->msgData
[0] = PinNum
;
1459 if (!(coredev
->device_flags
& SMS_DEVICE_FAMILY2
)) {
1460 pMsg
->xMsgHeader
.msgType
= MSG_SMS_GPIO_CONFIG_REQ
;
1461 if (GetGpioPinParams(PinNum
, &TranslatedPinNum
, &GroupNum
,
1465 pMsg
->msgData
[1] = TranslatedPinNum
;
1466 pMsg
->msgData
[2] = GroupNum
;
1467 ElectricChar
= (pGpioConfig
->PullUpDown
)
1468 | (pGpioConfig
->InputCharacteristics
<< 2)
1469 | (pGpioConfig
->OutputSlewRate
<< 3)
1470 | (pGpioConfig
->OutputDriving
<< 4);
1471 pMsg
->msgData
[3] = ElectricChar
;
1472 pMsg
->msgData
[4] = pGpioConfig
->Direction
;
1473 pMsg
->msgData
[5] = groupCfg
;
1475 pMsg
->xMsgHeader
.msgType
= MSG_SMS_GPIO_CONFIG_EX_REQ
;
1476 pMsg
->msgData
[1] = pGpioConfig
->PullUpDown
;
1477 pMsg
->msgData
[2] = pGpioConfig
->OutputSlewRate
;
1478 pMsg
->msgData
[3] = pGpioConfig
->OutputDriving
;
1479 pMsg
->msgData
[4] = pGpioConfig
->Direction
;
1480 pMsg
->msgData
[5] = 0;
1483 smsendian_handle_tx_message((struct SmsMsgHdr_ST
*)pMsg
);
1484 rc
= smscore_sendrequest_and_wait(coredev
, pMsg
, totalLen
,
1485 &coredev
->gpio_configuration_done
);
1489 sms_err("smscore_gpio_configure timeout");
1491 sms_err("smscore_gpio_configure error");
1498 int smscore_gpio_set_level(struct smscore_device_t
*coredev
, u8 PinNum
,
1506 struct SmsMsgHdr_ST xMsgHeader
;
1507 u32 msgData
[3]; /* keep it 3 ! */
1510 if ((NewLevel
> 1) || (PinNum
> MAX_GPIO_PIN_NUMBER
) ||
1511 (PinNum
> MAX_GPIO_PIN_NUMBER
))
1514 totalLen
= sizeof(struct SmsMsgHdr_ST
) +
1515 (3 * sizeof(u32
)); /* keep it 3 ! */
1517 buffer
= kmalloc(totalLen
+ SMS_DMA_ALIGNMENT
,
1518 GFP_KERNEL
| GFP_DMA
);
1522 pMsg
= (struct SetGpioMsg
*) SMS_ALIGN_ADDRESS(buffer
);
1524 pMsg
->xMsgHeader
.msgSrcId
= DVBT_BDA_CONTROL_MSG_ID
;
1525 pMsg
->xMsgHeader
.msgDstId
= HIF_TASK
;
1526 pMsg
->xMsgHeader
.msgFlags
= 0;
1527 pMsg
->xMsgHeader
.msgType
= MSG_SMS_GPIO_SET_LEVEL_REQ
;
1528 pMsg
->xMsgHeader
.msgLength
= (u16
) totalLen
;
1529 pMsg
->msgData
[0] = PinNum
;
1530 pMsg
->msgData
[1] = NewLevel
;
1532 /* Send message to SMS */
1533 smsendian_handle_tx_message((struct SmsMsgHdr_ST
*)pMsg
);
1534 rc
= smscore_sendrequest_and_wait(coredev
, pMsg
, totalLen
,
1535 &coredev
->gpio_set_level_done
);
1539 sms_err("smscore_gpio_set_level timeout");
1541 sms_err("smscore_gpio_set_level error");
1548 int smscore_gpio_get_level(struct smscore_device_t
*coredev
, u8 PinNum
,
1556 struct SmsMsgHdr_ST xMsgHeader
;
1561 if (PinNum
> MAX_GPIO_PIN_NUMBER
)
1564 totalLen
= sizeof(struct SmsMsgHdr_ST
) + (2 * sizeof(u32
));
1566 buffer
= kmalloc(totalLen
+ SMS_DMA_ALIGNMENT
,
1567 GFP_KERNEL
| GFP_DMA
);
1571 pMsg
= (struct SetGpioMsg
*) SMS_ALIGN_ADDRESS(buffer
);
1573 pMsg
->xMsgHeader
.msgSrcId
= DVBT_BDA_CONTROL_MSG_ID
;
1574 pMsg
->xMsgHeader
.msgDstId
= HIF_TASK
;
1575 pMsg
->xMsgHeader
.msgFlags
= 0;
1576 pMsg
->xMsgHeader
.msgType
= MSG_SMS_GPIO_GET_LEVEL_REQ
;
1577 pMsg
->xMsgHeader
.msgLength
= (u16
) totalLen
;
1578 pMsg
->msgData
[0] = PinNum
;
1579 pMsg
->msgData
[1] = 0;
1581 /* Send message to SMS */
1582 smsendian_handle_tx_message((struct SmsMsgHdr_ST
*)pMsg
);
1583 rc
= smscore_sendrequest_and_wait(coredev
, pMsg
, totalLen
,
1584 &coredev
->gpio_get_level_done
);
1588 sms_err("smscore_gpio_get_level timeout");
1590 sms_err("smscore_gpio_get_level error");
1594 /* Its a race between other gpio_get_level() and the copy of the single
1595 * global 'coredev->gpio_get_res' to the function's variable 'level'
1597 *level
= coredev
->gpio_get_res
;
1602 static int __init
smscore_module_init(void)
1606 INIT_LIST_HEAD(&g_smscore_notifyees
);
1607 INIT_LIST_HEAD(&g_smscore_devices
);
1608 kmutex_init(&g_smscore_deviceslock
);
1610 INIT_LIST_HEAD(&g_smscore_registry
);
1611 kmutex_init(&g_smscore_registrylock
);
1616 static void __exit
smscore_module_exit(void)
1618 kmutex_lock(&g_smscore_deviceslock
);
1619 while (!list_empty(&g_smscore_notifyees
)) {
1620 struct smscore_device_notifyee_t
*notifyee
=
1621 (struct smscore_device_notifyee_t
*)
1622 g_smscore_notifyees
.next
;
1624 list_del(¬ifyee
->entry
);
1627 kmutex_unlock(&g_smscore_deviceslock
);
1629 kmutex_lock(&g_smscore_registrylock
);
1630 while (!list_empty(&g_smscore_registry
)) {
1631 struct smscore_registry_entry_t
*entry
=
1632 (struct smscore_registry_entry_t
*)
1633 g_smscore_registry
.next
;
1635 list_del(&entry
->entry
);
1638 kmutex_unlock(&g_smscore_registrylock
);
1643 module_init(smscore_module_init
);
1644 module_exit(smscore_module_exit
);
1646 MODULE_DESCRIPTION("Siano MDTV Core module");
1647 MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
1648 MODULE_LICENSE("GPL");