1 /*
2  *  Siano core API module
3  *
4  *  This file contains implementation for the interface to sms core component
5  *
6  *  author: Uri Shkolnik
7  *
8  *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License version 2 as
12  *  published by the Free Software Foundation;
13  *
14  *  Software distributed under the License is distributed on an "AS IS"
15  *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
16  *
17  *  See the GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23 
24 #include "smscoreapi.h"
25 
26 #include <linux/kernel.h>
27 #include <linux/init.h>
28 #include <linux/module.h>
29 #include <linux/moduleparam.h>
30 #include <linux/dma-mapping.h>
31 #include <linux/delay.h>
32 #include <linux/io.h>
33 #include <linux/slab.h>
34 
35 #include <linux/firmware.h>
36 #include <linux/wait.h>
37 #include <asm/byteorder.h>
38 
39 #include "sms-cards.h"
40 #include "smsir.h"
41 
42 struct smscore_device_notifyee_t {
43 	struct list_head entry;
44 	hotplug_t hotplug;
45 };
46 
47 struct smscore_idlist_t {
48 	struct list_head entry;
49 	int		id;
50 	int		data_type;
51 };
52 
53 struct smscore_client_t {
54 	struct list_head entry;
55 	struct smscore_device_t *coredev;
56 	void			*context;
57 	struct list_head	idlist;
58 	onresponse_t		onresponse_handler;
59 	onremove_t		onremove_handler;
60 };
61 
62 static char *siano_msgs[] = {
63 	[MSG_TYPE_BASE_VAL                           - MSG_TYPE_BASE_VAL] = "MSG_TYPE_BASE_VAL",
64 	[MSG_SMS_GET_VERSION_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_REQ",
65 	[MSG_SMS_GET_VERSION_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_RES",
66 	[MSG_SMS_MULTI_BRIDGE_CFG                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MULTI_BRIDGE_CFG",
67 	[MSG_SMS_GPIO_CONFIG_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_REQ",
68 	[MSG_SMS_GPIO_CONFIG_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_RES",
69 	[MSG_SMS_GPIO_SET_LEVEL_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_SET_LEVEL_REQ",
70 	[MSG_SMS_GPIO_SET_LEVEL_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_SET_LEVEL_RES",
71 	[MSG_SMS_GPIO_GET_LEVEL_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_GET_LEVEL_REQ",
72 	[MSG_SMS_GPIO_GET_LEVEL_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_GET_LEVEL_RES",
73 	[MSG_SMS_EEPROM_BURN_IND                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EEPROM_BURN_IND",
74 	[MSG_SMS_LOG_ENABLE_CHANGE_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_ENABLE_CHANGE_REQ",
75 	[MSG_SMS_LOG_ENABLE_CHANGE_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_ENABLE_CHANGE_RES",
76 	[MSG_SMS_SET_MAX_TX_MSG_LEN_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_MAX_TX_MSG_LEN_REQ",
77 	[MSG_SMS_SET_MAX_TX_MSG_LEN_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_MAX_TX_MSG_LEN_RES",
78 	[MSG_SMS_SPI_HALFDUPLEX_TOKEN_HOST_TO_DEVICE - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_HALFDUPLEX_TOKEN_HOST_TO_DEVICE",
79 	[MSG_SMS_SPI_HALFDUPLEX_TOKEN_DEVICE_TO_HOST - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_HALFDUPLEX_TOKEN_DEVICE_TO_HOST",
80 	[MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_REQ     - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_REQ",
81 	[MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_RES     - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_FLAG_CHANGE_RES",
82 	[MSG_SMS_BACKGROUND_SCAN_SIGNAL_DETECTED_IND - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_SIGNAL_DETECTED_IND",
83 	[MSG_SMS_BACKGROUND_SCAN_NO_SIGNAL_IND       - MSG_TYPE_BASE_VAL] = "MSG_SMS_BACKGROUND_SCAN_NO_SIGNAL_IND",
84 	[MSG_SMS_CONFIGURE_RF_SWITCH_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIGURE_RF_SWITCH_REQ",
85 	[MSG_SMS_CONFIGURE_RF_SWITCH_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIGURE_RF_SWITCH_RES",
86 	[MSG_SMS_MRC_PATH_DISCONNECT_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_PATH_DISCONNECT_REQ",
87 	[MSG_SMS_MRC_PATH_DISCONNECT_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_PATH_DISCONNECT_RES",
88 	[MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_REQ    - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_REQ",
89 	[MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_RES    - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_1SEG_THROUGH_FULLSEG_RES",
90 	[MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_REQ       - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_REQ",
91 	[MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_RES       - MSG_TYPE_BASE_VAL] = "MSG_SMS_RECEIVE_VHF_VIA_VHF_INPUT_RES",
92 	[MSG_WR_REG_RFT_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_WR_REG_RFT_REQ",
93 	[MSG_WR_REG_RFT_RES                          - MSG_TYPE_BASE_VAL] = "MSG_WR_REG_RFT_RES",
94 	[MSG_RD_REG_RFT_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_RFT_REQ",
95 	[MSG_RD_REG_RFT_RES                          - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_RFT_RES",
96 	[MSG_RD_REG_ALL_RFT_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_ALL_RFT_REQ",
97 	[MSG_RD_REG_ALL_RFT_RES                      - MSG_TYPE_BASE_VAL] = "MSG_RD_REG_ALL_RFT_RES",
98 	[MSG_HELP_INT                                - MSG_TYPE_BASE_VAL] = "MSG_HELP_INT",
99 	[MSG_RUN_SCRIPT_INT                          - MSG_TYPE_BASE_VAL] = "MSG_RUN_SCRIPT_INT",
100 	[MSG_SMS_EWS_INBAND_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_EWS_INBAND_REQ",
101 	[MSG_SMS_EWS_INBAND_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_EWS_INBAND_RES",
102 	[MSG_SMS_RFS_SELECT_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_RFS_SELECT_REQ",
103 	[MSG_SMS_RFS_SELECT_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_RFS_SELECT_RES",
104 	[MSG_SMS_MB_GET_VER_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_GET_VER_REQ",
105 	[MSG_SMS_MB_GET_VER_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_GET_VER_RES",
106 	[MSG_SMS_MB_WRITE_CFGFILE_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_WRITE_CFGFILE_REQ",
107 	[MSG_SMS_MB_WRITE_CFGFILE_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_WRITE_CFGFILE_RES",
108 	[MSG_SMS_MB_READ_CFGFILE_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_READ_CFGFILE_REQ",
109 	[MSG_SMS_MB_READ_CFGFILE_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_READ_CFGFILE_RES",
110 	[MSG_SMS_RD_MEM_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_RD_MEM_REQ",
111 	[MSG_SMS_RD_MEM_RES                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_RD_MEM_RES",
112 	[MSG_SMS_WR_MEM_REQ                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_WR_MEM_REQ",
113 	[MSG_SMS_WR_MEM_RES                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_WR_MEM_RES",
114 	[MSG_SMS_UPDATE_MEM_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_UPDATE_MEM_REQ",
115 	[MSG_SMS_UPDATE_MEM_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_UPDATE_MEM_RES",
116 	[MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_REQ    - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_REQ",
117 	[MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_RES    - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_FULL_PARAMS_SET_RES",
118 	[MSG_SMS_RF_TUNE_REQ                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_RF_TUNE_REQ",
119 	[MSG_SMS_RF_TUNE_RES                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_RF_TUNE_RES",
120 	[MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_REQ      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_REQ",
121 	[MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_RES      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_ENABLE_HIGH_MOBILITY_RES",
122 	[MSG_SMS_ISDBT_SB_RECEPTION_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_SB_RECEPTION_REQ",
123 	[MSG_SMS_ISDBT_SB_RECEPTION_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_SB_RECEPTION_RES",
124 	[MSG_SMS_GENERIC_EPROM_WRITE_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_WRITE_REQ",
125 	[MSG_SMS_GENERIC_EPROM_WRITE_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_WRITE_RES",
126 	[MSG_SMS_GENERIC_EPROM_READ_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_READ_REQ",
127 	[MSG_SMS_GENERIC_EPROM_READ_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_EPROM_READ_RES",
128 	[MSG_SMS_EEPROM_WRITE_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_EEPROM_WRITE_REQ",
129 	[MSG_SMS_EEPROM_WRITE_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_EEPROM_WRITE_RES",
130 	[MSG_SMS_CUSTOM_READ_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_READ_REQ",
131 	[MSG_SMS_CUSTOM_READ_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_READ_RES",
132 	[MSG_SMS_CUSTOM_WRITE_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_WRITE_REQ",
133 	[MSG_SMS_CUSTOM_WRITE_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_CUSTOM_WRITE_RES",
134 	[MSG_SMS_INIT_DEVICE_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_INIT_DEVICE_REQ",
135 	[MSG_SMS_INIT_DEVICE_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_INIT_DEVICE_RES",
136 	[MSG_SMS_ATSC_SET_ALL_IP_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_SET_ALL_IP_REQ",
137 	[MSG_SMS_ATSC_SET_ALL_IP_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_SET_ALL_IP_RES",
138 	[MSG_SMS_ATSC_START_ENSEMBLE_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_START_ENSEMBLE_REQ",
139 	[MSG_SMS_ATSC_START_ENSEMBLE_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_START_ENSEMBLE_RES",
140 	[MSG_SMS_SET_OUTPUT_MODE_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_OUTPUT_MODE_REQ",
141 	[MSG_SMS_SET_OUTPUT_MODE_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_OUTPUT_MODE_RES",
142 	[MSG_SMS_ATSC_IP_FILTER_GET_LIST_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_GET_LIST_REQ",
143 	[MSG_SMS_ATSC_IP_FILTER_GET_LIST_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_GET_LIST_RES",
144 	[MSG_SMS_SUB_CHANNEL_START_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_START_REQ",
145 	[MSG_SMS_SUB_CHANNEL_START_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_START_RES",
146 	[MSG_SMS_SUB_CHANNEL_STOP_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_STOP_REQ",
147 	[MSG_SMS_SUB_CHANNEL_STOP_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SUB_CHANNEL_STOP_RES",
148 	[MSG_SMS_ATSC_IP_FILTER_ADD_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_ADD_REQ",
149 	[MSG_SMS_ATSC_IP_FILTER_ADD_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_ADD_RES",
150 	[MSG_SMS_ATSC_IP_FILTER_REMOVE_REQ           - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_REQ",
151 	[MSG_SMS_ATSC_IP_FILTER_REMOVE_RES           - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_RES",
152 	[MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_REQ       - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_REQ",
153 	[MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_RES       - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_IP_FILTER_REMOVE_ALL_RES",
154 	[MSG_SMS_WAIT_CMD                            - MSG_TYPE_BASE_VAL] = "MSG_SMS_WAIT_CMD",
155 	[MSG_SMS_ADD_PID_FILTER_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_ADD_PID_FILTER_REQ",
156 	[MSG_SMS_ADD_PID_FILTER_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_ADD_PID_FILTER_RES",
157 	[MSG_SMS_REMOVE_PID_FILTER_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_REMOVE_PID_FILTER_REQ",
158 	[MSG_SMS_REMOVE_PID_FILTER_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_REMOVE_PID_FILTER_RES",
159 	[MSG_SMS_FAST_INFORMATION_CHANNEL_REQ        - MSG_TYPE_BASE_VAL] = "MSG_SMS_FAST_INFORMATION_CHANNEL_REQ",
160 	[MSG_SMS_FAST_INFORMATION_CHANNEL_RES        - MSG_TYPE_BASE_VAL] = "MSG_SMS_FAST_INFORMATION_CHANNEL_RES",
161 	[MSG_SMS_DAB_CHANNEL                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_DAB_CHANNEL",
162 	[MSG_SMS_GET_PID_FILTER_LIST_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_PID_FILTER_LIST_REQ",
163 	[MSG_SMS_GET_PID_FILTER_LIST_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_PID_FILTER_LIST_RES",
164 	[MSG_SMS_POWER_DOWN_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_REQ",
165 	[MSG_SMS_POWER_DOWN_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_RES",
166 	[MSG_SMS_ATSC_SLT_EXIST_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_SLT_EXIST_IND",
167 	[MSG_SMS_ATSC_NO_SLT_IND                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_ATSC_NO_SLT_IND",
168 	[MSG_SMS_GET_STATISTICS_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_REQ",
169 	[MSG_SMS_GET_STATISTICS_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_RES",
170 	[MSG_SMS_SEND_DUMP                           - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_DUMP",
171 	[MSG_SMS_SCAN_START_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_START_REQ",
172 	[MSG_SMS_SCAN_START_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_START_RES",
173 	[MSG_SMS_SCAN_STOP_REQ                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_STOP_REQ",
174 	[MSG_SMS_SCAN_STOP_RES                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_STOP_RES",
175 	[MSG_SMS_SCAN_PROGRESS_IND                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_PROGRESS_IND",
176 	[MSG_SMS_SCAN_COMPLETE_IND                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_SCAN_COMPLETE_IND",
177 	[MSG_SMS_LOG_ITEM                            - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_ITEM",
178 	[MSG_SMS_DAB_SUBCHANNEL_RECONFIG_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_DAB_SUBCHANNEL_RECONFIG_REQ",
179 	[MSG_SMS_DAB_SUBCHANNEL_RECONFIG_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_DAB_SUBCHANNEL_RECONFIG_RES",
180 	[MSG_SMS_HO_PER_SLICES_IND                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PER_SLICES_IND",
181 	[MSG_SMS_HO_INBAND_POWER_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_INBAND_POWER_IND",
182 	[MSG_SMS_MANUAL_DEMOD_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MANUAL_DEMOD_REQ",
183 	[MSG_SMS_HO_TUNE_ON_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_ON_REQ",
184 	[MSG_SMS_HO_TUNE_ON_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_ON_RES",
185 	[MSG_SMS_HO_TUNE_OFF_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_OFF_REQ",
186 	[MSG_SMS_HO_TUNE_OFF_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_TUNE_OFF_RES",
187 	[MSG_SMS_HO_PEEK_FREQ_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PEEK_FREQ_REQ",
188 	[MSG_SMS_HO_PEEK_FREQ_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PEEK_FREQ_RES",
189 	[MSG_SMS_HO_PEEK_FREQ_IND                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_HO_PEEK_FREQ_IND",
190 	[MSG_SMS_MB_ATTEN_SET_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_ATTEN_SET_REQ",
191 	[MSG_SMS_MB_ATTEN_SET_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_MB_ATTEN_SET_RES",
192 	[MSG_SMS_ENABLE_STAT_IN_I2C_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENABLE_STAT_IN_I2C_REQ",
193 	[MSG_SMS_ENABLE_STAT_IN_I2C_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENABLE_STAT_IN_I2C_RES",
194 	[MSG_SMS_SET_ANTENNA_CONFIG_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_ANTENNA_CONFIG_REQ",
195 	[MSG_SMS_SET_ANTENNA_CONFIG_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_ANTENNA_CONFIG_RES",
196 	[MSG_SMS_GET_STATISTICS_EX_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_EX_REQ",
197 	[MSG_SMS_GET_STATISTICS_EX_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_STATISTICS_EX_RES",
198 	[MSG_SMS_SLEEP_RESUME_COMP_IND               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SLEEP_RESUME_COMP_IND",
199 	[MSG_SMS_SWITCH_HOST_INTERFACE_REQ           - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWITCH_HOST_INTERFACE_REQ",
200 	[MSG_SMS_SWITCH_HOST_INTERFACE_RES           - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWITCH_HOST_INTERFACE_RES",
201 	[MSG_SMS_DATA_DOWNLOAD_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_DOWNLOAD_REQ",
202 	[MSG_SMS_DATA_DOWNLOAD_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_DOWNLOAD_RES",
203 	[MSG_SMS_DATA_VALIDITY_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_VALIDITY_REQ",
204 	[MSG_SMS_DATA_VALIDITY_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_VALIDITY_RES",
205 	[MSG_SMS_SWDOWNLOAD_TRIGGER_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_TRIGGER_REQ",
206 	[MSG_SMS_SWDOWNLOAD_TRIGGER_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_TRIGGER_RES",
207 	[MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ",
208 	[MSG_SMS_SWDOWNLOAD_BACKDOOR_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_SWDOWNLOAD_BACKDOOR_RES",
209 	[MSG_SMS_GET_VERSION_EX_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_EX_REQ",
210 	[MSG_SMS_GET_VERSION_EX_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_VERSION_EX_RES",
211 	[MSG_SMS_CLOCK_OUTPUT_CONFIG_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CLOCK_OUTPUT_CONFIG_REQ",
212 	[MSG_SMS_CLOCK_OUTPUT_CONFIG_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_CLOCK_OUTPUT_CONFIG_RES",
213 	[MSG_SMS_I2C_SET_FREQ_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_I2C_SET_FREQ_REQ",
214 	[MSG_SMS_I2C_SET_FREQ_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_I2C_SET_FREQ_RES",
215 	[MSG_SMS_GENERIC_I2C_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_I2C_REQ",
216 	[MSG_SMS_GENERIC_I2C_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_GENERIC_I2C_RES",
217 	[MSG_SMS_DVBT_BDA_DATA                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DVBT_BDA_DATA",
218 	[MSG_SW_RELOAD_REQ                           - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_REQ",
219 	[MSG_SMS_DATA_MSG                            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_MSG",
220 	[MSG_TABLE_UPLOAD_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_TABLE_UPLOAD_REQ",
221 	[MSG_TABLE_UPLOAD_RES                        - MSG_TYPE_BASE_VAL] = "MSG_TABLE_UPLOAD_RES",
222 	[MSG_SW_RELOAD_START_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_START_REQ",
223 	[MSG_SW_RELOAD_START_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_START_RES",
224 	[MSG_SW_RELOAD_EXEC_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_EXEC_REQ",
225 	[MSG_SW_RELOAD_EXEC_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SW_RELOAD_EXEC_RES",
226 	[MSG_SMS_SPI_INT_LINE_SET_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_INT_LINE_SET_REQ",
227 	[MSG_SMS_SPI_INT_LINE_SET_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_INT_LINE_SET_RES",
228 	[MSG_SMS_GPIO_CONFIG_EX_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_EX_REQ",
229 	[MSG_SMS_GPIO_CONFIG_EX_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_GPIO_CONFIG_EX_RES",
230 	[MSG_SMS_WATCHDOG_ACT_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_WATCHDOG_ACT_REQ",
231 	[MSG_SMS_WATCHDOG_ACT_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_WATCHDOG_ACT_RES",
232 	[MSG_SMS_LOOPBACK_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOOPBACK_REQ",
233 	[MSG_SMS_LOOPBACK_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOOPBACK_RES",
234 	[MSG_SMS_RAW_CAPTURE_START_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_START_REQ",
235 	[MSG_SMS_RAW_CAPTURE_START_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_START_RES",
236 	[MSG_SMS_RAW_CAPTURE_ABORT_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_ABORT_REQ",
237 	[MSG_SMS_RAW_CAPTURE_ABORT_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_ABORT_RES",
238 	[MSG_SMS_RAW_CAPTURE_COMPLETE_IND            - MSG_TYPE_BASE_VAL] = "MSG_SMS_RAW_CAPTURE_COMPLETE_IND",
239 	[MSG_SMS_DATA_PUMP_IND                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_PUMP_IND",
240 	[MSG_SMS_DATA_PUMP_REQ                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_PUMP_REQ",
241 	[MSG_SMS_DATA_PUMP_RES                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_DATA_PUMP_RES",
242 	[MSG_SMS_FLASH_DL_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_FLASH_DL_REQ",
243 	[MSG_SMS_EXEC_TEST_1_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXEC_TEST_1_REQ",
244 	[MSG_SMS_EXEC_TEST_1_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXEC_TEST_1_RES",
245 	[MSG_SMS_ENBALE_TS_INTERFACE_REQ             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENBALE_TS_INTERFACE_REQ",
246 	[MSG_SMS_ENBALE_TS_INTERFACE_RES             - MSG_TYPE_BASE_VAL] = "MSG_SMS_ENBALE_TS_INTERFACE_RES",
247 	[MSG_SMS_SPI_SET_BUS_WIDTH_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_SET_BUS_WIDTH_REQ",
248 	[MSG_SMS_SPI_SET_BUS_WIDTH_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SPI_SET_BUS_WIDTH_RES",
249 	[MSG_SMS_SEND_EMM_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_EMM_REQ",
250 	[MSG_SMS_SEND_EMM_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_EMM_RES",
251 	[MSG_SMS_DISABLE_TS_INTERFACE_REQ            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DISABLE_TS_INTERFACE_REQ",
252 	[MSG_SMS_DISABLE_TS_INTERFACE_RES            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DISABLE_TS_INTERFACE_RES",
253 	[MSG_SMS_IS_BUF_FREE_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_IS_BUF_FREE_REQ",
254 	[MSG_SMS_IS_BUF_FREE_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_IS_BUF_FREE_RES",
255 	[MSG_SMS_EXT_ANTENNA_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXT_ANTENNA_REQ",
256 	[MSG_SMS_EXT_ANTENNA_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXT_ANTENNA_RES",
257 	[MSG_SMS_CMMB_GET_NET_OF_FREQ_REQ_OBSOLETE   - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NET_OF_FREQ_REQ_OBSOLETE",
258 	[MSG_SMS_CMMB_GET_NET_OF_FREQ_RES_OBSOLETE   - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NET_OF_FREQ_RES_OBSOLETE",
259 	[MSG_SMS_BATTERY_LEVEL_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_BATTERY_LEVEL_REQ",
260 	[MSG_SMS_BATTERY_LEVEL_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_BATTERY_LEVEL_RES",
261 	[MSG_SMS_CMMB_INJECT_TABLE_REQ_OBSOLETE      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_INJECT_TABLE_REQ_OBSOLETE",
262 	[MSG_SMS_CMMB_INJECT_TABLE_RES_OBSOLETE      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_INJECT_TABLE_RES_OBSOLETE",
263 	[MSG_SMS_FM_RADIO_BLOCK_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_FM_RADIO_BLOCK_IND",
264 	[MSG_SMS_HOST_NOTIFICATION_IND               - MSG_TYPE_BASE_VAL] = "MSG_SMS_HOST_NOTIFICATION_IND",
265 	[MSG_SMS_CMMB_GET_CONTROL_TABLE_REQ_OBSOLETE - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_CONTROL_TABLE_REQ_OBSOLETE",
266 	[MSG_SMS_CMMB_GET_CONTROL_TABLE_RES_OBSOLETE - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_CONTROL_TABLE_RES_OBSOLETE",
267 	[MSG_SMS_CMMB_GET_NETWORKS_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NETWORKS_REQ",
268 	[MSG_SMS_CMMB_GET_NETWORKS_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_NETWORKS_RES",
269 	[MSG_SMS_CMMB_START_SERVICE_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_SERVICE_REQ",
270 	[MSG_SMS_CMMB_START_SERVICE_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_SERVICE_RES",
271 	[MSG_SMS_CMMB_STOP_SERVICE_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_SERVICE_REQ",
272 	[MSG_SMS_CMMB_STOP_SERVICE_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_SERVICE_RES",
273 	[MSG_SMS_CMMB_ADD_CHANNEL_FILTER_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_ADD_CHANNEL_FILTER_REQ",
274 	[MSG_SMS_CMMB_ADD_CHANNEL_FILTER_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_ADD_CHANNEL_FILTER_RES",
275 	[MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_REQ      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_REQ",
276 	[MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_RES      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_REMOVE_CHANNEL_FILTER_RES",
277 	[MSG_SMS_CMMB_START_CONTROL_INFO_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_CONTROL_INFO_REQ",
278 	[MSG_SMS_CMMB_START_CONTROL_INFO_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_START_CONTROL_INFO_RES",
279 	[MSG_SMS_CMMB_STOP_CONTROL_INFO_REQ          - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_CONTROL_INFO_REQ",
280 	[MSG_SMS_CMMB_STOP_CONTROL_INFO_RES          - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_STOP_CONTROL_INFO_RES",
281 	[MSG_SMS_ISDBT_TUNE_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_TUNE_REQ",
282 	[MSG_SMS_ISDBT_TUNE_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_ISDBT_TUNE_RES",
283 	[MSG_SMS_TRANSMISSION_IND                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_TRANSMISSION_IND",
284 	[MSG_SMS_PID_STATISTICS_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_PID_STATISTICS_IND",
285 	[MSG_SMS_POWER_DOWN_IND                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_IND",
286 	[MSG_SMS_POWER_DOWN_CONF                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_DOWN_CONF",
287 	[MSG_SMS_POWER_UP_IND                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_UP_IND",
288 	[MSG_SMS_POWER_UP_CONF                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_UP_CONF",
289 	[MSG_SMS_POWER_MODE_SET_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_MODE_SET_REQ",
290 	[MSG_SMS_POWER_MODE_SET_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_POWER_MODE_SET_RES",
291 	[MSG_SMS_DEBUG_HOST_EVENT_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DEBUG_HOST_EVENT_REQ",
292 	[MSG_SMS_DEBUG_HOST_EVENT_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DEBUG_HOST_EVENT_RES",
293 	[MSG_SMS_NEW_CRYSTAL_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_NEW_CRYSTAL_REQ",
294 	[MSG_SMS_NEW_CRYSTAL_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_NEW_CRYSTAL_RES",
295 	[MSG_SMS_CONFIG_SPI_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIG_SPI_REQ",
296 	[MSG_SMS_CONFIG_SPI_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_CONFIG_SPI_RES",
297 	[MSG_SMS_I2C_SHORT_STAT_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_I2C_SHORT_STAT_IND",
298 	[MSG_SMS_START_IR_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_START_IR_REQ",
299 	[MSG_SMS_START_IR_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_START_IR_RES",
300 	[MSG_SMS_IR_SAMPLES_IND                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_IR_SAMPLES_IND",
301 	[MSG_SMS_CMMB_CA_SERVICE_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_CA_SERVICE_IND",
302 	[MSG_SMS_SLAVE_DEVICE_DETECTED               - MSG_TYPE_BASE_VAL] = "MSG_SMS_SLAVE_DEVICE_DETECTED",
303 	[MSG_SMS_INTERFACE_LOCK_IND                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_INTERFACE_LOCK_IND",
304 	[MSG_SMS_INTERFACE_UNLOCK_IND                - MSG_TYPE_BASE_VAL] = "MSG_SMS_INTERFACE_UNLOCK_IND",
305 	[MSG_SMS_SEND_ROSUM_BUFF_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_ROSUM_BUFF_REQ",
306 	[MSG_SMS_SEND_ROSUM_BUFF_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_ROSUM_BUFF_RES",
307 	[MSG_SMS_ROSUM_BUFF                          - MSG_TYPE_BASE_VAL] = "MSG_SMS_ROSUM_BUFF",
308 	[MSG_SMS_SET_AES128_KEY_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_AES128_KEY_REQ",
309 	[MSG_SMS_SET_AES128_KEY_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_AES128_KEY_RES",
310 	[MSG_SMS_MBBMS_WRITE_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_MBBMS_WRITE_REQ",
311 	[MSG_SMS_MBBMS_WRITE_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_MBBMS_WRITE_RES",
312 	[MSG_SMS_MBBMS_READ_IND                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_MBBMS_READ_IND",
313 	[MSG_SMS_IQ_STREAM_START_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_START_REQ",
314 	[MSG_SMS_IQ_STREAM_START_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_START_RES",
315 	[MSG_SMS_IQ_STREAM_STOP_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_STOP_REQ",
316 	[MSG_SMS_IQ_STREAM_STOP_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_STOP_RES",
317 	[MSG_SMS_IQ_STREAM_DATA_BLOCK                - MSG_TYPE_BASE_VAL] = "MSG_SMS_IQ_STREAM_DATA_BLOCK",
318 	[MSG_SMS_GET_EEPROM_VERSION_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_EEPROM_VERSION_REQ",
319 	[MSG_SMS_GET_EEPROM_VERSION_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_GET_EEPROM_VERSION_RES",
320 	[MSG_SMS_SIGNAL_DETECTED_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SIGNAL_DETECTED_IND",
321 	[MSG_SMS_NO_SIGNAL_IND                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_NO_SIGNAL_IND",
322 	[MSG_SMS_MRC_SHUTDOWN_SLAVE_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_SHUTDOWN_SLAVE_REQ",
323 	[MSG_SMS_MRC_SHUTDOWN_SLAVE_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_SHUTDOWN_SLAVE_RES",
324 	[MSG_SMS_MRC_BRINGUP_SLAVE_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_BRINGUP_SLAVE_REQ",
325 	[MSG_SMS_MRC_BRINGUP_SLAVE_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_BRINGUP_SLAVE_RES",
326 	[MSG_SMS_EXTERNAL_LNA_CTRL_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXTERNAL_LNA_CTRL_REQ",
327 	[MSG_SMS_EXTERNAL_LNA_CTRL_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_EXTERNAL_LNA_CTRL_RES",
328 	[MSG_SMS_SET_PERIODIC_STATISTICS_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_PERIODIC_STATISTICS_REQ",
329 	[MSG_SMS_SET_PERIODIC_STATISTICS_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SET_PERIODIC_STATISTICS_RES",
330 	[MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_REQ        - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_REQ",
331 	[MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_RES        - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_AUTO_OUTPUT_TS0_RES",
332 	[LOCAL_TUNE                                  - MSG_TYPE_BASE_VAL] = "LOCAL_TUNE",
333 	[LOCAL_IFFT_H_ICI                            - MSG_TYPE_BASE_VAL] = "LOCAL_IFFT_H_ICI",
334 	[MSG_RESYNC_REQ                              - MSG_TYPE_BASE_VAL] = "MSG_RESYNC_REQ",
335 	[MSG_SMS_CMMB_GET_MRC_STATISTICS_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_MRC_STATISTICS_REQ",
336 	[MSG_SMS_CMMB_GET_MRC_STATISTICS_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_MRC_STATISTICS_RES",
337 	[MSG_SMS_LOG_EX_ITEM                         - MSG_TYPE_BASE_VAL] = "MSG_SMS_LOG_EX_ITEM",
338 	[MSG_SMS_DEVICE_DATA_LOSS_IND                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DEVICE_DATA_LOSS_IND",
339 	[MSG_SMS_MRC_WATCHDOG_TRIGGERED_IND          - MSG_TYPE_BASE_VAL] = "MSG_SMS_MRC_WATCHDOG_TRIGGERED_IND",
340 	[MSG_SMS_USER_MSG_REQ                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_USER_MSG_REQ",
341 	[MSG_SMS_USER_MSG_RES                        - MSG_TYPE_BASE_VAL] = "MSG_SMS_USER_MSG_RES",
342 	[MSG_SMS_SMART_CARD_INIT_REQ                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_INIT_REQ",
343 	[MSG_SMS_SMART_CARD_INIT_RES                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_INIT_RES",
344 	[MSG_SMS_SMART_CARD_WRITE_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_WRITE_REQ",
345 	[MSG_SMS_SMART_CARD_WRITE_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_WRITE_RES",
346 	[MSG_SMS_SMART_CARD_READ_IND                 - MSG_TYPE_BASE_VAL] = "MSG_SMS_SMART_CARD_READ_IND",
347 	[MSG_SMS_TSE_ENABLE_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_TSE_ENABLE_REQ",
348 	[MSG_SMS_TSE_ENABLE_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_TSE_ENABLE_RES",
349 	[MSG_SMS_CMMB_GET_SHORT_STATISTICS_REQ       - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_SHORT_STATISTICS_REQ",
350 	[MSG_SMS_CMMB_GET_SHORT_STATISTICS_RES       - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_GET_SHORT_STATISTICS_RES",
351 	[MSG_SMS_LED_CONFIG_REQ                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_LED_CONFIG_REQ",
352 	[MSG_SMS_LED_CONFIG_RES                      - MSG_TYPE_BASE_VAL] = "MSG_SMS_LED_CONFIG_RES",
353 	[MSG_PWM_ANTENNA_REQ                         - MSG_TYPE_BASE_VAL] = "MSG_PWM_ANTENNA_REQ",
354 	[MSG_PWM_ANTENNA_RES                         - MSG_TYPE_BASE_VAL] = "MSG_PWM_ANTENNA_RES",
355 	[MSG_SMS_CMMB_SMD_SN_REQ                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SMD_SN_REQ",
356 	[MSG_SMS_CMMB_SMD_SN_RES                     - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SMD_SN_RES",
357 	[MSG_SMS_CMMB_SET_CA_CW_REQ                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_CW_REQ",
358 	[MSG_SMS_CMMB_SET_CA_CW_RES                  - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_CW_RES",
359 	[MSG_SMS_CMMB_SET_CA_SALT_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_SALT_REQ",
360 	[MSG_SMS_CMMB_SET_CA_SALT_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_CMMB_SET_CA_SALT_RES",
361 	[MSG_SMS_NSCD_INIT_REQ                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_INIT_REQ",
362 	[MSG_SMS_NSCD_INIT_RES                       - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_INIT_RES",
363 	[MSG_SMS_NSCD_PROCESS_SECTION_REQ            - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_PROCESS_SECTION_REQ",
364 	[MSG_SMS_NSCD_PROCESS_SECTION_RES            - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_PROCESS_SECTION_RES",
365 	[MSG_SMS_DBD_CREATE_OBJECT_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CREATE_OBJECT_REQ",
366 	[MSG_SMS_DBD_CREATE_OBJECT_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CREATE_OBJECT_RES",
367 	[MSG_SMS_DBD_CONFIGURE_REQ                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CONFIGURE_REQ",
368 	[MSG_SMS_DBD_CONFIGURE_RES                   - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_CONFIGURE_RES",
369 	[MSG_SMS_DBD_SET_KEYS_REQ                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_SET_KEYS_REQ",
370 	[MSG_SMS_DBD_SET_KEYS_RES                    - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_SET_KEYS_RES",
371 	[MSG_SMS_DBD_PROCESS_HEADER_REQ              - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_HEADER_REQ",
372 	[MSG_SMS_DBD_PROCESS_HEADER_RES              - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_HEADER_RES",
373 	[MSG_SMS_DBD_PROCESS_DATA_REQ                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_DATA_REQ",
374 	[MSG_SMS_DBD_PROCESS_DATA_RES                - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_DATA_RES",
375 	[MSG_SMS_DBD_PROCESS_GET_DATA_REQ            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_GET_DATA_REQ",
376 	[MSG_SMS_DBD_PROCESS_GET_DATA_RES            - MSG_TYPE_BASE_VAL] = "MSG_SMS_DBD_PROCESS_GET_DATA_RES",
377 	[MSG_SMS_NSCD_OPEN_SESSION_REQ               - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_OPEN_SESSION_REQ",
378 	[MSG_SMS_NSCD_OPEN_SESSION_RES               - MSG_TYPE_BASE_VAL] = "MSG_SMS_NSCD_OPEN_SESSION_RES",
379 	[MSG_SMS_SEND_HOST_DATA_TO_DEMUX_REQ         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_HOST_DATA_TO_DEMUX_REQ",
380 	[MSG_SMS_SEND_HOST_DATA_TO_DEMUX_RES         - MSG_TYPE_BASE_VAL] = "MSG_SMS_SEND_HOST_DATA_TO_DEMUX_RES",
381 	[MSG_LAST_MSG_TYPE                           - MSG_TYPE_BASE_VAL] = "MSG_LAST_MSG_TYPE",
382 };
383 
384 char *smscore_translate_msg(enum msg_types msgtype)
385 {
386 	int i = msgtype - MSG_TYPE_BASE_VAL;
387 	char *msg;
388 
389 	if (i < 0 || i >= ARRAY_SIZE(siano_msgs))
390 		return "Unknown msg type";
391 
392 	msg = siano_msgs[i];
393 
394 	if (!*msg)
395 		return "Unknown msg type";
396 
397 	return msg;
398 }
399 EXPORT_SYMBOL_GPL(smscore_translate_msg);
400 
401 void smscore_set_board_id(struct smscore_device_t *core, int id)
402 {
403 	core->board_id = id;
404 }
405 
406 int smscore_led_state(struct smscore_device_t *core, int led)
407 {
408 	if (led >= 0)
409 		core->led_state = led;
410 	return core->led_state;
411 }
412 EXPORT_SYMBOL_GPL(smscore_set_board_id);
413 
414 int smscore_get_board_id(struct smscore_device_t *core)
415 {
416 	return core->board_id;
417 }
418 EXPORT_SYMBOL_GPL(smscore_get_board_id);
419 
420 struct smscore_registry_entry_t {
421 	struct list_head entry;
422 	char			devpath[32];
423 	int				mode;
424 	enum sms_device_type_st	type;
425 };
426 
427 static struct list_head g_smscore_notifyees;
428 static struct list_head g_smscore_devices;
429 static struct mutex g_smscore_deviceslock;
430 
431 static struct list_head g_smscore_registry;
432 static struct mutex g_smscore_registrylock;
433 
434 static int default_mode = DEVICE_MODE_NONE;
435 
436 module_param(default_mode, int, 0644);
437 MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
438 
439 static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
440 {
441 	struct smscore_registry_entry_t *entry;
442 	struct list_head *next;
443 
444 	kmutex_lock(&g_smscore_registrylock);
445 	for (next = g_smscore_registry.next;
446 	     next != &g_smscore_registry;
447 	     next = next->next) {
448 		entry = (struct smscore_registry_entry_t *) next;
449 		if (!strcmp(entry->devpath, devpath)) {
450 			kmutex_unlock(&g_smscore_registrylock);
451 			return entry;
452 		}
453 	}
454 	entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL);
455 	if (entry) {
456 		entry->mode = default_mode;
457 		strcpy(entry->devpath, devpath);
458 		list_add(&entry->entry, &g_smscore_registry);
459 	} else
460 		pr_err("failed to create smscore_registry.\n");
461 	kmutex_unlock(&g_smscore_registrylock);
462 	return entry;
463 }
464 
465 int smscore_registry_getmode(char *devpath)
466 {
467 	struct smscore_registry_entry_t *entry;
468 
469 	entry = smscore_find_registry(devpath);
470 	if (entry)
471 		return entry->mode;
472 	else
473 		pr_err("No registry found.\n");
474 
475 	return default_mode;
476 }
477 EXPORT_SYMBOL_GPL(smscore_registry_getmode);
478 
479 static enum sms_device_type_st smscore_registry_gettype(char *devpath)
480 {
481 	struct smscore_registry_entry_t *entry;
482 
483 	entry = smscore_find_registry(devpath);
484 	if (entry)
485 		return entry->type;
486 	else
487 		pr_err("No registry found.\n");
488 
489 	return -EINVAL;
490 }
491 
492 static void smscore_registry_setmode(char *devpath, int mode)
493 {
494 	struct smscore_registry_entry_t *entry;
495 
496 	entry = smscore_find_registry(devpath);
497 	if (entry)
498 		entry->mode = mode;
499 	else
500 		pr_err("No registry found.\n");
501 }
502 
503 static void smscore_registry_settype(char *devpath,
504 				     enum sms_device_type_st type)
505 {
506 	struct smscore_registry_entry_t *entry;
507 
508 	entry = smscore_find_registry(devpath);
509 	if (entry)
510 		entry->type = type;
511 	else
512 		pr_err("No registry found.\n");
513 }
514 
515 
516 static void list_add_locked(struct list_head *new, struct list_head *head,
517 			    spinlock_t *lock)
518 {
519 	unsigned long flags;
520 
521 	spin_lock_irqsave(lock, flags);
522 
523 	list_add(new, head);
524 
525 	spin_unlock_irqrestore(lock, flags);
526 }
527 
528 /**
529  * register a client callback that called when device plugged in/unplugged
530  * NOTE: if devices exist callback is called immediately for each device
531  *
532  * @param hotplug callback
533  *
534  * @return 0 on success, <0 on error.
535  */
536 int smscore_register_hotplug(hotplug_t hotplug)
537 {
538 	struct smscore_device_notifyee_t *notifyee;
539 	struct list_head *next, *first;
540 	int rc = 0;
541 
542 	kmutex_lock(&g_smscore_deviceslock);
543 
544 	notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
545 			   GFP_KERNEL);
546 	if (notifyee) {
547 		/* now notify callback about existing devices */
548 		first = &g_smscore_devices;
549 		for (next = first->next;
550 		     next != first && !rc;
551 		     next = next->next) {
552 			struct smscore_device_t *coredev =
553 				(struct smscore_device_t *) next;
554 			rc = hotplug(coredev, coredev->device, 1);
555 		}
556 
557 		if (rc >= 0) {
558 			notifyee->hotplug = hotplug;
559 			list_add(&notifyee->entry, &g_smscore_notifyees);
560 		} else
561 			kfree(notifyee);
562 	} else
563 		rc = -ENOMEM;
564 
565 	kmutex_unlock(&g_smscore_deviceslock);
566 
567 	return rc;
568 }
569 EXPORT_SYMBOL_GPL(smscore_register_hotplug);
570 
571 /**
572  * unregister a client callback that called when device plugged in/unplugged
573  *
574  * @param hotplug callback
575  *
576  */
577 void smscore_unregister_hotplug(hotplug_t hotplug)
578 {
579 	struct list_head *next, *first;
580 
581 	kmutex_lock(&g_smscore_deviceslock);
582 
583 	first = &g_smscore_notifyees;
584 
585 	for (next = first->next; next != first;) {
586 		struct smscore_device_notifyee_t *notifyee =
587 			(struct smscore_device_notifyee_t *) next;
588 		next = next->next;
589 
590 		if (notifyee->hotplug == hotplug) {
591 			list_del(&notifyee->entry);
592 			kfree(notifyee);
593 		}
594 	}
595 
596 	kmutex_unlock(&g_smscore_deviceslock);
597 }
598 EXPORT_SYMBOL_GPL(smscore_unregister_hotplug);
599 
600 static void smscore_notify_clients(struct smscore_device_t *coredev)
601 {
602 	struct smscore_client_t *client;
603 
604 	/* the client must call smscore_unregister_client from remove handler */
605 	while (!list_empty(&coredev->clients)) {
606 		client = (struct smscore_client_t *) coredev->clients.next;
607 		client->onremove_handler(client->context);
608 	}
609 }
610 
611 static int smscore_notify_callbacks(struct smscore_device_t *coredev,
612 				    struct device *device, int arrival)
613 {
614 	struct smscore_device_notifyee_t *elem;
615 	int rc = 0;
616 
617 	/* note: must be called under g_deviceslock */
618 
619 	list_for_each_entry(elem, &g_smscore_notifyees, entry) {
620 		rc = elem->hotplug(coredev, device, arrival);
621 		if (rc < 0)
622 			break;
623 	}
624 
625 	return rc;
626 }
627 
628 static struct
629 smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
630 				       dma_addr_t common_buffer_phys)
631 {
632 	struct smscore_buffer_t *cb;
633 
634 	cb = kzalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
635 	if (!cb)
636 		return NULL;
637 
638 	cb->p = buffer;
639 	cb->offset_in_common = buffer - (u8 *) common_buffer;
640 	cb->phys = common_buffer_phys + cb->offset_in_common;
641 
642 	return cb;
643 }
644 
645 /**
646  * creates coredev object for a device, prepares buffers,
647  * creates buffer mappings, notifies registered hotplugs about new device.
648  *
649  * @param params device pointer to struct with device specific parameters
650  *               and handlers
651  * @param coredev pointer to a value that receives created coredev object
652  *
653  * @return 0 on success, <0 on error.
654  */
655 int smscore_register_device(struct smsdevice_params_t *params,
656 			    struct smscore_device_t **coredev,
657 			    void *mdev)
658 {
659 	struct smscore_device_t *dev;
660 	u8 *buffer;
661 
662 	dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
663 	if (!dev)
664 		return -ENOMEM;
665 
666 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
667 	dev->media_dev = mdev;
668 #endif
669 
670 	/* init list entry so it could be safe in smscore_unregister_device */
671 	INIT_LIST_HEAD(&dev->entry);
672 
673 	/* init queues */
674 	INIT_LIST_HEAD(&dev->clients);
675 	INIT_LIST_HEAD(&dev->buffers);
676 
677 	/* init locks */
678 	spin_lock_init(&dev->clientslock);
679 	spin_lock_init(&dev->bufferslock);
680 
681 	/* init completion events */
682 	init_completion(&dev->version_ex_done);
683 	init_completion(&dev->data_download_done);
684 	init_completion(&dev->data_validity_done);
685 	init_completion(&dev->trigger_done);
686 	init_completion(&dev->init_device_done);
687 	init_completion(&dev->reload_start_done);
688 	init_completion(&dev->resume_done);
689 	init_completion(&dev->gpio_configuration_done);
690 	init_completion(&dev->gpio_set_level_done);
691 	init_completion(&dev->gpio_get_level_done);
692 	init_completion(&dev->ir_init_done);
693 
694 	/* Buffer management */
695 	init_waitqueue_head(&dev->buffer_mng_waitq);
696 
697 	/* alloc common buffer */
698 	dev->common_buffer_size = params->buffer_size * params->num_buffers;
699 	dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
700 						&dev->common_buffer_phys,
701 						GFP_KERNEL | GFP_DMA);
702 	if (!dev->common_buffer) {
703 		smscore_unregister_device(dev);
704 		return -ENOMEM;
705 	}
706 
707 	/* prepare dma buffers */
708 	for (buffer = dev->common_buffer;
709 	     dev->num_buffers < params->num_buffers;
710 	     dev->num_buffers++, buffer += params->buffer_size) {
711 		struct smscore_buffer_t *cb;
712 
713 		cb = smscore_createbuffer(buffer, dev->common_buffer,
714 					  dev->common_buffer_phys);
715 		if (!cb) {
716 			smscore_unregister_device(dev);
717 			return -ENOMEM;
718 		}
719 
720 		smscore_putbuffer(dev, cb);
721 	}
722 
723 	pr_debug("allocated %d buffers\n", dev->num_buffers);
724 
725 	dev->mode = DEVICE_MODE_NONE;
726 	dev->board_id = SMS_BOARD_UNKNOWN;
727 	dev->context = params->context;
728 	dev->device = params->device;
729 	dev->setmode_handler = params->setmode_handler;
730 	dev->detectmode_handler = params->detectmode_handler;
731 	dev->sendrequest_handler = params->sendrequest_handler;
732 	dev->preload_handler = params->preload_handler;
733 	dev->postload_handler = params->postload_handler;
734 
735 	dev->device_flags = params->flags;
736 	strcpy(dev->devpath, params->devpath);
737 
738 	smscore_registry_settype(dev->devpath, params->device_type);
739 
740 	/* add device to devices list */
741 	kmutex_lock(&g_smscore_deviceslock);
742 	list_add(&dev->entry, &g_smscore_devices);
743 	kmutex_unlock(&g_smscore_deviceslock);
744 
745 	*coredev = dev;
746 
747 	pr_debug("device %p created\n", dev);
748 
749 	return 0;
750 }
751 EXPORT_SYMBOL_GPL(smscore_register_device);
752 
753 
754 static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
755 		void *buffer, size_t size, struct completion *completion) {
756 	int rc;
757 
758 	if (completion == NULL)
759 		return -EINVAL;
760 	init_completion(completion);
761 
762 	rc = coredev->sendrequest_handler(coredev->context, buffer, size);
763 	if (rc < 0) {
764 		pr_info("sendrequest returned error %d\n", rc);
765 		return rc;
766 	}
767 
768 	return wait_for_completion_timeout(completion,
769 			msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ?
770 			0 : -ETIME;
771 }
772 
773 /**
774  * Starts & enables IR operations
775  *
776  * @return 0 on success, < 0 on error.
777  */
778 static int smscore_init_ir(struct smscore_device_t *coredev)
779 {
780 	int ir_io;
781 	int rc;
782 	void *buffer;
783 
784 	coredev->ir.dev = NULL;
785 	ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir;
786 	if (ir_io) {/* only if IR port exist we use IR sub-module */
787 		pr_debug("IR loading\n");
788 		rc = sms_ir_init(coredev);
789 
790 		if	(rc != 0)
791 			pr_err("Error initialization DTV IR sub-module\n");
792 		else {
793 			buffer = kmalloc(sizeof(struct sms_msg_data2) +
794 						SMS_DMA_ALIGNMENT,
795 						GFP_KERNEL | GFP_DMA);
796 			if (buffer) {
797 				struct sms_msg_data2 *msg =
798 				(struct sms_msg_data2 *)
799 				SMS_ALIGN_ADDRESS(buffer);
800 
801 				SMS_INIT_MSG(&msg->x_msg_header,
802 						MSG_SMS_START_IR_REQ,
803 						sizeof(struct sms_msg_data2));
804 				msg->msg_data[0] = coredev->ir.controller;
805 				msg->msg_data[1] = coredev->ir.timeout;
806 
807 				rc = smscore_sendrequest_and_wait(coredev, msg,
808 						msg->x_msg_header. msg_length,
809 						&coredev->ir_init_done);
810 
811 				kfree(buffer);
812 			} else
813 				pr_err("Sending IR initialization message failed\n");
814 		}
815 	} else
816 		pr_info("IR port has not been detected\n");
817 
818 	return 0;
819 }
820 
821 /**
822  * configures device features according to board configuration structure.
823  *
824  * @param coredev pointer to a coredev object returned by
825  *                smscore_register_device
826  *
827  * @return 0 on success, <0 on error.
828  */
829 static int smscore_configure_board(struct smscore_device_t *coredev)
830 {
831 	struct sms_board *board;
832 
833 	board = sms_get_board(coredev->board_id);
834 	if (!board) {
835 		pr_err("no board configuration exist.\n");
836 		return -EINVAL;
837 	}
838 
839 	if (board->mtu) {
840 		struct sms_msg_data mtu_msg;
841 		pr_debug("set max transmit unit %d\n", board->mtu);
842 
843 		mtu_msg.x_msg_header.msg_src_id = 0;
844 		mtu_msg.x_msg_header.msg_dst_id = HIF_TASK;
845 		mtu_msg.x_msg_header.msg_flags = 0;
846 		mtu_msg.x_msg_header.msg_type = MSG_SMS_SET_MAX_TX_MSG_LEN_REQ;
847 		mtu_msg.x_msg_header.msg_length = sizeof(mtu_msg);
848 		mtu_msg.msg_data[0] = board->mtu;
849 
850 		coredev->sendrequest_handler(coredev->context, &mtu_msg,
851 					     sizeof(mtu_msg));
852 	}
853 
854 	if (board->crystal) {
855 		struct sms_msg_data crys_msg;
856 		pr_debug("set crystal value %d\n", board->crystal);
857 
858 		SMS_INIT_MSG(&crys_msg.x_msg_header,
859 				MSG_SMS_NEW_CRYSTAL_REQ,
860 				sizeof(crys_msg));
861 		crys_msg.msg_data[0] = board->crystal;
862 
863 		coredev->sendrequest_handler(coredev->context, &crys_msg,
864 					     sizeof(crys_msg));
865 	}
866 
867 	return 0;
868 }
869 
870 /**
871  * sets initial device mode and notifies client hotplugs that device is ready
872  *
873  * @param coredev pointer to a coredev object returned by
874  *		  smscore_register_device
875  *
876  * @return 0 on success, <0 on error.
877  */
878 int smscore_start_device(struct smscore_device_t *coredev)
879 {
880 	int rc;
881 	int board_id = smscore_get_board_id(coredev);
882 	int mode = smscore_registry_getmode(coredev->devpath);
883 
884 	/* Device is initialized as DEVICE_MODE_NONE */
885 	if (board_id != SMS_BOARD_UNKNOWN && mode == DEVICE_MODE_NONE)
886 		mode = sms_get_board(board_id)->default_mode;
887 
888 	rc = smscore_set_device_mode(coredev, mode);
889 	if (rc < 0) {
890 		pr_info("set device mode failed , rc %d\n", rc);
891 		return rc;
892 	}
893 	rc = smscore_configure_board(coredev);
894 	if (rc < 0) {
895 		pr_info("configure board failed , rc %d\n", rc);
896 		return rc;
897 	}
898 
899 	kmutex_lock(&g_smscore_deviceslock);
900 
901 	rc = smscore_notify_callbacks(coredev, coredev->device, 1);
902 	smscore_init_ir(coredev);
903 
904 	pr_debug("device %p started, rc %d\n", coredev, rc);
905 
906 	kmutex_unlock(&g_smscore_deviceslock);
907 
908 	return rc;
909 }
910 EXPORT_SYMBOL_GPL(smscore_start_device);
911 
912 
913 static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
914 					 void *buffer, size_t size)
915 {
916 	struct sms_firmware *firmware = (struct sms_firmware *) buffer;
917 	struct sms_msg_data4 *msg;
918 	u32 mem_address,  calc_checksum = 0;
919 	u32 i, *ptr;
920 	u8 *payload = firmware->payload;
921 	int rc = 0;
922 	firmware->start_address = le32_to_cpup((__le32 *)&firmware->start_address);
923 	firmware->length = le32_to_cpup((__le32 *)&firmware->length);
924 
925 	mem_address = firmware->start_address;
926 
927 	pr_debug("loading FW to addr 0x%x size %d\n",
928 		 mem_address, firmware->length);
929 	if (coredev->preload_handler) {
930 		rc = coredev->preload_handler(coredev->context);
931 		if (rc < 0)
932 			return rc;
933 	}
934 
935 	/* PAGE_SIZE buffer shall be enough and dma aligned */
936 	msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
937 	if (!msg)
938 		return -ENOMEM;
939 
940 	if (coredev->mode != DEVICE_MODE_NONE) {
941 		pr_debug("sending reload command.\n");
942 		SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_START_REQ,
943 			     sizeof(struct sms_msg_hdr));
944 		rc = smscore_sendrequest_and_wait(coredev, msg,
945 						  msg->x_msg_header.msg_length,
946 						  &coredev->reload_start_done);
947 		if (rc < 0) {
948 			pr_err("device reload failed, rc %d\n", rc);
949 			goto exit_fw_download;
950 		}
951 		mem_address = *(u32 *) &payload[20];
952 	}
953 
954 	for (i = 0, ptr = (u32 *)firmware->payload; i < firmware->length/4 ;
955 	     i++, ptr++)
956 		calc_checksum += *ptr;
957 
958 	while (size && rc >= 0) {
959 		struct sms_data_download *data_msg =
960 			(struct sms_data_download *) msg;
961 		int payload_size = min_t(int, size, SMS_MAX_PAYLOAD_SIZE);
962 
963 		SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_DATA_DOWNLOAD_REQ,
964 			     (u16)(sizeof(struct sms_msg_hdr) +
965 				      sizeof(u32) + payload_size));
966 
967 		data_msg->mem_addr = mem_address;
968 		memcpy(data_msg->payload, payload, payload_size);
969 
970 		rc = smscore_sendrequest_and_wait(coredev, data_msg,
971 				data_msg->x_msg_header.msg_length,
972 				&coredev->data_download_done);
973 
974 		payload += payload_size;
975 		size -= payload_size;
976 		mem_address += payload_size;
977 	}
978 
979 	if (rc < 0)
980 		goto exit_fw_download;
981 
982 	pr_debug("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x\n",
983 		calc_checksum);
984 	SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_DATA_VALIDITY_REQ,
985 			sizeof(msg->x_msg_header) +
986 			sizeof(u32) * 3);
987 	msg->msg_data[0] = firmware->start_address;
988 		/* Entry point */
989 	msg->msg_data[1] = firmware->length;
990 	msg->msg_data[2] = 0; /* Regular checksum*/
991 	rc = smscore_sendrequest_and_wait(coredev, msg,
992 					  msg->x_msg_header.msg_length,
993 					  &coredev->data_validity_done);
994 	if (rc < 0)
995 		goto exit_fw_download;
996 
997 	if (coredev->mode == DEVICE_MODE_NONE) {
998 		struct sms_msg_data *trigger_msg =
999 			(struct sms_msg_data *) msg;
1000 
1001 		pr_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ\n");
1002 		SMS_INIT_MSG(&msg->x_msg_header,
1003 				MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
1004 				sizeof(struct sms_msg_hdr) +
1005 				sizeof(u32) * 5);
1006 
1007 		trigger_msg->msg_data[0] = firmware->start_address;
1008 					/* Entry point */
1009 		trigger_msg->msg_data[1] = 6; /* Priority */
1010 		trigger_msg->msg_data[2] = 0x200; /* Stack size */
1011 		trigger_msg->msg_data[3] = 0; /* Parameter */
1012 		trigger_msg->msg_data[4] = 4; /* Task ID */
1013 
1014 		rc = smscore_sendrequest_and_wait(coredev, trigger_msg,
1015 					trigger_msg->x_msg_header.msg_length,
1016 					&coredev->trigger_done);
1017 	} else {
1018 		SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_EXEC_REQ,
1019 				sizeof(struct sms_msg_hdr));
1020 		rc = coredev->sendrequest_handler(coredev->context, msg,
1021 				msg->x_msg_header.msg_length);
1022 	}
1023 
1024 	if (rc < 0)
1025 		goto exit_fw_download;
1026 
1027 	/*
1028 	 * backward compatibility - wait to device_ready_done for
1029 	 * not more than 400 ms
1030 	 */
1031 	msleep(400);
1032 
1033 exit_fw_download:
1034 	kfree(msg);
1035 
1036 	if (coredev->postload_handler) {
1037 		pr_debug("rc=%d, postload=0x%p\n",
1038 			 rc, coredev->postload_handler);
1039 		if (rc >= 0)
1040 			return coredev->postload_handler(coredev->context);
1041 	}
1042 
1043 	pr_debug("rc=%d\n", rc);
1044 	return rc;
1045 }
1046 
1047 static char *smscore_fw_lkup[][DEVICE_MODE_MAX] = {
1048 	[SMS_NOVA_A0] = {
1049 		[DEVICE_MODE_DVBT]		= SMS_FW_DVB_NOVA_12MHZ,
1050 		[DEVICE_MODE_DVBH]		= SMS_FW_DVB_NOVA_12MHZ,
1051 		[DEVICE_MODE_DAB_TDMB]		= SMS_FW_TDMB_NOVA_12MHZ,
1052 		[DEVICE_MODE_DVBT_BDA]		= SMS_FW_DVB_NOVA_12MHZ,
1053 		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_NOVA_12MHZ,
1054 		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_NOVA_12MHZ,
1055 	},
1056 	[SMS_NOVA_B0] = {
1057 		[DEVICE_MODE_DVBT]		= SMS_FW_DVB_NOVA_12MHZ_B0,
1058 		[DEVICE_MODE_DVBH]		= SMS_FW_DVB_NOVA_12MHZ_B0,
1059 		[DEVICE_MODE_DAB_TDMB]		= SMS_FW_TDMB_NOVA_12MHZ_B0,
1060 		[DEVICE_MODE_DVBT_BDA]		= SMS_FW_DVB_NOVA_12MHZ_B0,
1061 		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_NOVA_12MHZ_B0,
1062 		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_NOVA_12MHZ_B0,
1063 		[DEVICE_MODE_FM_RADIO]		= SMS_FW_FM_RADIO,
1064 		[DEVICE_MODE_FM_RADIO_BDA]	= SMS_FW_FM_RADIO,
1065 	},
1066 	[SMS_VEGA] = {
1067 		[DEVICE_MODE_CMMB]		= SMS_FW_CMMB_VEGA_12MHZ,
1068 	},
1069 	[SMS_VENICE] = {
1070 		[DEVICE_MODE_CMMB]		= SMS_FW_CMMB_VENICE_12MHZ,
1071 	},
1072 	[SMS_MING] = {
1073 		[DEVICE_MODE_CMMB]		= SMS_FW_CMMB_MING_APP,
1074 	},
1075 	[SMS_PELE] = {
1076 		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_PELE,
1077 		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_PELE,
1078 	},
1079 	[SMS_RIO] = {
1080 		[DEVICE_MODE_DVBT]		= SMS_FW_DVB_RIO,
1081 		[DEVICE_MODE_DVBH]		= SMS_FW_DVBH_RIO,
1082 		[DEVICE_MODE_DVBT_BDA]		= SMS_FW_DVB_RIO,
1083 		[DEVICE_MODE_ISDBT]		= SMS_FW_ISDBT_RIO,
1084 		[DEVICE_MODE_ISDBT_BDA]		= SMS_FW_ISDBT_RIO,
1085 		[DEVICE_MODE_FM_RADIO]		= SMS_FW_FM_RADIO_RIO,
1086 		[DEVICE_MODE_FM_RADIO_BDA]	= SMS_FW_FM_RADIO_RIO,
1087 	},
1088 	[SMS_DENVER_1530] = {
1089 		[DEVICE_MODE_ATSC]		= SMS_FW_ATSC_DENVER,
1090 	},
1091 	[SMS_DENVER_2160] = {
1092 		[DEVICE_MODE_DAB_TDMB]		= SMS_FW_TDMB_DENVER,
1093 	},
1094 };
1095 
1096 /**
1097  * get firmware file name from one of the two mechanisms : sms_boards or
1098  * smscore_fw_lkup.
1099  * @param coredev pointer to a coredev object returned by
1100  *		  smscore_register_device
1101  * @param mode requested mode of operation
1102  * @param lookup if 1, always get the fw filename from smscore_fw_lkup
1103  *	 table. if 0, try first to get from sms_boards
1104  *
1105  * @return 0 on success, <0 on error.
1106  */
1107 static char *smscore_get_fw_filename(struct smscore_device_t *coredev,
1108 			      int mode)
1109 {
1110 	char **fw;
1111 	int board_id = smscore_get_board_id(coredev);
1112 	enum sms_device_type_st type;
1113 
1114 	type = smscore_registry_gettype(coredev->devpath);
1115 
1116 	/* Prevent looking outside the smscore_fw_lkup table */
1117 	if (type <= SMS_UNKNOWN_TYPE || type >= SMS_NUM_OF_DEVICE_TYPES)
1118 		return NULL;
1119 	if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX)
1120 		return NULL;
1121 
1122 	pr_debug("trying to get fw name from sms_boards board_id %d mode %d\n",
1123 		  board_id, mode);
1124 	fw = sms_get_board(board_id)->fw;
1125 	if (!fw || !fw[mode]) {
1126 		pr_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d\n",
1127 			  mode, type);
1128 		return smscore_fw_lkup[type][mode];
1129 	}
1130 
1131 	return fw[mode];
1132 }
1133 
1134 /**
1135  * loads specified firmware into a buffer and calls device loadfirmware_handler
1136  *
1137  * @param coredev pointer to a coredev object returned by
1138  *                smscore_register_device
1139  * @param filename null-terminated string specifies firmware file name
1140  * @param loadfirmware_handler device handler that loads firmware
1141  *
1142  * @return 0 on success, <0 on error.
1143  */
1144 static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
1145 					   int mode,
1146 					   loadfirmware_t loadfirmware_handler)
1147 {
1148 	int rc = -ENOENT;
1149 	u8 *fw_buf;
1150 	u32 fw_buf_size;
1151 	const struct firmware *fw;
1152 
1153 	char *fw_filename = smscore_get_fw_filename(coredev, mode);
1154 	if (!fw_filename) {
1155 		pr_err("mode %d not supported on this device\n", mode);
1156 		return -ENOENT;
1157 	}
1158 	pr_debug("Firmware name: %s\n", fw_filename);
1159 
1160 	if (loadfirmware_handler == NULL && !(coredev->device_flags
1161 			& SMS_DEVICE_FAMILY2))
1162 		return -EINVAL;
1163 
1164 	rc = request_firmware(&fw, fw_filename, coredev->device);
1165 	if (rc < 0) {
1166 		pr_err("failed to open firmware file '%s'\n", fw_filename);
1167 		return rc;
1168 	}
1169 	pr_debug("read fw %s, buffer size=0x%zx\n", fw_filename, fw->size);
1170 	fw_buf = kmalloc(ALIGN(fw->size + sizeof(struct sms_firmware),
1171 			 SMS_ALLOC_ALIGNMENT), GFP_KERNEL | GFP_DMA);
1172 	if (!fw_buf) {
1173 		pr_err("failed to allocate firmware buffer\n");
1174 		rc = -ENOMEM;
1175 	} else {
1176 		memcpy(fw_buf, fw->data, fw->size);
1177 		fw_buf_size = fw->size;
1178 
1179 		rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
1180 			smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
1181 			: loadfirmware_handler(coredev->context, fw_buf,
1182 			fw_buf_size);
1183 	}
1184 
1185 	kfree(fw_buf);
1186 	release_firmware(fw);
1187 
1188 	return rc;
1189 }
1190 
1191 /**
1192  * notifies all clients registered with the device, notifies hotplugs,
1193  * frees all buffers and coredev object
1194  *
1195  * @param coredev pointer to a coredev object returned by
1196  *                smscore_register_device
1197  *
1198  * @return 0 on success, <0 on error.
1199  */
1200 void smscore_unregister_device(struct smscore_device_t *coredev)
1201 {
1202 	struct smscore_buffer_t *cb;
1203 	int num_buffers = 0;
1204 	int retry = 0;
1205 
1206 	kmutex_lock(&g_smscore_deviceslock);
1207 
1208 	/* Release input device (IR) resources */
1209 	sms_ir_exit(coredev);
1210 
1211 	smscore_notify_clients(coredev);
1212 	smscore_notify_callbacks(coredev, NULL, 0);
1213 
1214 	/* at this point all buffers should be back
1215 	 * onresponse must no longer be called */
1216 
1217 	while (1) {
1218 		while (!list_empty(&coredev->buffers)) {
1219 			cb = (struct smscore_buffer_t *) coredev->buffers.next;
1220 			list_del(&cb->entry);
1221 			kfree(cb);
1222 			num_buffers++;
1223 		}
1224 		if (num_buffers == coredev->num_buffers)
1225 			break;
1226 		if (++retry > 10) {
1227 			pr_info("exiting although not all buffers released.\n");
1228 			break;
1229 		}
1230 
1231 		pr_debug("waiting for %d buffer(s)\n",
1232 			 coredev->num_buffers - num_buffers);
1233 		kmutex_unlock(&g_smscore_deviceslock);
1234 		msleep(100);
1235 		kmutex_lock(&g_smscore_deviceslock);
1236 	}
1237 
1238 	pr_debug("freed %d buffers\n", num_buffers);
1239 
1240 	if (coredev->common_buffer)
1241 		dma_free_coherent(NULL, coredev->common_buffer_size,
1242 			coredev->common_buffer, coredev->common_buffer_phys);
1243 
1244 	kfree(coredev->fw_buf);
1245 
1246 	list_del(&coredev->entry);
1247 	kfree(coredev);
1248 
1249 	kmutex_unlock(&g_smscore_deviceslock);
1250 
1251 	pr_debug("device %p destroyed\n", coredev);
1252 }
1253 EXPORT_SYMBOL_GPL(smscore_unregister_device);
1254 
1255 static int smscore_detect_mode(struct smscore_device_t *coredev)
1256 {
1257 	void *buffer = kmalloc(sizeof(struct sms_msg_hdr) + SMS_DMA_ALIGNMENT,
1258 			       GFP_KERNEL | GFP_DMA);
1259 	struct sms_msg_hdr *msg =
1260 		(struct sms_msg_hdr *) SMS_ALIGN_ADDRESS(buffer);
1261 	int rc;
1262 
1263 	if (!buffer)
1264 		return -ENOMEM;
1265 
1266 	SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,
1267 		     sizeof(struct sms_msg_hdr));
1268 
1269 	rc = smscore_sendrequest_and_wait(coredev, msg, msg->msg_length,
1270 					  &coredev->version_ex_done);
1271 	if (rc == -ETIME) {
1272 		pr_err("MSG_SMS_GET_VERSION_EX_REQ failed first try\n");
1273 
1274 		if (wait_for_completion_timeout(&coredev->resume_done,
1275 						msecs_to_jiffies(5000))) {
1276 			rc = smscore_sendrequest_and_wait(
1277 				coredev, msg, msg->msg_length,
1278 				&coredev->version_ex_done);
1279 			if (rc < 0)
1280 				pr_err("MSG_SMS_GET_VERSION_EX_REQ failed second try, rc %d\n",
1281 					rc);
1282 		} else
1283 			rc = -ETIME;
1284 	}
1285 
1286 	kfree(buffer);
1287 
1288 	return rc;
1289 }
1290 
1291 /**
1292  * send init device request and wait for response
1293  *
1294  * @param coredev pointer to a coredev object returned by
1295  *                smscore_register_device
1296  * @param mode requested mode of operation
1297  *
1298  * @return 0 on success, <0 on error.
1299  */
1300 static int smscore_init_device(struct smscore_device_t *coredev, int mode)
1301 {
1302 	void *buffer;
1303 	struct sms_msg_data *msg;
1304 	int rc = 0;
1305 
1306 	buffer = kmalloc(sizeof(struct sms_msg_data) +
1307 			SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
1308 	if (!buffer) {
1309 		pr_err("Could not allocate buffer for init device message.\n");
1310 		return -ENOMEM;
1311 	}
1312 
1313 	msg = (struct sms_msg_data *)SMS_ALIGN_ADDRESS(buffer);
1314 	SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
1315 			sizeof(struct sms_msg_data));
1316 	msg->msg_data[0] = mode;
1317 
1318 	rc = smscore_sendrequest_and_wait(coredev, msg,
1319 			msg->x_msg_header. msg_length,
1320 			&coredev->init_device_done);
1321 
1322 	kfree(buffer);
1323 	return rc;
1324 }
1325 
1326 /**
1327  * calls device handler to change mode of operation
1328  * NOTE: stellar/usb may disconnect when changing mode
1329  *
1330  * @param coredev pointer to a coredev object returned by
1331  *                smscore_register_device
1332  * @param mode requested mode of operation
1333  *
1334  * @return 0 on success, <0 on error.
1335  */
1336 int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
1337 {
1338 	int rc = 0;
1339 
1340 	pr_debug("set device mode to %d\n", mode);
1341 	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
1342 		if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) {
1343 			pr_err("invalid mode specified %d\n", mode);
1344 			return -EINVAL;
1345 		}
1346 
1347 		smscore_registry_setmode(coredev->devpath, mode);
1348 
1349 		if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
1350 			rc = smscore_detect_mode(coredev);
1351 			if (rc < 0) {
1352 				pr_err("mode detect failed %d\n", rc);
1353 				return rc;
1354 			}
1355 		}
1356 
1357 		if (coredev->mode == mode) {
1358 			pr_debug("device mode %d already set\n", mode);
1359 			return 0;
1360 		}
1361 
1362 		if (!(coredev->modes_supported & (1 << mode))) {
1363 			rc = smscore_load_firmware_from_file(coredev,
1364 							     mode, NULL);
1365 			if (rc >= 0)
1366 				pr_debug("firmware download success\n");
1367 		} else {
1368 			pr_debug("mode %d is already supported by running firmware\n",
1369 				 mode);
1370 		}
1371 		if (coredev->fw_version >= 0x800) {
1372 			rc = smscore_init_device(coredev, mode);
1373 			if (rc < 0)
1374 				pr_err("device init failed, rc %d.\n", rc);
1375 		}
1376 	} else {
1377 		if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) {
1378 			pr_err("invalid mode specified %d\n", mode);
1379 			return -EINVAL;
1380 		}
1381 
1382 		smscore_registry_setmode(coredev->devpath, mode);
1383 
1384 		if (coredev->detectmode_handler)
1385 			coredev->detectmode_handler(coredev->context,
1386 						    &coredev->mode);
1387 
1388 		if (coredev->mode != mode && coredev->setmode_handler)
1389 			rc = coredev->setmode_handler(coredev->context, mode);
1390 	}
1391 
1392 	if (rc >= 0) {
1393 		char *buffer;
1394 		coredev->mode = mode;
1395 		coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
1396 
1397 		buffer = kmalloc(sizeof(struct sms_msg_data) +
1398 				 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
1399 		if (buffer) {
1400 			struct sms_msg_data *msg = (struct sms_msg_data *) SMS_ALIGN_ADDRESS(buffer);
1401 
1402 			SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
1403 				     sizeof(struct sms_msg_data));
1404 			msg->msg_data[0] = mode;
1405 
1406 			rc = smscore_sendrequest_and_wait(
1407 				coredev, msg, msg->x_msg_header.msg_length,
1408 				&coredev->init_device_done);
1409 
1410 			kfree(buffer);
1411 		}
1412 	}
1413 
1414 	if (rc < 0)
1415 		pr_err("return error code %d.\n", rc);
1416 	else
1417 		pr_debug("Success setting device mode.\n");
1418 
1419 	return rc;
1420 }
1421 
1422 /**
1423  * calls device handler to get current mode of operation
1424  *
1425  * @param coredev pointer to a coredev object returned by
1426  *                smscore_register_device
1427  *
1428  * @return current mode
1429  */
1430 int smscore_get_device_mode(struct smscore_device_t *coredev)
1431 {
1432 	return coredev->mode;
1433 }
1434 EXPORT_SYMBOL_GPL(smscore_get_device_mode);
1435 
1436 /**
1437  * find client by response id & type within the clients list.
1438  * return client handle or NULL.
1439  *
1440  * @param coredev pointer to a coredev object returned by
1441  *                smscore_register_device
1442  * @param data_type client data type (SMS_DONT_CARE for all types)
1443  * @param id client id (SMS_DONT_CARE for all id)
1444  *
1445  */
1446 static struct
1447 smscore_client_t *smscore_find_client(struct smscore_device_t *coredev,
1448 				      int data_type, int id)
1449 {
1450 	struct list_head *first;
1451 	struct smscore_client_t *client;
1452 	unsigned long flags;
1453 	struct list_head *firstid;
1454 	struct smscore_idlist_t *client_id;
1455 
1456 	spin_lock_irqsave(&coredev->clientslock, flags);
1457 	first = &coredev->clients;
1458 	list_for_each_entry(client, first, entry) {
1459 		firstid = &client->idlist;
1460 		list_for_each_entry(client_id, firstid, entry) {
1461 			if ((client_id->id == id) &&
1462 			    (client_id->data_type == data_type ||
1463 			    (client_id->data_type == 0)))
1464 				goto found;
1465 		}
1466 	}
1467 	client = NULL;
1468 found:
1469 	spin_unlock_irqrestore(&coredev->clientslock, flags);
1470 	return client;
1471 }
1472 
1473 /**
1474  * find client by response id/type, call clients onresponse handler
1475  * return buffer to pool on error
1476  *
1477  * @param coredev pointer to a coredev object returned by
1478  *                smscore_register_device
1479  * @param cb pointer to response buffer descriptor
1480  *
1481  */
1482 void smscore_onresponse(struct smscore_device_t *coredev,
1483 		struct smscore_buffer_t *cb) {
1484 	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) ((u8 *) cb->p
1485 			+ cb->offset);
1486 	struct smscore_client_t *client;
1487 	int rc = -EBUSY;
1488 	static unsigned long last_sample_time; /* = 0; */
1489 	static int data_total; /* = 0; */
1490 	unsigned long time_now = jiffies_to_msecs(jiffies);
1491 
1492 	if (!last_sample_time)
1493 		last_sample_time = time_now;
1494 
1495 	if (time_now - last_sample_time > 10000) {
1496 		pr_debug("data rate %d bytes/secs\n",
1497 			  (int)((data_total * 1000) /
1498 				(time_now - last_sample_time)));
1499 
1500 		last_sample_time = time_now;
1501 		data_total = 0;
1502 	}
1503 
1504 	data_total += cb->size;
1505 	/* Do we need to re-route? */
1506 	if ((phdr->msg_type == MSG_SMS_HO_PER_SLICES_IND) ||
1507 			(phdr->msg_type == MSG_SMS_TRANSMISSION_IND)) {
1508 		if (coredev->mode == DEVICE_MODE_DVBT_BDA)
1509 			phdr->msg_dst_id = DVBT_BDA_CONTROL_MSG_ID;
1510 	}
1511 
1512 
1513 	client = smscore_find_client(coredev, phdr->msg_type, phdr->msg_dst_id);
1514 
1515 	/* If no client registered for type & id,
1516 	 * check for control client where type is not registered */
1517 	if (client)
1518 		rc = client->onresponse_handler(client->context, cb);
1519 
1520 	if (rc < 0) {
1521 		switch (phdr->msg_type) {
1522 		case MSG_SMS_ISDBT_TUNE_RES:
1523 			break;
1524 		case MSG_SMS_RF_TUNE_RES:
1525 			break;
1526 		case MSG_SMS_SIGNAL_DETECTED_IND:
1527 			break;
1528 		case MSG_SMS_NO_SIGNAL_IND:
1529 			break;
1530 		case MSG_SMS_SPI_INT_LINE_SET_RES:
1531 			break;
1532 		case MSG_SMS_INTERFACE_LOCK_IND:
1533 			break;
1534 		case MSG_SMS_INTERFACE_UNLOCK_IND:
1535 			break;
1536 		case MSG_SMS_GET_VERSION_EX_RES:
1537 		{
1538 			struct sms_version_res *ver =
1539 				(struct sms_version_res *) phdr;
1540 			pr_debug("Firmware id %d prots 0x%x ver %d.%d\n",
1541 				  ver->firmware_id, ver->supported_protocols,
1542 				  ver->rom_ver_major, ver->rom_ver_minor);
1543 
1544 			coredev->mode = ver->firmware_id == 255 ?
1545 				DEVICE_MODE_NONE : ver->firmware_id;
1546 			coredev->modes_supported = ver->supported_protocols;
1547 			coredev->fw_version = ver->rom_ver_major << 8 |
1548 					      ver->rom_ver_minor;
1549 
1550 			complete(&coredev->version_ex_done);
1551 			break;
1552 		}
1553 		case MSG_SMS_INIT_DEVICE_RES:
1554 			complete(&coredev->init_device_done);
1555 			break;
1556 		case MSG_SW_RELOAD_START_RES:
1557 			complete(&coredev->reload_start_done);
1558 			break;
1559 		case MSG_SMS_DATA_VALIDITY_RES:
1560 		{
1561 			struct sms_msg_data *validity = (struct sms_msg_data *) phdr;
1562 
1563 			pr_debug("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x\n",
1564 				validity->msg_data[0]);
1565 			complete(&coredev->data_validity_done);
1566 			break;
1567 		}
1568 		case MSG_SMS_DATA_DOWNLOAD_RES:
1569 			complete(&coredev->data_download_done);
1570 			break;
1571 		case MSG_SW_RELOAD_EXEC_RES:
1572 			break;
1573 		case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
1574 			complete(&coredev->trigger_done);
1575 			break;
1576 		case MSG_SMS_SLEEP_RESUME_COMP_IND:
1577 			complete(&coredev->resume_done);
1578 			break;
1579 		case MSG_SMS_GPIO_CONFIG_EX_RES:
1580 			complete(&coredev->gpio_configuration_done);
1581 			break;
1582 		case MSG_SMS_GPIO_SET_LEVEL_RES:
1583 			complete(&coredev->gpio_set_level_done);
1584 			break;
1585 		case MSG_SMS_GPIO_GET_LEVEL_RES:
1586 		{
1587 			u32 *msgdata = (u32 *) phdr;
1588 			coredev->gpio_get_res = msgdata[1];
1589 			pr_debug("gpio level %d\n",
1590 					coredev->gpio_get_res);
1591 			complete(&coredev->gpio_get_level_done);
1592 			break;
1593 		}
1594 		case MSG_SMS_START_IR_RES:
1595 			complete(&coredev->ir_init_done);
1596 			break;
1597 		case MSG_SMS_IR_SAMPLES_IND:
1598 			sms_ir_event(coredev,
1599 				(const char *)
1600 				((char *)phdr
1601 				+ sizeof(struct sms_msg_hdr)),
1602 				(int)phdr->msg_length
1603 				- sizeof(struct sms_msg_hdr));
1604 			break;
1605 
1606 		case MSG_SMS_DVBT_BDA_DATA:
1607 			/*
1608 			 * It can be received here, if the frontend is
1609 			 * tuned into a valid channel and the proper firmware
1610 			 * is loaded. That happens when the module got removed
1611 			 * and re-inserted, without powering the device off
1612 			 */
1613 			break;
1614 
1615 		default:
1616 			pr_debug("message %s(%d) not handled.\n",
1617 				  smscore_translate_msg(phdr->msg_type),
1618 				  phdr->msg_type);
1619 			break;
1620 		}
1621 		smscore_putbuffer(coredev, cb);
1622 	}
1623 }
1624 EXPORT_SYMBOL_GPL(smscore_onresponse);
1625 
1626 /**
1627  * return pointer to next free buffer descriptor from core pool
1628  *
1629  * @param coredev pointer to a coredev object returned by
1630  *                smscore_register_device
1631  *
1632  * @return pointer to descriptor on success, NULL on error.
1633  */
1634 
1635 static struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev)
1636 {
1637 	struct smscore_buffer_t *cb = NULL;
1638 	unsigned long flags;
1639 
1640 	spin_lock_irqsave(&coredev->bufferslock, flags);
1641 	if (!list_empty(&coredev->buffers)) {
1642 		cb = (struct smscore_buffer_t *) coredev->buffers.next;
1643 		list_del(&cb->entry);
1644 	}
1645 	spin_unlock_irqrestore(&coredev->bufferslock, flags);
1646 	return cb;
1647 }
1648 
1649 struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
1650 {
1651 	struct smscore_buffer_t *cb = NULL;
1652 
1653 	wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev)));
1654 
1655 	return cb;
1656 }
1657 EXPORT_SYMBOL_GPL(smscore_getbuffer);
1658 
1659 /**
1660  * return buffer descriptor to a pool
1661  *
1662  * @param coredev pointer to a coredev object returned by
1663  *                smscore_register_device
1664  * @param cb pointer buffer descriptor
1665  *
1666  */
1667 void smscore_putbuffer(struct smscore_device_t *coredev,
1668 		struct smscore_buffer_t *cb) {
1669 	wake_up_interruptible(&coredev->buffer_mng_waitq);
1670 	list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
1671 }
1672 EXPORT_SYMBOL_GPL(smscore_putbuffer);
1673 
1674 static int smscore_validate_client(struct smscore_device_t *coredev,
1675 				   struct smscore_client_t *client,
1676 				   int data_type, int id)
1677 {
1678 	struct smscore_idlist_t *listentry;
1679 	struct smscore_client_t *registered_client;
1680 
1681 	if (!client) {
1682 		pr_err("bad parameter.\n");
1683 		return -EINVAL;
1684 	}
1685 	registered_client = smscore_find_client(coredev, data_type, id);
1686 	if (registered_client == client)
1687 		return 0;
1688 
1689 	if (registered_client) {
1690 		pr_err("The msg ID already registered to another client.\n");
1691 		return -EEXIST;
1692 	}
1693 	listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
1694 	if (!listentry) {
1695 		pr_err("Can't allocate memory for client id.\n");
1696 		return -ENOMEM;
1697 	}
1698 	listentry->id = id;
1699 	listentry->data_type = data_type;
1700 	list_add_locked(&listentry->entry, &client->idlist,
1701 			&coredev->clientslock);
1702 	return 0;
1703 }
1704 
1705 /**
1706  * creates smsclient object, check that id is taken by another client
1707  *
1708  * @param coredev pointer to a coredev object from clients hotplug
1709  * @param initial_id all messages with this id would be sent to this client
1710  * @param data_type all messages of this type would be sent to this client
1711  * @param onresponse_handler client handler that is called to
1712  *                           process incoming messages
1713  * @param onremove_handler client handler that is called when device is removed
1714  * @param context client-specific context
1715  * @param client pointer to a value that receives created smsclient object
1716  *
1717  * @return 0 on success, <0 on error.
1718  */
1719 int smscore_register_client(struct smscore_device_t *coredev,
1720 			    struct smsclient_params_t *params,
1721 			    struct smscore_client_t **client)
1722 {
1723 	struct smscore_client_t *newclient;
1724 	/* check that no other channel with same parameters exists */
1725 	if (smscore_find_client(coredev, params->data_type,
1726 				params->initial_id)) {
1727 		pr_err("Client already exist.\n");
1728 		return -EEXIST;
1729 	}
1730 
1731 	newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
1732 	if (!newclient) {
1733 		pr_err("Failed to allocate memory for client.\n");
1734 		return -ENOMEM;
1735 	}
1736 
1737 	INIT_LIST_HEAD(&newclient->idlist);
1738 	newclient->coredev = coredev;
1739 	newclient->onresponse_handler = params->onresponse_handler;
1740 	newclient->onremove_handler = params->onremove_handler;
1741 	newclient->context = params->context;
1742 	list_add_locked(&newclient->entry, &coredev->clients,
1743 			&coredev->clientslock);
1744 	smscore_validate_client(coredev, newclient, params->data_type,
1745 				params->initial_id);
1746 	*client = newclient;
1747 	pr_debug("%p %d %d\n", params->context, params->data_type,
1748 		  params->initial_id);
1749 
1750 	return 0;
1751 }
1752 EXPORT_SYMBOL_GPL(smscore_register_client);
1753 
1754 /**
1755  * frees smsclient object and all subclients associated with it
1756  *
1757  * @param client pointer to smsclient object returned by
1758  *               smscore_register_client
1759  *
1760  */
1761 void smscore_unregister_client(struct smscore_client_t *client)
1762 {
1763 	struct smscore_device_t *coredev = client->coredev;
1764 	unsigned long flags;
1765 
1766 	spin_lock_irqsave(&coredev->clientslock, flags);
1767 
1768 
1769 	while (!list_empty(&client->idlist)) {
1770 		struct smscore_idlist_t *identry =
1771 			(struct smscore_idlist_t *) client->idlist.next;
1772 		list_del(&identry->entry);
1773 		kfree(identry);
1774 	}
1775 
1776 	pr_debug("%p\n", client->context);
1777 
1778 	list_del(&client->entry);
1779 	kfree(client);
1780 
1781 	spin_unlock_irqrestore(&coredev->clientslock, flags);
1782 }
1783 EXPORT_SYMBOL_GPL(smscore_unregister_client);
1784 
1785 /**
1786  * verifies that source id is not taken by another client,
1787  * calls device handler to send requests to the device
1788  *
1789  * @param client pointer to smsclient object returned by
1790  *               smscore_register_client
1791  * @param buffer pointer to a request buffer
1792  * @param size size (in bytes) of request buffer
1793  *
1794  * @return 0 on success, <0 on error.
1795  */
1796 int smsclient_sendrequest(struct smscore_client_t *client,
1797 			  void *buffer, size_t size)
1798 {
1799 	struct smscore_device_t *coredev;
1800 	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer;
1801 	int rc;
1802 
1803 	if (client == NULL) {
1804 		pr_err("Got NULL client\n");
1805 		return -EINVAL;
1806 	}
1807 
1808 	coredev = client->coredev;
1809 
1810 	/* check that no other channel with same id exists */
1811 	if (coredev == NULL) {
1812 		pr_err("Got NULL coredev\n");
1813 		return -EINVAL;
1814 	}
1815 
1816 	rc = smscore_validate_client(client->coredev, client, 0,
1817 				     phdr->msg_src_id);
1818 	if (rc < 0)
1819 		return rc;
1820 
1821 	return coredev->sendrequest_handler(coredev->context, buffer, size);
1822 }
1823 EXPORT_SYMBOL_GPL(smsclient_sendrequest);
1824 
1825 
1826 /* old GPIO managements implementation */
1827 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
1828 			   struct smscore_config_gpio *pinconfig)
1829 {
1830 	struct {
1831 		struct sms_msg_hdr hdr;
1832 		u32 data[6];
1833 	} msg;
1834 
1835 	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
1836 		msg.hdr.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
1837 		msg.hdr.msg_dst_id = HIF_TASK;
1838 		msg.hdr.msg_flags = 0;
1839 		msg.hdr.msg_type  = MSG_SMS_GPIO_CONFIG_EX_REQ;
1840 		msg.hdr.msg_length = sizeof(msg);
1841 
1842 		msg.data[0] = pin;
1843 		msg.data[1] = pinconfig->pullupdown;
1844 
1845 		/* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */
1846 		msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0;
1847 
1848 		switch (pinconfig->outputdriving) {
1849 		case SMS_GPIO_OUTPUTDRIVING_S_16mA:
1850 			msg.data[3] = 7; /* Nova - 16mA */
1851 			break;
1852 		case SMS_GPIO_OUTPUTDRIVING_S_12mA:
1853 			msg.data[3] = 5; /* Nova - 11mA */
1854 			break;
1855 		case SMS_GPIO_OUTPUTDRIVING_S_8mA:
1856 			msg.data[3] = 3; /* Nova - 7mA */
1857 			break;
1858 		case SMS_GPIO_OUTPUTDRIVING_S_4mA:
1859 		default:
1860 			msg.data[3] = 2; /* Nova - 4mA */
1861 			break;
1862 		}
1863 
1864 		msg.data[4] = pinconfig->direction;
1865 		msg.data[5] = 0;
1866 	} else /* TODO: SMS_DEVICE_FAMILY1 */
1867 		return -EINVAL;
1868 
1869 	return coredev->sendrequest_handler(coredev->context,
1870 					    &msg, sizeof(msg));
1871 }
1872 
1873 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level)
1874 {
1875 	struct {
1876 		struct sms_msg_hdr hdr;
1877 		u32 data[3];
1878 	} msg;
1879 
1880 	if (pin > MAX_GPIO_PIN_NUMBER)
1881 		return -EINVAL;
1882 
1883 	msg.hdr.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
1884 	msg.hdr.msg_dst_id = HIF_TASK;
1885 	msg.hdr.msg_flags = 0;
1886 	msg.hdr.msg_type  = MSG_SMS_GPIO_SET_LEVEL_REQ;
1887 	msg.hdr.msg_length = sizeof(msg);
1888 
1889 	msg.data[0] = pin;
1890 	msg.data[1] = level ? 1 : 0;
1891 	msg.data[2] = 0;
1892 
1893 	return coredev->sendrequest_handler(coredev->context,
1894 					    &msg, sizeof(msg));
1895 }
1896 
1897 /* new GPIO management implementation */
1898 static int get_gpio_pin_params(u32 pin_num, u32 *p_translatedpin_num,
1899 		u32 *p_group_num, u32 *p_group_cfg) {
1900 
1901 	*p_group_cfg = 1;
1902 
1903 	if (pin_num <= 1)	{
1904 		*p_translatedpin_num = 0;
1905 		*p_group_num = 9;
1906 		*p_group_cfg = 2;
1907 	} else if (pin_num >= 2 && pin_num <= 6) {
1908 		*p_translatedpin_num = 2;
1909 		*p_group_num = 0;
1910 		*p_group_cfg = 2;
1911 	} else if (pin_num >= 7 && pin_num <= 11) {
1912 		*p_translatedpin_num = 7;
1913 		*p_group_num = 1;
1914 	} else if (pin_num >= 12 && pin_num <= 15) {
1915 		*p_translatedpin_num = 12;
1916 		*p_group_num = 2;
1917 		*p_group_cfg = 3;
1918 	} else if (pin_num == 16) {
1919 		*p_translatedpin_num = 16;
1920 		*p_group_num = 23;
1921 	} else if (pin_num >= 17 && pin_num <= 24) {
1922 		*p_translatedpin_num = 17;
1923 		*p_group_num = 3;
1924 	} else if (pin_num == 25) {
1925 		*p_translatedpin_num = 25;
1926 		*p_group_num = 6;
1927 	} else if (pin_num >= 26 && pin_num <= 28) {
1928 		*p_translatedpin_num = 26;
1929 		*p_group_num = 4;
1930 	} else if (pin_num == 29) {
1931 		*p_translatedpin_num = 29;
1932 		*p_group_num = 5;
1933 		*p_group_cfg = 2;
1934 	} else if (pin_num == 30) {
1935 		*p_translatedpin_num = 30;
1936 		*p_group_num = 8;
1937 	} else if (pin_num == 31) {
1938 		*p_translatedpin_num = 31;
1939 		*p_group_num = 17;
1940 	} else
1941 		return -1;
1942 
1943 	*p_group_cfg <<= 24;
1944 
1945 	return 0;
1946 }
1947 
1948 int smscore_gpio_configure(struct smscore_device_t *coredev, u8 pin_num,
1949 		struct smscore_config_gpio *p_gpio_config) {
1950 
1951 	u32 total_len;
1952 	u32 translatedpin_num = 0;
1953 	u32 group_num = 0;
1954 	u32 electric_char;
1955 	u32 group_cfg;
1956 	void *buffer;
1957 	int rc;
1958 
1959 	struct set_gpio_msg {
1960 		struct sms_msg_hdr x_msg_header;
1961 		u32 msg_data[6];
1962 	} *p_msg;
1963 
1964 
1965 	if (pin_num > MAX_GPIO_PIN_NUMBER)
1966 		return -EINVAL;
1967 
1968 	if (p_gpio_config == NULL)
1969 		return -EINVAL;
1970 
1971 	total_len = sizeof(struct sms_msg_hdr) + (sizeof(u32) * 6);
1972 
1973 	buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
1974 			GFP_KERNEL | GFP_DMA);
1975 	if (!buffer)
1976 		return -ENOMEM;
1977 
1978 	p_msg = (struct set_gpio_msg *) SMS_ALIGN_ADDRESS(buffer);
1979 
1980 	p_msg->x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
1981 	p_msg->x_msg_header.msg_dst_id = HIF_TASK;
1982 	p_msg->x_msg_header.msg_flags = 0;
1983 	p_msg->x_msg_header.msg_length = (u16) total_len;
1984 	p_msg->msg_data[0] = pin_num;
1985 
1986 	if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
1987 		p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_CONFIG_REQ;
1988 		if (get_gpio_pin_params(pin_num, &translatedpin_num, &group_num,
1989 				&group_cfg) != 0) {
1990 			rc = -EINVAL;
1991 			goto free;
1992 		}
1993 
1994 		p_msg->msg_data[1] = translatedpin_num;
1995 		p_msg->msg_data[2] = group_num;
1996 		electric_char = (p_gpio_config->pullupdown)
1997 				| (p_gpio_config->inputcharacteristics << 2)
1998 				| (p_gpio_config->outputslewrate << 3)
1999 				| (p_gpio_config->outputdriving << 4);
2000 		p_msg->msg_data[3] = electric_char;
2001 		p_msg->msg_data[4] = p_gpio_config->direction;
2002 		p_msg->msg_data[5] = group_cfg;
2003 	} else {
2004 		p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_CONFIG_EX_REQ;
2005 		p_msg->msg_data[1] = p_gpio_config->pullupdown;
2006 		p_msg->msg_data[2] = p_gpio_config->outputslewrate;
2007 		p_msg->msg_data[3] = p_gpio_config->outputdriving;
2008 		p_msg->msg_data[4] = p_gpio_config->direction;
2009 		p_msg->msg_data[5] = 0;
2010 	}
2011 
2012 	rc = smscore_sendrequest_and_wait(coredev, p_msg, total_len,
2013 			&coredev->gpio_configuration_done);
2014 
2015 	if (rc != 0) {
2016 		if (rc == -ETIME)
2017 			pr_err("smscore_gpio_configure timeout\n");
2018 		else
2019 			pr_err("smscore_gpio_configure error\n");
2020 	}
2021 free:
2022 	kfree(buffer);
2023 
2024 	return rc;
2025 }
2026 
2027 int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 pin_num,
2028 		u8 new_level) {
2029 
2030 	u32 total_len;
2031 	int rc;
2032 	void *buffer;
2033 
2034 	struct set_gpio_msg {
2035 		struct sms_msg_hdr x_msg_header;
2036 		u32 msg_data[3]; /* keep it 3 ! */
2037 	} *p_msg;
2038 
2039 	if ((new_level > 1) || (pin_num > MAX_GPIO_PIN_NUMBER))
2040 		return -EINVAL;
2041 
2042 	total_len = sizeof(struct sms_msg_hdr) +
2043 			(3 * sizeof(u32)); /* keep it 3 ! */
2044 
2045 	buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
2046 			GFP_KERNEL | GFP_DMA);
2047 	if (!buffer)
2048 		return -ENOMEM;
2049 
2050 	p_msg = (struct set_gpio_msg *) SMS_ALIGN_ADDRESS(buffer);
2051 
2052 	p_msg->x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
2053 	p_msg->x_msg_header.msg_dst_id = HIF_TASK;
2054 	p_msg->x_msg_header.msg_flags = 0;
2055 	p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_SET_LEVEL_REQ;
2056 	p_msg->x_msg_header.msg_length = (u16) total_len;
2057 	p_msg->msg_data[0] = pin_num;
2058 	p_msg->msg_data[1] = new_level;
2059 
2060 	/* Send message to SMS */
2061 	rc = smscore_sendrequest_and_wait(coredev, p_msg, total_len,
2062 			&coredev->gpio_set_level_done);
2063 
2064 	if (rc != 0) {
2065 		if (rc == -ETIME)
2066 			pr_err("smscore_gpio_set_level timeout\n");
2067 		else
2068 			pr_err("smscore_gpio_set_level error\n");
2069 	}
2070 	kfree(buffer);
2071 
2072 	return rc;
2073 }
2074 
2075 int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 pin_num,
2076 		u8 *level) {
2077 
2078 	u32 total_len;
2079 	int rc;
2080 	void *buffer;
2081 
2082 	struct set_gpio_msg {
2083 		struct sms_msg_hdr x_msg_header;
2084 		u32 msg_data[2];
2085 	} *p_msg;
2086 
2087 
2088 	if (pin_num > MAX_GPIO_PIN_NUMBER)
2089 		return -EINVAL;
2090 
2091 	total_len = sizeof(struct sms_msg_hdr) + (2 * sizeof(u32));
2092 
2093 	buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
2094 			GFP_KERNEL | GFP_DMA);
2095 	if (!buffer)
2096 		return -ENOMEM;
2097 
2098 	p_msg = (struct set_gpio_msg *) SMS_ALIGN_ADDRESS(buffer);
2099 
2100 	p_msg->x_msg_header.msg_src_id = DVBT_BDA_CONTROL_MSG_ID;
2101 	p_msg->x_msg_header.msg_dst_id = HIF_TASK;
2102 	p_msg->x_msg_header.msg_flags = 0;
2103 	p_msg->x_msg_header.msg_type = MSG_SMS_GPIO_GET_LEVEL_REQ;
2104 	p_msg->x_msg_header.msg_length = (u16) total_len;
2105 	p_msg->msg_data[0] = pin_num;
2106 	p_msg->msg_data[1] = 0;
2107 
2108 	/* Send message to SMS */
2109 	rc = smscore_sendrequest_and_wait(coredev, p_msg, total_len,
2110 			&coredev->gpio_get_level_done);
2111 
2112 	if (rc != 0) {
2113 		if (rc == -ETIME)
2114 			pr_err("smscore_gpio_get_level timeout\n");
2115 		else
2116 			pr_err("smscore_gpio_get_level error\n");
2117 	}
2118 	kfree(buffer);
2119 
2120 	/* Its a race between other gpio_get_level() and the copy of the single
2121 	 * global 'coredev->gpio_get_res' to  the function's variable 'level'
2122 	 */
2123 	*level = coredev->gpio_get_res;
2124 
2125 	return rc;
2126 }
2127 
2128 static int __init smscore_module_init(void)
2129 {
2130 	INIT_LIST_HEAD(&g_smscore_notifyees);
2131 	INIT_LIST_HEAD(&g_smscore_devices);
2132 	kmutex_init(&g_smscore_deviceslock);
2133 
2134 	INIT_LIST_HEAD(&g_smscore_registry);
2135 	kmutex_init(&g_smscore_registrylock);
2136 
2137 	return 0;
2138 }
2139 
2140 static void __exit smscore_module_exit(void)
2141 {
2142 	kmutex_lock(&g_smscore_deviceslock);
2143 	while (!list_empty(&g_smscore_notifyees)) {
2144 		struct smscore_device_notifyee_t *notifyee =
2145 			(struct smscore_device_notifyee_t *)
2146 				g_smscore_notifyees.next;
2147 
2148 		list_del(&notifyee->entry);
2149 		kfree(notifyee);
2150 	}
2151 	kmutex_unlock(&g_smscore_deviceslock);
2152 
2153 	kmutex_lock(&g_smscore_registrylock);
2154 	while (!list_empty(&g_smscore_registry)) {
2155 		struct smscore_registry_entry_t *entry =
2156 			(struct smscore_registry_entry_t *)
2157 				g_smscore_registry.next;
2158 
2159 		list_del(&entry->entry);
2160 		kfree(entry);
2161 	}
2162 	kmutex_unlock(&g_smscore_registrylock);
2163 
2164 	pr_debug("\n");
2165 }
2166 
2167 module_init(smscore_module_init);
2168 module_exit(smscore_module_exit);
2169 
2170 MODULE_DESCRIPTION("Siano MDTV Core module");
2171 MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
2172 MODULE_LICENSE("GPL");
2173 
2174 /* This should match what's defined at smscoreapi.h */
2175 MODULE_FIRMWARE(SMS_FW_ATSC_DENVER);
2176 MODULE_FIRMWARE(SMS_FW_CMMB_MING_APP);
2177 MODULE_FIRMWARE(SMS_FW_CMMB_VEGA_12MHZ);
2178 MODULE_FIRMWARE(SMS_FW_CMMB_VENICE_12MHZ);
2179 MODULE_FIRMWARE(SMS_FW_DVBH_RIO);
2180 MODULE_FIRMWARE(SMS_FW_DVB_NOVA_12MHZ_B0);
2181 MODULE_FIRMWARE(SMS_FW_DVB_NOVA_12MHZ);
2182 MODULE_FIRMWARE(SMS_FW_DVB_RIO);
2183 MODULE_FIRMWARE(SMS_FW_FM_RADIO);
2184 MODULE_FIRMWARE(SMS_FW_FM_RADIO_RIO);
2185 MODULE_FIRMWARE(SMS_FW_DVBT_HCW_55XXX);
2186 MODULE_FIRMWARE(SMS_FW_ISDBT_HCW_55XXX);
2187 MODULE_FIRMWARE(SMS_FW_ISDBT_NOVA_12MHZ_B0);
2188 MODULE_FIRMWARE(SMS_FW_ISDBT_NOVA_12MHZ);
2189 MODULE_FIRMWARE(SMS_FW_ISDBT_PELE);
2190 MODULE_FIRMWARE(SMS_FW_ISDBT_RIO);
2191 MODULE_FIRMWARE(SMS_FW_DVBT_NOVA_A);
2192 MODULE_FIRMWARE(SMS_FW_DVBT_NOVA_B);
2193 MODULE_FIRMWARE(SMS_FW_DVBT_STELLAR);
2194 MODULE_FIRMWARE(SMS_FW_TDMB_DENVER);
2195 MODULE_FIRMWARE(SMS_FW_TDMB_NOVA_12MHZ_B0);
2196 MODULE_FIRMWARE(SMS_FW_TDMB_NOVA_12MHZ);
2197