07bcc3cc3337661892472819618973cc15a3865c
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rkwifi / bcmdhd / dhd_config.c
1 \r
2 #include <typedefs.h>\r
3 #include <osl.h>\r
4 \r
5 #include <bcmutils.h>\r
6 #include <hndsoc.h>\r
7 #include <bcmsdbus.h>\r
8 #if defined(HW_OOB) || defined(FORCE_WOWLAN)
9 #include <bcmdefs.h>\r
10 #include <bcmsdh.h>\r
11 #include <sdio.h>\r
12 #include <sbchipc.h>\r
13 #endif\r
14 \r
15 #include <dhd_config.h>\r
16 #include <dhd_dbg.h>\r
17 \r
18 /* message levels */
19 #define CONFIG_ERROR_LEVEL      0x0001\r
20 #define CONFIG_TRACE_LEVEL      0x0002\r
21
22 uint config_msg_level = CONFIG_ERROR_LEVEL;\r
23
24 #define CONFIG_ERROR(x) \\r
25         do { \
26                 if (config_msg_level & CONFIG_ERROR_LEVEL) { \\r
27                         printk(KERN_ERR "CONFIG-ERROR) ");      \\r
28                         printk x; \
29                 } \
30         } while (0)
31 #define CONFIG_TRACE(x) \\r
32         do { \
33                 if (config_msg_level & CONFIG_TRACE_LEVEL) { \\r
34                         printk(KERN_ERR "CONFIG-TRACE) ");      \\r
35                         printk x; \
36                 } \
37         } while (0)\r
38 \r
39 #define MAXSZ_BUF               1000\r
40 #define MAXSZ_CONFIG    4096\r
41 \r
42 #define FW_TYPE_STA     0\r
43 #define FW_TYPE_APSTA   1\r
44 #define FW_TYPE_P2P     2\r
45 #define FW_TYPE_ES      3\r
46 #define FW_TYPE_MFG     4\r
47 #define FW_TYPE_G       0\r
48 #define FW_TYPE_AG      1\r
49 \r
50 #ifdef CONFIG_PATH_AUTO_SELECT\r
51 #define BCM4330B2_CONF_NAME "config_40183b2.txt"\r
52 #define BCM43362A0_CONF_NAME "config_40181a0.txt"\r
53 #define BCM43362A2_CONF_NAME "config_40181a2.txt"\r
54 #define BCM43438A0_CONF_NAME "config_43438a0.txt"\r
55 #define BCM43438A1_CONF_NAME "config_43438a1.txt"\r
56 #define BCM4334B1_CONF_NAME "config_4334b1.txt"\r
57 #define BCM43341B0_CONF_NAME "config_43341b0.txt"\r
58 #define BCM43241B4_CONF_NAME "config_43241b4.txt"\r
59 #define BCM4339A0_CONF_NAME "config_4339a0.txt"\r
60 #define BCM43455C0_CONF_NAME "config_43455c0.txt"\r
61 #define BCM4354A1_CONF_NAME "config_4354a1.txt"\r
62 #define BCM4356A2_CONF_NAME "config_4356a2.txt"\r
63 #define BCM4359B1_CONF_NAME "config_4359b1.txt"\r
64 #endif\r
65 \r
66 #ifdef BCMSDIO\r
67 #define SBSDIO_CIS_SIZE_LIMIT           0x200           /* maximum bytes in one CIS */\r
68 \r
69 const static char *bcm4330b2_fw_name[] = {\r
70         "fw_bcm40183b2.bin",\r
71         "fw_bcm40183b2_apsta.bin",\r
72         "fw_bcm40183b2_p2p.bin",\r
73         "fw_bcm40183b2_es.bin",\r
74         "fw_bcm40183b2_mfg.bin"\r
75 };\r
76 \r
77 const static char *bcm4330b2_ag_fw_name[] = {\r
78         "fw_bcm40183b2_ag.bin",\r
79         "fw_bcm40183b2_ag_apsta.bin",\r
80         "fw_bcm40183b2_ag_p2p.bin",\r
81         "fw_bcm40183b2_ag_es.bin",\r
82         "fw_bcm40183b2_ag_mfg.bin"\r
83 };\r
84 \r
85 const static char *bcm43362a0_fw_name[] = {\r
86         "fw_bcm40181a0.bin",\r
87         "fw_bcm40181a0_apsta.bin",\r
88         "fw_bcm40181a0_p2p.bin",\r
89         "fw_bcm40181a0_es.bin",\r
90         "fw_bcm40181a0_mfg.bin"\r
91 };\r
92 \r
93 const static char *bcm43362a2_fw_name[] = {\r
94         "fw_bcm40181a2.bin",\r
95         "fw_bcm40181a2_apsta.bin",\r
96         "fw_bcm40181a2_p2p.bin",\r
97         "fw_bcm40181a2_es.bin",\r
98         "fw_bcm40181a2_mfg.bin"\r
99 };\r
100 \r
101 const static char *bcm4334b1_ag_fw_name[] = {\r
102         "fw_bcm4334b1_ag.bin",\r
103         "fw_bcm4334b1_ag_apsta.bin",\r
104         "fw_bcm4334b1_ag_p2p.bin",\r
105         "fw_bcm4334b1_ag_es.bin",\r
106         "fw_bcm4334b1_ag_mfg.bin"\r
107 };\r
108 \r
109 const static char *bcm43438a0_fw_name[] = {\r
110         "fw_bcm43438a0.bin",\r
111         "fw_bcm43438a0_apsta.bin",\r
112         "fw_bcm43438a0_p2p.bin",\r
113         "fw_bcm43438a0_es.bin",\r
114         "fw_bcm43438a0_mfg.bin"\r
115 };\r
116 \r
117 const static char *bcm43438a1_fw_name[] = {\r
118         "fw_bcm43438a1.bin",\r
119         "fw_bcm43438a1_apsta.bin",\r
120         "fw_bcm43438a1_p2p.bin",\r
121         "fw_bcm43438a1_es.bin",\r
122         "fw_bcm43438a1_mfg.bin"\r
123 };\r
124 \r
125 const static char *bcm43341b0_ag_fw_name[] = {\r
126         "fw_bcm43341b0_ag.bin",\r
127         "fw_bcm43341b0_ag_apsta.bin",\r
128         "fw_bcm43341b0_ag_p2p.bin",\r
129         "fw_bcm43341b0_ag_es.bin",\r
130         "fw_bcm43341b0_ag_mfg.bin"\r
131 };\r
132 \r
133 const static char *bcm43241b4_ag_fw_name[] = {\r
134         "fw_bcm43241b4_ag.bin",\r
135         "fw_bcm43241b4_ag_apsta.bin",\r
136         "fw_bcm43241b4_ag_p2p.bin",\r
137         "fw_bcm43241b4_ag_es.bin",\r
138         "fw_bcm43241b4_ag_mfg.bin"\r
139 };\r
140 \r
141 const static char *bcm4339a0_ag_fw_name[] = {\r
142         "fw_bcm4339a0_ag.bin",\r
143         "fw_bcm4339a0_ag_apsta.bin",\r
144         "fw_bcm4339a0_ag_p2p.bin",\r
145         "fw_bcm4339a0_ag_es.bin",\r
146         "fw_bcm4339a0_ag_mfg.bin"\r
147 };\r
148 \r
149 const static char *bcm43455c0_ag_fw_name[] = {\r
150         "fw_bcm43455c0_ag.bin",\r
151         "fw_bcm43455c0_ag_apsta.bin",\r
152         "fw_bcm43455c0_ag_p2p.bin",\r
153         "fw_bcm43455c0_ag_es.bin",\r
154         "fw_bcm43455c0_ag_mfg.bin"\r
155 };\r
156 \r
157 const static char *bcm4354a1_ag_fw_name[] = {\r
158         "fw_bcm4354a1_ag.bin",\r
159         "fw_bcm4354a1_ag_apsta.bin",\r
160         "fw_bcm4354a1_ag_p2p.bin",\r
161         "fw_bcm4354a1_ag_es.bin",\r
162         "fw_bcm4354a1_ag_mfg.bin"\r
163 };\r
164 \r
165 const static char *bcm4356a2_ag_fw_name[] = {\r
166         "fw_bcm4356a2_ag.bin",\r
167         "fw_bcm4356a2_ag_apsta.bin",\r
168         "fw_bcm4356a2_ag_p2p.bin",\r
169         "fw_bcm4356a2_ag_es.bin",\r
170         "fw_bcm4356a2_ag_mfg.bin"\r
171 };\r
172 \r
173 const static char *bcm4359b1_ag_fw_name[] = {\r
174         "fw_bcm4359b1_ag.bin",\r
175         "fw_bcm4359b1_ag_apsta.bin",\r
176         "fw_bcm4359b1_ag_p2p.bin",\r
177         "fw_bcm4359b1_ag_es.bin",\r
178         "fw_bcm4359b1_ag_mfg.bin"\r
179 };\r
180 #endif\r
181 #ifdef BCMPCIE\r
182 const static char *bcm4356a2_pcie_ag_fw_name[] = {\r
183         "fw_bcm4356a2_pcie_ag.bin",\r
184         "fw_bcm4356a2_pcie_ag_apsta.bin",\r
185         "fw_bcm4356a2_pcie_ag_p2p.bin",\r
186         "fw_bcm4356a2_pcie_ag_es.bin",\r
187         "fw_bcm4356a2_pcie_ag_mfg.bin"\r
188 };\r
189 #endif\r
190 \r
191 #define htod32(i) i
192 #define htod16(i) i
193 #define dtoh32(i) i
194 #define dtoh16(i) i
195 #define htodchanspec(i) i
196 #define dtohchanspec(i) i\r
197 \r
198 #ifdef BCMSDIO\r
199 void\r
200 dhd_conf_free_mac_list(wl_mac_list_ctrl_t *mac_list)\r
201 {\r
202         int i;\r
203 \r
204         CONFIG_TRACE(("%s called\n", __FUNCTION__));\r
205         if (mac_list->m_mac_list_head) {\r
206                 for (i=0; i<mac_list->count; i++) {\r
207                         if (mac_list->m_mac_list_head[i].mac) {\r
208                                 CONFIG_TRACE(("%s Free mac %p\n", __FUNCTION__, mac_list->m_mac_list_head[i].mac));\r
209                                 kfree(mac_list->m_mac_list_head[i].mac);\r
210                         }\r
211                 }\r
212                 CONFIG_TRACE(("%s Free m_mac_list_head %p\n", __FUNCTION__, mac_list->m_mac_list_head));\r
213                 kfree(mac_list->m_mac_list_head);\r
214         }\r
215         mac_list->count = 0;\r
216 }\r
217 \r
218 void\r
219 dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list)\r
220 {\r
221         CONFIG_TRACE(("%s called\n", __FUNCTION__));\r
222 \r
223         if (chip_nv_list->m_chip_nv_path_head) {\r
224                 CONFIG_TRACE(("%s Free %p\n", __FUNCTION__, chip_nv_list->m_chip_nv_path_head));\r
225                 kfree(chip_nv_list->m_chip_nv_path_head);\r
226         }\r
227         chip_nv_list->count = 0;\r
228 }\r
229 \r
230 #if defined(HW_OOB) || defined(FORCE_WOWLAN)\r
231 void\r
232 dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip)\r
233 {\r
234         uint32 gpiocontrol, addr;\r
235 \r
236         if (CHIPID(chip) == BCM43362_CHIP_ID) {\r
237                 printf("%s: Enable HW OOB for 43362\n", __FUNCTION__);\r
238                 addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol);\r
239                 gpiocontrol = bcmsdh_reg_read(sdh, addr, 4);\r
240                 gpiocontrol |= 0x2;\r
241                 bcmsdh_reg_write(sdh, addr, 4, gpiocontrol);\r
242                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL);\r
243                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL);\r
244                 bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL);\r
245         }\r
246 }\r
247 #endif\r
248 \r
249 int\r
250 dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, uint8 *mac)\r
251 {\r
252         int i, err = -1;\r
253         uint8 *ptr = 0;\r
254         unsigned char tpl_code, tpl_link='\0';\r
255         uint8 header[3] = {0x80, 0x07, 0x19};\r
256         uint8 *cis;\r
257 \r
258         if (!(cis = MALLOC(dhd->osh, SBSDIO_CIS_SIZE_LIMIT))) {\r
259                 CONFIG_ERROR(("%s: cis malloc failed\n", __FUNCTION__));\r
260                 return err;\r
261         }\r
262         bzero(cis, SBSDIO_CIS_SIZE_LIMIT);\r
263 \r
264         if ((err = bcmsdh_cis_read(sdh, 0, cis, SBSDIO_CIS_SIZE_LIMIT))) {\r
265                 CONFIG_ERROR(("%s: cis read err %d\n", __FUNCTION__, err));\r
266                 MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);\r
267                 return err;\r
268         }\r
269         err = -1; // reset err;\r
270         ptr = cis;\r
271         do {\r
272                 /* 0xff means we're done */\r
273                 tpl_code = *ptr;\r
274                 ptr++;\r
275                 if (tpl_code == 0xff)\r
276                         break;\r
277 \r
278                 /* null entries have no link field or data */\r
279                 if (tpl_code == 0x00)\r
280                         continue;\r
281 \r
282                 tpl_link = *ptr;\r
283                 ptr++;\r
284                 /* a size of 0xff also means we're done */\r
285                 if (tpl_link == 0xff)\r
286                         break;\r
287                 if (config_msg_level & CONFIG_TRACE_LEVEL) {\r
288                         printf("%s: tpl_code=0x%02x, tpl_link=0x%02x, tag=0x%02x\n",\r
289                                 __FUNCTION__, tpl_code, tpl_link, *ptr);\r
290                         printk("%s: value:", __FUNCTION__);\r
291                         for (i=0; i<tpl_link-1; i++) {\r
292                                 printk("%02x ", ptr[i+1]);\r
293                                 if ((i+1) % 16 == 0)\r
294                                         printk("\n");\r
295                         }\r
296                         printk("\n");\r
297                 }\r
298 \r
299                 if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19)\r
300                         break;\r
301 \r
302                 ptr += tpl_link;\r
303         } while (1);\r
304 \r
305         if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19) {\r
306                 /* Normal OTP */\r
307                 memcpy(mac, ptr+1, 6);\r
308                 err = 0;\r
309         } else {\r
310                 ptr = cis;\r
311                 /* Special OTP */\r
312                 if (bcmsdh_reg_read(sdh, SI_ENUM_BASE, 4) == 0x16044330) {\r
313                         for (i=0; i<SBSDIO_CIS_SIZE_LIMIT; i++) {\r
314                                 if (!memcmp(header, ptr, 3)) {\r
315                                         memcpy(mac, ptr+1, 6);\r
316                                         err = 0;\r
317                                         break;\r
318                                 }\r
319                                 ptr++;\r
320                         }\r
321                 }\r
322         }\r
323 \r
324         ASSERT(cis);\r
325         MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);\r
326 \r
327         return err;\r
328 }\r
329 \r
330 void\r
331 dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *fw_path)\r
332 {\r
333         int i, j;\r
334         uint8 mac[6]={0};\r
335         int fw_num=0, mac_num=0;\r
336         uint32 oui, nic;\r
337         wl_mac_list_t *mac_list;\r
338         wl_mac_range_t *mac_range;\r
339         char *pfw_name;\r
340         int fw_type, fw_type_new;\r
341 \r
342         mac_list = dhd->conf->fw_by_mac.m_mac_list_head;\r
343         fw_num = dhd->conf->fw_by_mac.count;\r
344         if (!mac_list || !fw_num)\r
345                 return;\r
346 \r
347         if (dhd_conf_get_mac(dhd, sdh, mac)) {\r
348                 CONFIG_ERROR(("%s: Can not read MAC address\n", __FUNCTION__));\r
349                 return;\r
350         }\r
351         oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);\r
352         nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);\r
353 \r
354         /* find out the last '/' */\r
355         i = strlen(fw_path);\r
356         while (i > 0) {\r
357                 if (fw_path[i] == '/') break;\r
358                 i--;\r
359         }\r
360         pfw_name = &fw_path[i+1];\r
361         fw_type = (strstr(pfw_name, "_mfg") ?\r
362                 FW_TYPE_MFG : (strstr(pfw_name, "_apsta") ?\r
363                 FW_TYPE_APSTA : (strstr(pfw_name, "_p2p") ?\r
364                 FW_TYPE_P2P : FW_TYPE_STA)));\r
365 \r
366         for (i=0; i<fw_num; i++) {\r
367                 mac_num = mac_list[i].count;\r
368                 mac_range = mac_list[i].mac;\r
369                 fw_type_new = (strstr(mac_list[i].name, "_mfg") ?\r
370                         FW_TYPE_MFG : (strstr(mac_list[i].name, "_apsta") ?\r
371                         FW_TYPE_APSTA : (strstr(mac_list[i].name, "_p2p") ?\r
372                         FW_TYPE_P2P : FW_TYPE_STA)));\r
373                 if (fw_type != fw_type_new) {\r
374                         printf("%s: fw_typ=%d != fw_type_new=%d\n", __FUNCTION__, fw_type, fw_type_new);\r
375                         continue;\r
376                 }\r
377                 for (j=0; j<mac_num; j++) {\r
378                         if (oui == mac_range[j].oui) {\r
379                                 if (nic >= mac_range[j].nic_start && nic <= mac_range[j].nic_end) {\r
380                                         strcpy(pfw_name, mac_list[i].name);\r
381                                         printf("%s: matched oui=0x%06X, nic=0x%06X\n",\r
382                                                 __FUNCTION__, oui, nic);\r
383                                         printf("%s: fw_path=%s\n", __FUNCTION__, fw_path);\r
384                                         return;\r
385                                 }\r
386                         }\r
387                 }\r
388         }\r
389 }\r
390 \r
391 void\r
392 dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *nv_path)\r
393 {\r
394         int i, j;\r
395         uint8 mac[6]={0};\r
396         int nv_num=0, mac_num=0;\r
397         uint32 oui, nic;\r
398         wl_mac_list_t *mac_list;\r
399         wl_mac_range_t *mac_range;\r
400         char *pnv_name;\r
401 \r
402         mac_list = dhd->conf->nv_by_mac.m_mac_list_head;\r
403         nv_num = dhd->conf->nv_by_mac.count;\r
404         if (!mac_list || !nv_num)\r
405                 return;\r
406 \r
407         if (dhd_conf_get_mac(dhd, sdh, mac)) {\r
408                 CONFIG_ERROR(("%s: Can not read MAC address\n", __FUNCTION__));\r
409                 return;\r
410         }\r
411         oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);\r
412         nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);\r
413 \r
414         /* find out the last '/' */\r
415         i = strlen(nv_path);\r
416         while (i > 0) {\r
417                 if (nv_path[i] == '/') break;\r
418                 i--;\r
419         }\r
420         pnv_name = &nv_path[i+1];\r
421 \r
422         for (i=0; i<nv_num; i++) {\r
423                 mac_num = mac_list[i].count;\r
424                 mac_range = mac_list[i].mac;\r
425                 for (j=0; j<mac_num; j++) {\r
426                         if (oui == mac_range[j].oui) {\r
427                                 if (nic >= mac_range[j].nic_start && nic <= mac_range[j].nic_end) {\r
428                                         strcpy(pnv_name, mac_list[i].name);\r
429                                         printf("%s: matched oui=0x%06X, nic=0x%06X\n",\r
430                                                 __FUNCTION__, oui, nic);\r
431                                         printf("%s: nv_path=%s\n", __FUNCTION__, nv_path);\r
432                                         return;\r
433                                 }\r
434                         }\r
435                 }\r
436         }\r
437 }\r
438 #endif\r
439 \r
440 void\r
441 dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)\r
442 {\r
443         int fw_type, ag_type;\r
444         uint chip, chiprev;\r
445         int i;\r
446 \r
447         chip = dhd->conf->chip;\r
448         chiprev = dhd->conf->chiprev;\r
449 \r
450         if (fw_path[0] == '\0') {\r
451 #ifdef CONFIG_BCMDHD_FW_PATH\r
452                 bcm_strncpy_s(fw_path, MOD_PARAM_PATHLEN-1, CONFIG_BCMDHD_FW_PATH, MOD_PARAM_PATHLEN-1);\r
453                 if (fw_path[0] == '\0')\r
454 #endif\r
455                 {\r
456                         printf("firmware path is null\n");\r
457                         return;\r
458                 }\r
459         }\r
460 #ifndef FW_PATH_AUTO_SELECT\r
461         return;\r
462 #endif\r
463 \r
464         /* find out the last '/' */\r
465         i = strlen(fw_path);\r
466         while (i > 0) {\r
467                 if (fw_path[i] == '/') break;\r
468                 i--;\r
469         }\r
470 #ifdef BAND_AG\r
471         ag_type = FW_TYPE_AG;\r
472 #else\r
473         ag_type = strstr(&fw_path[i], "_ag") ? FW_TYPE_AG : FW_TYPE_G;\r
474 #endif\r
475         fw_type = (strstr(&fw_path[i], "_mfg") ? FW_TYPE_MFG :\r
476                 (strstr(&fw_path[i], "_apsta") ? FW_TYPE_APSTA :\r
477                 (strstr(&fw_path[i], "_p2p") ? FW_TYPE_P2P :\r
478                 (strstr(&fw_path[i], "_es") ? FW_TYPE_ES :\r
479                 FW_TYPE_STA))));\r
480 \r
481         switch (chip) {\r
482 #ifdef BCMSDIO\r
483                 case BCM4330_CHIP_ID:\r
484                         if (ag_type == FW_TYPE_G) {\r
485                                 if (chiprev == BCM4330B2_CHIP_REV)\r
486                                         strcpy(&fw_path[i+1], bcm4330b2_fw_name[fw_type]);\r
487                                 break;\r
488                         } else {\r
489                                 if (chiprev == BCM4330B2_CHIP_REV)\r
490                                         strcpy(&fw_path[i+1], bcm4330b2_ag_fw_name[fw_type]);\r
491                                 break;\r
492                         }\r
493                 case BCM43362_CHIP_ID:\r
494                         if (chiprev == BCM43362A0_CHIP_REV)\r
495                                 strcpy(&fw_path[i+1], bcm43362a0_fw_name[fw_type]);\r
496                         else\r
497                                 strcpy(&fw_path[i+1], bcm43362a2_fw_name[fw_type]);\r
498                         break;\r
499                 case BCM43430_CHIP_ID:\r
500                         if (chiprev == BCM43430A0_CHIP_REV)\r
501                                 strcpy(&fw_path[i+1], bcm43438a0_fw_name[fw_type]);\r
502                         else if (chiprev == BCM43430A1_CHIP_REV)\r
503                                 strcpy(&fw_path[i+1], bcm43438a1_fw_name[fw_type]);\r
504                         break;\r
505                 case BCM4334_CHIP_ID:\r
506                         if (chiprev == BCM4334B1_CHIP_REV)\r
507                                 strcpy(&fw_path[i+1], bcm4334b1_ag_fw_name[fw_type]);\r
508                         break;\r
509                 case BCM43340_CHIP_ID:\r
510                 case BCM43341_CHIP_ID:\r
511                         if (chiprev == BCM43341B0_CHIP_REV)\r
512                                 strcpy(&fw_path[i+1], bcm43341b0_ag_fw_name[fw_type]);\r
513                         break;\r
514                 case BCM4324_CHIP_ID:\r
515                         if (chiprev == BCM43241B4_CHIP_REV)\r
516                                 strcpy(&fw_path[i+1], bcm43241b4_ag_fw_name[fw_type]);\r
517                         break;\r
518                 case BCM4335_CHIP_ID:\r
519                         if (chiprev == BCM4335A0_CHIP_REV)\r
520                                 strcpy(&fw_path[i+1], bcm4339a0_ag_fw_name[fw_type]);\r
521                         break;\r
522                 case BCM4345_CHIP_ID:\r
523                 case BCM43454_CHIP_ID:\r
524                         if (chiprev == BCM43455C0_CHIP_REV)\r
525                                 strcpy(&fw_path[i+1], bcm43455c0_ag_fw_name[fw_type]);\r
526                         break;\r
527                 case BCM4339_CHIP_ID:\r
528                         if (chiprev == BCM4339A0_CHIP_REV)\r
529                                 strcpy(&fw_path[i+1], bcm4339a0_ag_fw_name[fw_type]);\r
530                         break;\r
531                 case BCM4354_CHIP_ID:\r
532                         if (chiprev == BCM4354A1_CHIP_REV)\r
533                                 strcpy(&fw_path[i+1], bcm4354a1_ag_fw_name[fw_type]);\r
534                         else if (chiprev == BCM4356A2_CHIP_REV)\r
535                                 strcpy(&fw_path[i+1], bcm4356a2_ag_fw_name[fw_type]);\r
536                         break;\r
537                 case BCM4356_CHIP_ID:\r
538                 case BCM4371_CHIP_ID:\r
539                         if (chiprev == BCM4356A2_CHIP_REV)\r
540                                 strcpy(&fw_path[i+1], bcm4356a2_ag_fw_name[fw_type]);\r
541                         break;\r
542                 case BCM4359_CHIP_ID:\r
543                         if (chiprev == BCM4359B1_CHIP_REV)\r
544                                 strcpy(&fw_path[i+1], bcm4359b1_ag_fw_name[fw_type]);\r
545                         break;\r
546 #endif\r
547 #ifdef BCMPCIE\r
548                 case BCM4354_CHIP_ID:\r
549                         if (chiprev == BCM4356A2_CHIP_REV)\r
550                                 strcpy(&fw_path[i+1], bcm4356a2_pcie_ag_fw_name[fw_type]);\r
551                         break;\r
552                 case BCM4356_CHIP_ID:\r
553                         if (chiprev == BCM4356A2_CHIP_REV)\r
554                                 strcpy(&fw_path[i+1], bcm4356a2_pcie_ag_fw_name[fw_type]);\r
555                         break;\r
556 #endif\r
557         }\r
558 \r
559         printf("%s: firmware_path=%s\n", __FUNCTION__, fw_path);\r
560 }\r
561 \r
562 void\r
563 dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path)\r
564 {\r
565         int matched=-1;\r
566         uint chip, chiprev;\r
567         int i;\r
568 \r
569         chip = dhd->conf->chip;\r
570         chiprev = dhd->conf->chiprev;\r
571 \r
572         for (i=0; i<dhd->conf->nv_by_chip.count; i++) {\r
573                 if (chip==dhd->conf->nv_by_chip.m_chip_nv_path_head[i].chip &&\r
574                                 chiprev==dhd->conf->nv_by_chip.m_chip_nv_path_head[i].chiprev) {\r
575                         matched = i;\r
576                         break;\r
577                 }\r
578         }\r
579         if (matched < 0)\r
580                 return;\r
581 \r
582         if (nv_path[0] == '\0') {\r
583 #ifdef CONFIG_BCMDHD_NVRAM_PATH\r
584                 bcm_strncpy_s(nv_path, MOD_PARAM_PATHLEN-1, CONFIG_BCMDHD_NVRAM_PATH, MOD_PARAM_PATHLEN-1);\r
585                 if (nv_path[0] == '\0')\r
586 #endif\r
587                 {\r
588                         printf("nvram path is null\n");\r
589                         return;\r
590                 }\r
591         }\r
592 \r
593         /* find out the last '/' */\r
594         i = strlen(nv_path);\r
595         while (i > 0) {
596                 if (nv_path[i] == '/') break;\r
597                 i--;\r
598         }\r
599 \r
600         strcpy(&nv_path[i+1], dhd->conf->nv_by_chip.m_chip_nv_path_head[matched].name);\r
601 \r
602         printf("%s: nvram_path=%s\n", __FUNCTION__, nv_path);\r
603 }\r
604 \r
605 void\r
606 dhd_conf_set_conf_path_by_nv_path(dhd_pub_t *dhd, char *conf_path, char *nv_path)\r
607 {\r
608         int i;\r
609 \r
610         if (nv_path[0] == '\0') {\r
611 #ifdef CONFIG_BCMDHD_NVRAM_PATH\r
612                 bcm_strncpy_s(conf_path, MOD_PARAM_PATHLEN-1, CONFIG_BCMDHD_NVRAM_PATH, MOD_PARAM_PATHLEN-1);\r
613                 if (nv_path[0] == '\0')\r
614 #endif\r
615                 {\r
616                         printf("nvram path is null\n");\r
617                         return;\r
618                 }\r
619         } else\r
620                 strcpy(conf_path, nv_path);\r
621 \r
622         /* find out the last '/' */\r
623         i = strlen(conf_path);\r
624         while (i > 0) {
625                 if (conf_path[i] == '/') break;\r
626                 i--;\r
627         }\r
628         strcpy(&conf_path[i+1], "config.txt");\r
629 \r
630         printf("%s: config_path=%s\n", __FUNCTION__, conf_path);\r
631 }\r
632 \r
633 #ifdef CONFIG_PATH_AUTO_SELECT\r
634 void\r
635 dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path)\r
636 {\r
637         uint chip, chiprev;\r
638         int i;\r
639 \r
640         chip = dhd->conf->chip;\r
641         chiprev = dhd->conf->chiprev;\r
642 \r
643         if (conf_path[0] == '\0') {\r
644                 printf("config path is null\n");\r
645                 return;\r
646         }\r
647 \r
648         /* find out the last '/' */\r
649         i = strlen(conf_path);\r
650         while (i > 0) {\r
651                 if (conf_path[i] == '/') break;\r
652                 i--;\r
653         }\r
654 \r
655         switch (chip) {\r
656 #ifdef BCMSDIO\r
657                 case BCM4330_CHIP_ID:\r
658                         if (chiprev == BCM4330B2_CHIP_REV)\r
659                                 strcpy(&conf_path[i+1], BCM4330B2_CONF_NAME);\r
660                         break;\r
661                 case BCM43362_CHIP_ID:\r
662                         if (chiprev == BCM43362A0_CHIP_REV)\r
663                                 strcpy(&conf_path[i+1], BCM43362A0_CONF_NAME);\r
664                         else\r
665                                 strcpy(&conf_path[i+1], BCM43362A2_CONF_NAME);\r
666                         break;\r
667                 case BCM43430_CHIP_ID:\r
668                         if (chiprev == BCM43430A0_CHIP_REV)\r
669                                 strcpy(&conf_path[i+1], BCM43438A0_CONF_NAME);\r
670                         else if (chiprev == BCM43430A1_CHIP_REV)\r
671                                 strcpy(&conf_path[i+1], BCM43438A1_CONF_NAME);\r
672                         break;\r
673                 case BCM4334_CHIP_ID:\r
674                         if (chiprev == BCM4334B1_CHIP_REV)\r
675                                 strcpy(&conf_path[i+1], BCM4334B1_CONF_NAME);\r
676                         break;\r
677                 case BCM43340_CHIP_ID:\r
678                 case BCM43341_CHIP_ID:\r
679                         if (chiprev == BCM43341B0_CHIP_REV)\r
680                                 strcpy(&conf_path[i+1], BCM43341B0_CONF_NAME);\r
681                         break;\r
682                 case BCM4324_CHIP_ID:\r
683                         if (chiprev == BCM43241B4_CHIP_REV)\r
684                                 strcpy(&conf_path[i+1], BCM43241B4_CONF_NAME);\r
685                         break;\r
686                 case BCM4335_CHIP_ID:\r
687                         if (chiprev == BCM4335A0_CHIP_REV)\r
688                                 strcpy(&conf_path[i+1], BCM4339A0_CONF_NAME);\r
689                         break;\r
690                 case BCM4345_CHIP_ID:\r
691                 case BCM43454_CHIP_ID:\r
692                         if (chiprev == BCM43455C0_CHIP_REV)\r
693                                 strcpy(&conf_path[i+1], BCM43455C0_CONF_NAME);\r
694                         break;\r
695                 case BCM4339_CHIP_ID:\r
696                         if (chiprev == BCM4339A0_CHIP_REV)\r
697                                 strcpy(&conf_path[i+1], BCM4339A0_CONF_NAME);\r
698                         break;\r
699                 case BCM4354_CHIP_ID:\r
700                         if (chiprev == BCM4354A1_CHIP_REV)\r
701                                 strcpy(&conf_path[i+1], BCM4354A1_CONF_NAME);\r
702                         else if (chiprev == BCM4356A2_CHIP_REV)\r
703                                 strcpy(&conf_path[i+1], BCM4356A2_CONF_NAME);\r
704                         break;\r
705                 case BCM4356_CHIP_ID:\r
706                 case BCM4371_CHIP_ID:\r
707                         if (chiprev == BCM4356A2_CHIP_REV)\r
708                                 strcpy(&conf_path[i+1], BCM4356A2_CONF_NAME);\r
709                         break;\r
710                 case BCM4359_CHIP_ID:\r
711                         if (chiprev == BCM4359B1_CHIP_REV)\r
712                                 strcpy(&conf_path[i+1], BCM4359B1_CONF_NAME);\r
713                         break;\r
714 #endif\r
715 #ifdef BCMPCIE\r
716                 case BCM4356_CHIP_ID:\r
717                         if (chiprev == BCM4356A2_CHIP_REV)\r
718                                 strcpy(&conf_path[i+1], BCM4356A2_CONF_NAME);\r
719                         break;\r
720 #endif\r
721         }\r
722 \r
723         printf("%s: config_path=%s\n", __FUNCTION__, conf_path);\r
724 }\r
725 #endif\r
726 \r
727 int\r
728 dhd_conf_set_fw_int_cmd(dhd_pub_t *dhd, char *name, uint cmd, int val,\r
729         int def, bool down)\r
730 {\r
731         int bcmerror = -1;\r
732 \r
733         if (val >= def) {\r
734                 if (down) {\r
735                         if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
736                                 CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, bcmerror));\r
737                 }\r
738                 printf("%s: set %s %d %d\n", __FUNCTION__, name, cmd, val);\r
739                 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, cmd, &val, sizeof(val), TRUE, 0)) < 0)\r
740                         CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, bcmerror));\r
741         }\r
742         return bcmerror;\r
743 }\r
744 \r
745 int\r
746 dhd_conf_set_fw_int_struct_cmd(dhd_pub_t *dhd, char *name, uint cmd,\r
747         int *val, int len, bool down)\r
748 {\r
749         int bcmerror = -1;\r
750 \r
751         if (down) {\r
752                 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
753                         CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, bcmerror));\r
754         }\r
755         if ((bcmerror = dhd_wl_ioctl_cmd(dhd, cmd, val, len, TRUE, 0)) < 0)\r
756                 CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, bcmerror));\r
757 \r
758         return bcmerror;\r
759 }\r
760 \r
761 int\r
762 dhd_conf_set_fw_string_cmd(dhd_pub_t *dhd, char *cmd, int val, int def,\r
763         bool down)\r
764 {\r
765         int bcmerror = -1;\r
766         char iovbuf[WL_EVENTING_MASK_LEN + 12]; /*  Room for "event_msgs" + '\0' + bitvec  */\r
767 \r
768         if (val >= def) {\r
769                 if (down) {\r
770                         if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
771                                 CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, bcmerror));\r
772                 }\r
773                 printf("%s: set %s %d\n", __FUNCTION__, cmd, val);\r
774                 bcm_mkiovar(cmd, (char *)&val, 4, iovbuf, sizeof(iovbuf));\r
775                 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
776                         CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, cmd, bcmerror));\r
777         }\r
778         return bcmerror;\r
779 }\r
780 \r
781 int\r
782 dhd_conf_set_fw_string_struct_cmd(dhd_pub_t *dhd, char *cmd, char *val,\r
783         int len, bool down)\r
784 {\r
785         int bcmerror = -1;\r
786         char iovbuf[WLC_IOCTL_SMLEN];\r
787         \r
788         if (down) {\r
789                 if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
790                         CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, bcmerror));\r
791         }\r
792         printf("%s: set %s\n", __FUNCTION__, cmd);\r
793         bcm_mkiovar(cmd, val, len, iovbuf, sizeof(iovbuf));\r
794         if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
795                 CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, cmd, bcmerror));\r
796 \r
797         return bcmerror;\r
798 }\r
799 \r
800 uint\r
801 dhd_conf_get_band(dhd_pub_t *dhd)\r
802 {\r
803         uint band = WLC_BAND_AUTO;\r
804 \r
805         if (dhd && dhd->conf)\r
806                 band = dhd->conf->band;\r
807         else\r
808                 CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__));\r
809 \r
810         return band;\r
811 }\r
812 \r
813 int\r
814 dhd_conf_set_country(dhd_pub_t *dhd)\r
815 {\r
816         int bcmerror = -1;\r
817 \r
818         memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t));\r
819         printf("%s: set country %s, revision %d\n", __FUNCTION__,\r
820                 dhd->conf->cspec.ccode, dhd->conf->cspec.rev);\r
821         dhd_conf_set_fw_string_struct_cmd(dhd, "country", (char *)&dhd->conf->cspec, sizeof(wl_country_t), FALSE);\r
822 \r
823         return bcmerror;\r
824 }\r
825 \r
826 int\r
827 dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec)\r
828 {\r
829         int bcmerror = -1;\r
830 \r
831         memset(cspec, 0, sizeof(wl_country_t));\r
832         bcm_mkiovar("country", NULL, 0, (char*)cspec, sizeof(wl_country_t));\r
833         if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cspec, sizeof(wl_country_t), FALSE, 0)) < 0)\r
834                 CONFIG_ERROR(("%s: country code getting failed %d\n", __FUNCTION__, bcmerror));\r
835         else\r
836                 printf("Country code: %s (%s/%d)\n", cspec->country_abbrev, cspec->ccode, cspec->rev);\r
837 \r
838         return bcmerror;\r
839 }\r
840 \r
841 int\r
842 dhd_conf_get_country_from_config(dhd_pub_t *dhd, wl_country_t *cspec)\r
843 {\r
844         int bcmerror = -1, i;\r
845         struct dhd_conf *conf = dhd->conf;\r
846 \r
847         for (i = 0; i < conf->country_list.count; i++) {\r
848                 if (strcmp(cspec->country_abbrev, conf->country_list.cspec[i].country_abbrev) == 0) {\r
849                         memcpy(cspec->ccode,\r
850                                 conf->country_list.cspec[i].ccode, WLC_CNTRY_BUF_SZ);\r
851                         cspec->rev = conf->country_list.cspec[i].rev;\r
852                         printf("%s: %s/%d\n", __FUNCTION__, cspec->ccode, cspec->rev);\r
853                         return 0;\r
854                 }\r
855         }\r
856 \r
857         return bcmerror;\r
858 }\r
859 \r
860 int\r
861 dhd_conf_fix_country(dhd_pub_t *dhd)\r
862 {\r
863         int bcmerror = -1;\r
864         uint band;\r
865         wl_uint32_list_t *list;\r
866         u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];\r
867 \r
868         if (!(dhd && dhd->conf)) {\r
869                 return bcmerror;\r
870         }\r
871
872         memset(valid_chan_list, 0, sizeof(valid_chan_list));\r
873         list = (wl_uint32_list_t *)(void *) valid_chan_list;
874         list->count = htod32(WL_NUMCHANNELS);
875         if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), FALSE, 0)) < 0) {\r
876                 CONFIG_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, bcmerror));\r
877         }\r
878 \r
879         band = dhd_conf_get_band(dhd);\r
880 \r
881         if (bcmerror || ((band==WLC_BAND_AUTO || band==WLC_BAND_2G) &&\r
882                         dtoh32(list->count)<11)) {\r
883                 CONFIG_ERROR(("%s: bcmerror=%d, # of channels %d\n",\r
884                         __FUNCTION__, bcmerror, dtoh32(list->count)));\r
885                 if ((bcmerror = dhd_conf_set_country(dhd)) < 0) {\r
886                         strcpy(dhd->conf->cspec.country_abbrev, "US");\r
887                         dhd->conf->cspec.rev = 0;\r
888                         strcpy(dhd->conf->cspec.ccode, "US");\r
889                         dhd_conf_set_country(dhd);\r
890                 }\r
891         }\r
892 \r
893         return bcmerror;\r
894 }\r
895 \r
896 bool\r
897 dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel)\r
898 {\r
899         int i;\r
900         bool match = false;\r
901 \r
902         if (dhd && dhd->conf) {\r
903                 if (dhd->conf->channels.count == 0)\r
904                         return true;\r
905                 for (i=0; i<dhd->conf->channels.count; i++) {\r
906                         if (channel == dhd->conf->channels.channel[i])\r
907                                 match = true;\r
908                 }\r
909         } else {\r
910                 match = true;\r
911                 CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__));\r
912         }\r
913 \r
914         return match;\r
915 }\r
916 \r
917 int\r
918 dhd_conf_set_roam(dhd_pub_t *dhd)\r
919 {\r
920         int bcmerror = -1;\r
921         struct dhd_conf *conf = dhd->conf;\r
922 \r
923         dhd_roam_disable = conf->roam_off;\r
924         dhd_conf_set_fw_string_cmd(dhd, "roam_off", dhd->conf->roam_off, 0, FALSE);\r
925 \r
926         if (!conf->roam_off || !conf->roam_off_suspend) {\r
927                 printf("%s: set roam_trigger %d\n", __FUNCTION__, conf->roam_trigger[0]);\r
928                 dhd_conf_set_fw_int_struct_cmd(dhd, "WLC_SET_ROAM_TRIGGER", WLC_SET_ROAM_TRIGGER,\r
929                                 conf->roam_trigger, sizeof(conf->roam_trigger), FALSE);\r
930 \r
931                 printf("%s: set roam_scan_period %d\n", __FUNCTION__, conf->roam_scan_period[0]);\r
932                 dhd_conf_set_fw_int_struct_cmd(dhd, "WLC_SET_ROAM_SCAN_PERIOD", WLC_SET_ROAM_SCAN_PERIOD,\r
933                                 conf->roam_scan_period, sizeof(conf->roam_scan_period), FALSE);\r
934 \r
935                 printf("%s: set roam_delta %d\n", __FUNCTION__, conf->roam_delta[0]);\r
936                 dhd_conf_set_fw_int_struct_cmd(dhd, "WLC_SET_ROAM_DELTA", WLC_SET_ROAM_DELTA,\r
937                                 conf->roam_delta, sizeof(conf->roam_delta), FALSE);\r
938                 \r
939                 dhd_conf_set_fw_string_cmd(dhd, "fullroamperiod", dhd->conf->fullroamperiod, 1, FALSE);\r
940         }\r
941 \r
942         return bcmerror;\r
943 }\r
944 \r
945 void\r
946 dhd_conf_get_wme(dhd_pub_t *dhd, edcf_acparam_t *acp)\r
947 {\r
948         int bcmerror = -1;\r
949         char iovbuf[WLC_IOCTL_SMLEN];\r
950         edcf_acparam_t *acparam;\r
951 \r
952         bzero(iovbuf, sizeof(iovbuf));\r
953 \r
954         /*\r
955          * Get current acparams, using buf as an input buffer.\r
956          * Return data is array of 4 ACs of wme params.\r
957          */\r
958         bcm_mkiovar("wme_ac_sta", NULL, 0, iovbuf, sizeof(iovbuf));\r
959         if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {\r
960                 CONFIG_ERROR(("%s: wme_ac_sta getting failed %d\n", __FUNCTION__, bcmerror));\r
961                 return;\r
962         }\r
963         memcpy((char*)acp, iovbuf, sizeof(edcf_acparam_t)*AC_COUNT);\r
964 \r
965         acparam = &acp[AC_BK];\r
966         CONFIG_TRACE(("%s: BK: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,\r
967                 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,\r
968                 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
969                 (int)sizeof(acp)));\r
970         acparam = &acp[AC_BE];\r
971         CONFIG_TRACE(("%s: BE: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,\r
972                 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,\r
973                 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
974                 (int)sizeof(acp)));\r
975         acparam = &acp[AC_VI];\r
976         CONFIG_TRACE(("%s: VI: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,\r
977                 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,\r
978                 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
979                 (int)sizeof(acp)));\r
980         acparam = &acp[AC_VO];\r
981         CONFIG_TRACE(("%s: VO: aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,\r
982                 acparam->ACI, acparam->ACI&EDCF_AIFSN_MASK,\r
983                 acparam->ECW&EDCF_ECWMIN_MASK, (acparam->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
984                 (int)sizeof(acp)));\r
985 \r
986         return;\r
987 }\r
988 \r
989 void\r
990 dhd_conf_update_wme(dhd_pub_t *dhd, edcf_acparam_t *acparam_cur, int aci)\r
991 {\r
992         int aifsn, ecwmin, ecwmax;\r
993         edcf_acparam_t *acp;\r
994         struct dhd_conf *conf = dhd->conf;\r
995 \r
996         /* Default value */\r
997         aifsn = acparam_cur->ACI&EDCF_AIFSN_MASK;\r
998         ecwmin = acparam_cur->ECW&EDCF_ECWMIN_MASK;\r
999         ecwmax = (acparam_cur->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT;\r
1000 \r
1001         /* Modified value */\r
1002         if (conf->wme.aifsn[aci] > 0)\r
1003                 aifsn = conf->wme.aifsn[aci];\r
1004         if (conf->wme.cwmin[aci] > 0)\r
1005                 ecwmin = conf->wme.cwmin[aci];\r
1006         if (conf->wme.cwmax[aci] > 0)\r
1007                 ecwmax = conf->wme.cwmax[aci];\r
1008 \r
1009         /* Update */\r
1010         acp = acparam_cur;\r
1011         acp->ACI = (acp->ACI & ~EDCF_AIFSN_MASK) | (aifsn & EDCF_AIFSN_MASK);\r
1012         acp->ECW = ((ecwmax << EDCF_ECWMAX_SHIFT) & EDCF_ECWMAX_MASK) | (acp->ECW & EDCF_ECWMIN_MASK);\r
1013         acp->ECW = ((acp->ECW & EDCF_ECWMAX_MASK) | (ecwmin & EDCF_ECWMIN_MASK));\r
1014 \r
1015         CONFIG_TRACE(("%s: mod aci %d aifsn %d ecwmin %d ecwmax %d size %d\n", __FUNCTION__,\r
1016                 acp->ACI, acp->ACI&EDCF_AIFSN_MASK,\r
1017                 acp->ECW&EDCF_ECWMIN_MASK, (acp->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
1018                 (int)sizeof(edcf_acparam_t)));\r
1019 \r
1020         /*\r
1021         * Now use buf as an output buffer.\r
1022         * Put WME acparams after "wme_ac\0" in buf.\r
1023         * NOTE: only one of the four ACs can be set at a time.\r
1024         */\r
1025         dhd_conf_set_fw_string_struct_cmd(dhd, "wme_ac_sta", (char *)acp, sizeof(edcf_acparam_t), FALSE);\r
1026 \r
1027 }\r
1028 \r
1029 void\r
1030 dhd_conf_set_wme(dhd_pub_t *dhd)\r
1031 {\r
1032         edcf_acparam_t acparam_cur[AC_COUNT];\r
1033 \r
1034         if (dhd && dhd->conf) {\r
1035                 if (!dhd->conf->force_wme_ac) {\r
1036                         CONFIG_TRACE(("%s: force_wme_ac is not enabled %d\n",\r
1037                                 __FUNCTION__, dhd->conf->force_wme_ac));\r
1038                         return;\r
1039                 }\r
1040 \r
1041                 CONFIG_TRACE(("%s: Before change:\n", __FUNCTION__));\r
1042                 dhd_conf_get_wme(dhd, acparam_cur);\r
1043 \r
1044                 dhd_conf_update_wme(dhd, &acparam_cur[AC_BK], AC_BK);\r
1045                 dhd_conf_update_wme(dhd, &acparam_cur[AC_BE], AC_BE);\r
1046                 dhd_conf_update_wme(dhd, &acparam_cur[AC_VI], AC_VI);\r
1047                 dhd_conf_update_wme(dhd, &acparam_cur[AC_VO], AC_VO);\r
1048 \r
1049                 CONFIG_TRACE(("%s: After change:\n", __FUNCTION__));\r
1050                 dhd_conf_get_wme(dhd, acparam_cur);\r
1051         } else {\r
1052                 CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__));\r
1053         }\r
1054 \r
1055         return;\r
1056 }\r
1057 \r
1058 #ifdef PKT_FILTER_SUPPORT\r
1059 void\r
1060 dhd_conf_add_pkt_filter(dhd_pub_t *dhd)\r
1061 {\r
1062         int i;\r
1063         char str[12];\r
1064 #define MACS "%02x%02x%02x%02x%02x%02x"\r
1065 \r
1066         /*\r
1067          * All pkt: pkt_filter_add=99 0 0 0 0x000000000000 0x000000000000\r
1068          * Netbios pkt: 120 0 0 12 0xFFFF000000000000000000FF000000000000000000000000FFFF 0x0800000000000000000000110000000000000000000000000089\r
1069          */\r
1070         for(i=0; i<dhd->conf->pkt_filter_add.count; i++) {\r
1071                 dhd->pktfilter[i+dhd->pktfilter_count] = dhd->conf->pkt_filter_add.filter[i];\r
1072                 printf("%s: %s\n", __FUNCTION__, dhd->pktfilter[i+dhd->pktfilter_count]);\r
1073         }\r
1074         dhd->pktfilter_count += i;\r
1075 \r
1076         if (dhd->conf->pkt_filter_magic) {\r
1077                 strcpy(&dhd->conf->pkt_filter_add.filter[dhd->conf->pkt_filter_add.count][0], "256 0 1 0 0x");\r
1078                 for (i=0; i<16; i++)\r
1079                         strcat(&dhd->conf->pkt_filter_add.filter[dhd->conf->pkt_filter_add.count][0], "FFFFFFFFFFFF");\r
1080                 strcat(&dhd->conf->pkt_filter_add.filter[dhd->conf->pkt_filter_add.count][0], " 0x");\r
1081                 sprintf(str, MACS, MAC2STRDBG(dhd->mac.octet));\r
1082                 for (i=0; i<16; i++)\r
1083                         strcat(&dhd->conf->pkt_filter_add.filter[dhd->conf->pkt_filter_add.count][0], str);\r
1084                 dhd->pktfilter[dhd->pktfilter_count] = dhd->conf->pkt_filter_add.filter[dhd->conf->pkt_filter_add.count];\r
1085                 dhd->pktfilter_count += 1;\r
1086         }\r
1087 }\r
1088 \r
1089 bool\r
1090 dhd_conf_del_pkt_filter(dhd_pub_t *dhd, uint32 id)\r
1091 {\r
1092         int i;\r
1093 \r
1094         if (dhd && dhd->conf) {\r
1095                 for (i=0; i<dhd->conf->pkt_filter_del.count; i++) {\r
1096                         if (id == dhd->conf->pkt_filter_del.id[i]) {\r
1097                                 printf("%s: %d\n", __FUNCTION__, dhd->conf->pkt_filter_del.id[i]);\r
1098                                 return true;\r
1099                         }\r
1100                 }\r
1101                 return false;\r
1102         }\r
1103         return false;\r
1104 }\r
1105 \r
1106 void\r
1107 dhd_conf_discard_pkt_filter(dhd_pub_t *dhd)\r
1108 {
1109         dhd->pktfilter_count = 6;\r
1110         dhd->pktfilter[DHD_UNICAST_FILTER_NUM] = NULL;\r
1111         dhd->pktfilter[DHD_BROADCAST_FILTER_NUM] = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF";\r
1112         dhd->pktfilter[DHD_MULTICAST4_FILTER_NUM] = "102 0 0 0 0xFFFFFF 0x01005E";\r
1113         dhd->pktfilter[DHD_MULTICAST6_FILTER_NUM] = "103 0 0 0 0xFFFF 0x3333";\r
1114         dhd->pktfilter[DHD_MDNS_FILTER_NUM] = NULL;\r
1115         /* Do not enable ARP to pkt filter if dhd_master_mode is false.*/\r
1116         dhd->pktfilter[DHD_ARP_FILTER_NUM] = NULL;\r
1117 \r
1118         /* IPv4 broadcast address XXX.XXX.XXX.255 */\r
1119         dhd->pktfilter[dhd->pktfilter_count] = "110 0 0 12 0xFFFF00000000000000000000000000000000000000FF 0x080000000000000000000000000000000000000000FF";\r
1120         dhd->pktfilter_count++;\r
1121         /* discard IPv4 multicast address 224.0.0.0/4 */\r
1122         dhd->pktfilter[dhd->pktfilter_count] = "111 0 0 12 0xFFFF00000000000000000000000000000000F0 0x080000000000000000000000000000000000E0";\r
1123         dhd->pktfilter_count++;\r
1124         /* discard IPv6 multicast address FF00::/8 */\r
1125         dhd->pktfilter[dhd->pktfilter_count] = "112 0 0 12 0xFFFF000000000000000000000000000000000000000000000000FF 0x86DD000000000000000000000000000000000000000000000000FF";\r
1126         dhd->pktfilter_count++;\r
1127         /* discard Netbios pkt */\r
1128         dhd->pktfilter[dhd->pktfilter_count] = "120 0 0 12 0xFFFF000000000000000000FF000000000000000000000000FFFF 0x0800000000000000000000110000000000000000000000000089";\r
1129         dhd->pktfilter_count++;\r
1130 \r
1131 }\r
1132 #endif /* PKT_FILTER_SUPPORT */\r
1133 \r
1134 void\r
1135 dhd_conf_set_disable_proptx(dhd_pub_t *dhd)\r
1136 {\r
1137         printf("%s: set disable_proptx %d\n", __FUNCTION__, dhd->conf->disable_proptx);\r
1138         disable_proptx = dhd->conf->disable_proptx;\r
1139 }\r
1140 \r
1141 int\r
1142 dhd_conf_get_pm(dhd_pub_t *dhd)\r
1143 {\r
1144         if (dhd && dhd->conf)\r
1145                 return dhd->conf->pm;\r
1146         return -1;\r
1147 }\r
1148 \r
1149 int\r
1150 dhd_conf_get_tcpack_sup_mode(dhd_pub_t *dhd)\r
1151 {\r
1152         if (dhd && dhd->conf)\r
1153                 return dhd->conf->tcpack_sup_mode;\r
1154         return -1;\r
1155 }\r
1156 \r
1157 unsigned int\r
1158 process_config_vars(char *varbuf, unsigned int len, char *pickbuf, char *param)\r
1159 {\r
1160         bool findNewline, changenewline=FALSE, pick=FALSE;\r
1161         int column;\r
1162         unsigned int n, pick_column=0;\r
1163 \r
1164         findNewline = FALSE;\r
1165         column = 0;\r
1166 \r
1167         for (n = 0; n < len; n++) {\r
1168                 if (varbuf[n] == '\r')\r
1169                         continue;\r
1170                 if ((findNewline || changenewline) && varbuf[n] != '\n')\r
1171                         continue;\r
1172                 findNewline = FALSE;\r
1173                 if (varbuf[n] == '#') {\r
1174                         findNewline = TRUE;\r
1175                         continue;\r
1176                 }\r
1177                 if (varbuf[n] == '\\') {\r
1178                         changenewline = TRUE;\r
1179                         continue;\r
1180                 }\r
1181                 if (!changenewline && varbuf[n] == '\n') {\r
1182                         if (column == 0)\r
1183                                 continue;\r
1184                         column = 0;\r
1185                         continue;\r
1186                 }\r
1187                 if (changenewline && varbuf[n] == '\n') {\r
1188                         changenewline = FALSE;\r
1189                         continue;\r
1190                 }\r
1191                 if (!memcmp(&varbuf[n], param, strlen(param)) && column==0) {\r
1192                         pick = TRUE;\r
1193                         column = strlen(param);\r
1194                         n += column;\r
1195                         pick_column = 0;\r
1196                 } else {\r
1197                         if (pick && column==0)\r
1198                                 pick = FALSE;\r
1199                         else\r
1200                                 column++;\r
1201                 }\r
1202                 if (pick) {\r
1203                         if (varbuf[n] == 0x9)\r
1204                                 continue;\r
1205                         if (pick_column>0 && pickbuf[pick_column-1]==' ' && varbuf[n]==' ')\r
1206                                 continue;\r
1207                         pickbuf[pick_column] = varbuf[n];\r
1208                         pick_column++;\r
1209                 }\r
1210         }\r
1211 \r
1212         return pick_column;\r
1213 }\r
1214 \r
1215 void\r
1216 dhd_conf_read_log_level(dhd_pub_t *dhd, char *bufp, uint len)\r
1217 {\r
1218         uint len_val;\r
1219         char *pick;\r
1220 \r
1221         pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
1222         if (!pick) {\r
1223                 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
1224                         __FUNCTION__, MAXSZ_BUF));\r
1225                 return;\r
1226         }\r
1227 \r
1228         /* Process dhd_msglevel */\r
1229         memset(pick, 0, MAXSZ_BUF);\r
1230         len_val = process_config_vars(bufp, len, pick, "msglevel=");\r
1231         if (len_val) {\r
1232                 dhd_msg_level = (int)simple_strtol(pick, NULL, 0);\r
1233                 printf("%s: dhd_msg_level = 0x%X\n", __FUNCTION__, dhd_msg_level);\r
1234         }\r
1235 #ifdef BCMSDIO\r
1236         /* Process sd_msglevel */\r
1237         memset(pick, 0, MAXSZ_BUF);\r
1238         len_val = process_config_vars(bufp, len, pick, "sd_msglevel=");\r
1239         if (len_val) {\r
1240                 sd_msglevel = (int)simple_strtol(pick, NULL, 0);\r
1241                 printf("%s: sd_msglevel = 0x%X\n", __FUNCTION__, sd_msglevel);\r
1242         }\r
1243 #endif\r
1244         /* Process android_msg_level */\r
1245         memset(pick, 0, MAXSZ_BUF);\r
1246         len_val = process_config_vars(bufp, len, pick, "android_msg_level=");\r
1247         if (len_val) {\r
1248                 android_msg_level = (int)simple_strtol(pick, NULL, 0);\r
1249                 printf("%s: android_msg_level = 0x%X\n", __FUNCTION__, android_msg_level);\r
1250         }\r
1251         /* Process config_msg_level */\r
1252         memset(pick, 0, MAXSZ_BUF);\r
1253         len_val = process_config_vars(bufp, len, pick, "config_msg_level=");\r
1254         if (len_val) {\r
1255                 config_msg_level = (int)simple_strtol(pick, NULL, 0);\r
1256                 printf("%s: config_msg_level = 0x%X\n", __FUNCTION__, config_msg_level);\r
1257         }\r
1258 #ifdef WL_CFG80211\r
1259         /* Process wl_dbg_level */\r
1260         memset(pick, 0, MAXSZ_BUF);\r
1261         len_val = process_config_vars(bufp, len, pick, "wl_dbg_level=");\r
1262         if (len_val) {\r
1263                 wl_dbg_level = (int)simple_strtol(pick, NULL, 0);\r
1264                 printf("%s: wl_dbg_level = 0x%X\n", __FUNCTION__, wl_dbg_level);\r
1265         }\r
1266 #endif\r
1267 #if defined(WL_WIRELESS_EXT)\r
1268         /* Process iw_msg_level */\r
1269         memset(pick, 0, MAXSZ_BUF);\r
1270         len_val = process_config_vars(bufp, len, pick, "iw_msg_level=");\r
1271         if (len_val) {\r
1272                 iw_msg_level = (int)simple_strtol(pick, NULL, 0);\r
1273                 printf("%s: iw_msg_level = 0x%X\n", __FUNCTION__, iw_msg_level);\r
1274         }\r
1275 #endif\r
1276 \r
1277 #if defined(DHD_DEBUG)\r
1278         /* Process dhd_console_ms */\r
1279         memset(pick, 0, MAXSZ_BUF);\r
1280         len_val = process_config_vars(bufp, len, pick, "dhd_console_ms=");\r
1281         if (len_val) {\r
1282                 dhd_console_ms = (int)simple_strtol(pick, NULL, 0);\r
1283                 printf("%s: dhd_console_ms = 0x%X\n", __FUNCTION__, dhd_console_ms);\r
1284         }\r
1285 #endif\r
1286 \r
1287         if (pick)\r
1288                 MFREE(dhd->osh, pick, MAXSZ_BUF);\r
1289 }
1290
1291 void\r
1292 dhd_conf_read_wme_ac_params(dhd_pub_t *dhd, char *bufp, uint len)\r
1293 {\r
1294         uint len_val;\r
1295         char *pick;\r
1296         struct dhd_conf *conf = dhd->conf;\r
1297 \r
1298         pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
1299         if (!pick) {\r
1300                 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
1301                         __FUNCTION__, MAXSZ_BUF));\r
1302                 return;\r
1303         }\r
1304 \r
1305         /* Process WMM parameters */\r
1306         memset(pick, 0, MAXSZ_BUF);\r
1307         len_val = process_config_vars(bufp, len, pick, "force_wme_ac=");\r
1308         if (len_val) {\r
1309                 conf->force_wme_ac = (int)simple_strtol(pick, NULL, 10);\r
1310                 printf("%s: force_wme_ac = %d\n", __FUNCTION__, conf->force_wme_ac);\r
1311         }\r
1312 \r
1313         if (conf->force_wme_ac) {\r
1314                 memset(pick, 0, MAXSZ_BUF);\r
1315                 len_val = process_config_vars(bufp, len, pick, "bk_aifsn=");\r
1316                 if (len_val) {\r
1317                         conf->wme.aifsn[AC_BK] = (int)simple_strtol(pick, NULL, 10);\r
1318                         printf("%s: AC_BK aifsn = %d\n", __FUNCTION__, conf->wme.aifsn[AC_BK]);\r
1319                 }\r
1320 \r
1321                 memset(pick, 0, MAXSZ_BUF);\r
1322                 len_val = process_config_vars(bufp, len, pick, "bk_cwmin=");\r
1323                 if (len_val) {\r
1324                         conf->wme.cwmin[AC_BK] = (int)simple_strtol(pick, NULL, 10);\r
1325                         printf("%s: AC_BK cwmin = %d\n", __FUNCTION__, conf->wme.cwmin[AC_BK]);\r
1326                 }\r
1327 \r
1328                 memset(pick, 0, MAXSZ_BUF);\r
1329                 len_val = process_config_vars(bufp, len, pick, "bk_cwmax=");\r
1330                 if (len_val) {\r
1331                         conf->wme.cwmax[AC_BK] = (int)simple_strtol(pick, NULL, 10);\r
1332                         printf("%s: AC_BK cwmax = %d\n", __FUNCTION__, conf->wme.cwmax[AC_BK]);\r
1333                 }\r
1334 \r
1335                 memset(pick, 0, MAXSZ_BUF);\r
1336                 len_val = process_config_vars(bufp, len, pick, "be_aifsn=");\r
1337                 if (len_val) {\r
1338                         conf->wme.aifsn[AC_BE] = (int)simple_strtol(pick, NULL, 10);\r
1339                         printf("%s: AC_BE aifsn = %d\n", __FUNCTION__, conf->wme.aifsn[AC_BE]);\r
1340                 }\r
1341 \r
1342                 memset(pick, 0, MAXSZ_BUF);\r
1343                 len_val = process_config_vars(bufp, len, pick, "be_cwmin=");\r
1344                 if (len_val) {\r
1345                         conf->wme.cwmin[AC_BE] = (int)simple_strtol(pick, NULL, 10);\r
1346                         printf("%s: AC_BE cwmin = %d\n", __FUNCTION__, conf->wme.cwmin[AC_BE]);\r
1347                 }\r
1348 \r
1349                 memset(pick, 0, MAXSZ_BUF);\r
1350                 len_val = process_config_vars(bufp, len, pick, "be_cwmax=");\r
1351                 if (len_val) {\r
1352                         conf->wme.cwmax[AC_BE] = (int)simple_strtol(pick, NULL, 10);\r
1353                         printf("%s: AC_BE cwmax = %d\n", __FUNCTION__, conf->wme.cwmax[AC_BE]);\r
1354                 }\r
1355 \r
1356                 memset(pick, 0, MAXSZ_BUF);\r
1357                 len_val = process_config_vars(bufp, len, pick, "vi_aifsn=");\r
1358                 if (len_val) {\r
1359                         conf->wme.aifsn[AC_VI] = (int)simple_strtol(pick, NULL, 10);\r
1360                         printf("%s: AC_VI aifsn = %d\n", __FUNCTION__, conf->wme.aifsn[AC_VI]);\r
1361                 }\r
1362 \r
1363                 memset(pick, 0, MAXSZ_BUF);\r
1364                 len_val = process_config_vars(bufp, len, pick, "vi_cwmin=");\r
1365                 if (len_val) {\r
1366                         conf->wme.cwmin[AC_VI] = (int)simple_strtol(pick, NULL, 10);\r
1367                         printf("%s: AC_VI cwmin = %d\n", __FUNCTION__, conf->wme.cwmin[AC_VI]);\r
1368                 }\r
1369 \r
1370                 memset(pick, 0, MAXSZ_BUF);\r
1371                 len_val = process_config_vars(bufp, len, pick, "vi_cwmax=");\r
1372                 if (len_val) {\r
1373                         conf->wme.cwmax[AC_VI] = (int)simple_strtol(pick, NULL, 10);\r
1374                         printf("%s: AC_VI cwmax = %d\n", __FUNCTION__, conf->wme.cwmax[AC_VI]);\r
1375                 }\r
1376 \r
1377                 memset(pick, 0, MAXSZ_BUF);\r
1378                 len_val = process_config_vars(bufp, len, pick, "vo_aifsn=");\r
1379                 if (len_val) {\r
1380                         conf->wme.aifsn[AC_VO] = (int)simple_strtol(pick, NULL, 10);\r
1381                         printf("%s: AC_VO aifsn = %d\n", __FUNCTION__, conf->wme.aifsn[AC_VO]);\r
1382                 }\r
1383 \r
1384                 memset(pick, 0, MAXSZ_BUF);\r
1385                 len_val = process_config_vars(bufp, len, pick, "vo_cwmin=");\r
1386                 if (len_val) {\r
1387                         conf->wme.cwmin[AC_VO] = (int)simple_strtol(pick, NULL, 10);\r
1388                         printf("%s: AC_VO cwmin = %d\n", __FUNCTION__, conf->wme.cwmin[AC_VO]);\r
1389                 }\r
1390 \r
1391                 memset(pick, 0, MAXSZ_BUF);\r
1392                 len_val = process_config_vars(bufp, len, pick, "vo_cwmax=");\r
1393                 if (len_val) {\r
1394                         conf->wme.cwmax[AC_VO] = (int)simple_strtol(pick, NULL, 10);\r
1395                         printf("%s: AC_VO cwmax = %d\n", __FUNCTION__, conf->wme.cwmax[AC_VO]);\r
1396                 }\r
1397         }\r
1398 \r
1399         if (pick)\r
1400                 MFREE(dhd->osh, pick, MAXSZ_BUF);\r
1401 \r
1402 }\r
1403 \r
1404 void\r
1405 dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *bufp, uint len)\r
1406 {\r
1407         uint len_val;\r
1408         int i, j;\r
1409         char *pick;\r
1410         char *pch, *pick_tmp;\r
1411         wl_mac_list_t *mac_list;\r
1412         wl_mac_range_t *mac_range;\r
1413         struct dhd_conf *conf = dhd->conf;\r
1414 \r
1415         pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
1416         if (!pick) {\r
1417                 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
1418                         __FUNCTION__, MAXSZ_BUF));\r
1419                 return;\r
1420         }\r
1421 \r
1422         /* Process fw_by_mac:\r
1423          * fw_by_mac=[fw_mac_num] \\r
1424          *  [fw_name1] [mac_num1] [oui1-1] [nic_start1-1] [nic_end1-1] \\r
1425          *                                    [oui1-1] [nic_start1-1] [nic_end1-1]... \\r
1426          *                                    [oui1-n] [nic_start1-n] [nic_end1-n] \\r
1427          *  [fw_name2] [mac_num2] [oui2-1] [nic_start2-1] [nic_end2-1] \\r
1428          *                                    [oui2-1] [nic_start2-1] [nic_end2-1]... \\r
1429          *                                    [oui2-n] [nic_start2-n] [nic_end2-n] \\r
1430          * Ex: fw_by_mac=2 \\r
1431          *  fw_bcmdhd1.bin 2 0x0022F4 0xE85408 0xE8549D 0x983B16 0x3557A9 0x35582A \\r
1432          *  fw_bcmdhd2.bin 3 0x0022F4 0xE85408 0xE8549D 0x983B16 0x3557A9 0x35582A \\r
1433          *                           0x983B16 0x916157 0x916487\r
1434          */\r
1435         memset(pick, 0, MAXSZ_BUF);\r
1436         len_val = process_config_vars(bufp, len, pick, "fw_by_mac=");\r
1437         if (len_val) {\r
1438                 pick_tmp = pick;\r
1439                 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1440                 conf->fw_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);\r
1441                 if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->fw_by_mac.count, GFP_KERNEL))) {\r
1442                         conf->fw_by_mac.count = 0;\r
1443                         CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
1444                 }\r
1445                 printf("%s: fw_count=%d\n", __FUNCTION__, conf->fw_by_mac.count);\r
1446                 conf->fw_by_mac.m_mac_list_head = mac_list;\r
1447                 for (i=0; i<conf->fw_by_mac.count; i++) {\r
1448                         pch = bcmstrtok(&pick_tmp, " ", 0);\r
1449                         strcpy(mac_list[i].name, pch);\r
1450                         pch = bcmstrtok(&pick_tmp, " ", 0);\r
1451                         mac_list[i].count = (uint32)simple_strtol(pch, NULL, 0);\r
1452                         printf("%s: name=%s, mac_count=%d\n", __FUNCTION__,\r
1453                                 mac_list[i].name, mac_list[i].count);\r
1454                         if (!(mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count, GFP_KERNEL))) {\r
1455                                 mac_list[i].count = 0;\r
1456                                 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
1457                                 break;\r
1458                         }\r
1459                         mac_list[i].mac = mac_range;\r
1460                         for (j=0; j<mac_list[i].count; j++) {\r
1461                                 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1462                                 mac_range[j].oui = (uint32)simple_strtol(pch, NULL, 0);\r
1463                                 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1464                                 mac_range[j].nic_start = (uint32)simple_strtol(pch, NULL, 0);\r
1465                                 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1466                                 mac_range[j].nic_end = (uint32)simple_strtol(pch, NULL, 0);\r
1467                                 printf("%s: oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n",\r
1468                                         __FUNCTION__, mac_range[j].oui,\r
1469                                         mac_range[j].nic_start, mac_range[j].nic_end);\r
1470                         }\r
1471                 }\r
1472         }\r
1473 \r
1474         if (pick)\r
1475                 MFREE(dhd->osh, pick, MAXSZ_BUF);\r
1476 }\r
1477 \r
1478 void\r
1479 dhd_conf_read_nv_by_mac(dhd_pub_t *dhd, char *bufp, uint len)\r
1480 {\r
1481         uint len_val;\r
1482         int i, j;\r
1483         char *pick;\r
1484         char *pch, *pick_tmp;\r
1485         wl_mac_list_t *mac_list;\r
1486         wl_mac_range_t *mac_range;\r
1487         struct dhd_conf *conf = dhd->conf;\r
1488 \r
1489         pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
1490         if (!pick) {\r
1491                 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
1492                         __FUNCTION__, MAXSZ_BUF));\r
1493                 return;\r
1494         }\r
1495 \r
1496         /* Process nv_by_mac:\r
1497          * [nv_by_mac]: The same format as fw_by_mac\r
1498          */\r
1499         memset(pick, 0, MAXSZ_BUF);\r
1500         len_val = process_config_vars(bufp, len, pick, "nv_by_mac=");\r
1501         if (len_val) {\r
1502                 pick_tmp = pick;\r
1503                 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1504                 conf->nv_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);\r
1505                 if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_mac.count, GFP_KERNEL))) {\r
1506                         conf->nv_by_mac.count = 0;\r
1507                         CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
1508                 }\r
1509                 printf("%s: nv_count=%d\n", __FUNCTION__, conf->nv_by_mac.count);\r
1510                 conf->nv_by_mac.m_mac_list_head = mac_list;\r
1511                 for (i=0; i<conf->nv_by_mac.count; i++) {\r
1512                         pch = bcmstrtok(&pick_tmp, " ", 0);\r
1513                         strcpy(mac_list[i].name, pch);\r
1514                         pch = bcmstrtok(&pick_tmp, " ", 0);\r
1515                         mac_list[i].count = (uint32)simple_strtol(pch, NULL, 0);\r
1516                         printf("%s: name=%s, mac_count=%d\n", __FUNCTION__,\r
1517                                 mac_list[i].name, mac_list[i].count);\r
1518                         if (!(mac_range = kmalloc(sizeof(wl_mac_range_t)*mac_list[i].count, GFP_KERNEL))) {\r
1519                                 mac_list[i].count = 0;\r
1520                                 CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
1521                                 break;\r
1522                         }\r
1523                         mac_list[i].mac = mac_range;\r
1524                         for (j=0; j<mac_list[i].count; j++) {\r
1525                                 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1526                                 mac_range[j].oui = (uint32)simple_strtol(pch, NULL, 0);\r
1527                                 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1528                                 mac_range[j].nic_start = (uint32)simple_strtol(pch, NULL, 0);\r
1529                                 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1530                                 mac_range[j].nic_end = (uint32)simple_strtol(pch, NULL, 0);\r
1531                                 printf("%s: oui=0x%06X, nic_start=0x%06X, nic_end=0x%06X\n",\r
1532                                         __FUNCTION__, mac_range[j].oui,\r
1533                                         mac_range[j].nic_start, mac_range[j].nic_end);\r
1534                         }\r
1535                 }\r
1536         }\r
1537 \r
1538         if (pick)\r
1539                 MFREE(dhd->osh, pick, MAXSZ_BUF);\r
1540 }\r
1541 \r
1542 void\r
1543 dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *bufp, uint len)\r
1544 {\r
1545         uint len_val;\r
1546         int i;\r
1547         char *pick;\r
1548         char *pch, *pick_tmp;\r
1549         wl_chip_nv_path_t *chip_nv_path;\r
1550         struct dhd_conf *conf = dhd->conf;\r
1551 \r
1552         pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
1553         if (!pick) {\r
1554                 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
1555                         __FUNCTION__, MAXSZ_BUF));\r
1556                 return;\r
1557         }\r
1558 \r
1559         /* Process nv_by_chip:\r
1560          * nv_by_chip=[nv_chip_num] \\r
1561          *  [chip1] [chiprev1] [nv_name1] [chip2] [chiprev2] [nv_name2] \\r
1562          * Ex: nv_by_chip=2 \\r
1563          *  43430 0 nvram_ap6212.txt 43430 1 nvram_ap6212a.txt \\r
1564          */\r
1565         memset(pick, 0, MAXSZ_BUF);\r
1566         len_val = process_config_vars(bufp, len, pick, "nv_by_chip=");\r
1567         if (len_val) {\r
1568                 pick_tmp = pick;\r
1569                 pch = bcmstrtok(&pick_tmp, " ", 0);\r
1570                 conf->nv_by_chip.count = (uint32)simple_strtol(pch, NULL, 0);\r
1571                 if (!(chip_nv_path = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_chip.count, GFP_KERNEL))) {\r
1572                         conf->nv_by_chip.count = 0;\r
1573                         CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
1574                 }\r
1575                 printf("%s: nv_by_chip_count=%d\n", __FUNCTION__, conf->nv_by_chip.count);\r
1576                 conf->nv_by_chip.m_chip_nv_path_head = chip_nv_path;\r
1577                 for (i=0; i<conf->nv_by_chip.count; i++) {\r
1578                         pch = bcmstrtok(&pick_tmp, " ", 0);\r
1579                         chip_nv_path[i].chip = (uint32)simple_strtol(pch, NULL, 0);\r
1580                         pch = bcmstrtok(&pick_tmp, " ", 0);\r
1581                         chip_nv_path[i].chiprev = (uint32)simple_strtol(pch, NULL, 0);\r
1582                         pch = bcmstrtok(&pick_tmp, " ", 0);\r
1583                         strcpy(chip_nv_path[i].name, pch);\r
1584                         printf("%s: chip=0x%x, chiprev=%d, name=%s\n", __FUNCTION__,\r
1585                                 chip_nv_path[i].chip, chip_nv_path[i].chiprev, chip_nv_path[i].name);\r
1586                 }\r
1587         }\r
1588 \r
1589         if (pick)\r
1590                 MFREE(dhd->osh, pick, MAXSZ_BUF);\r
1591 }\r
1592 \r
1593 void\r
1594 dhd_conf_read_roam_params(dhd_pub_t *dhd, char *bufp, uint len)\r
1595 {\r
1596         uint len_val;\r
1597         char *pick;\r
1598         struct dhd_conf *conf = dhd->conf;\r
1599 \r
1600         pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
1601         if (!pick) {\r
1602                 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
1603                         __FUNCTION__, MAXSZ_BUF));\r
1604                 return;\r
1605         }\r
1606 \r
1607         /* Process roam */\r
1608         memset(pick, 0, MAXSZ_BUF);\r
1609         len_val = process_config_vars(bufp, len, pick, "roam_off=");\r
1610         if (len_val) {\r
1611                 if (!strncmp(pick, "0", len_val))\r
1612                         conf->roam_off = 0;\r
1613                 else\r
1614                         conf->roam_off = 1;\r
1615                 printf("%s: roam_off = %d\n", __FUNCTION__, conf->roam_off);\r
1616         }\r
1617 \r
1618         memset(pick, 0, MAXSZ_BUF);\r
1619         len_val = process_config_vars(bufp, len, pick, "roam_off_suspend=");\r
1620         if (len_val) {\r
1621                 if (!strncmp(pick, "0", len_val))\r
1622                         conf->roam_off_suspend = 0;\r
1623                 else\r
1624                         conf->roam_off_suspend = 1;\r
1625                 printf("%s: roam_off_suspend = %d\n", __FUNCTION__,\r
1626                         conf->roam_off_suspend);\r
1627         }\r
1628 \r
1629         if (!conf->roam_off || !conf->roam_off_suspend) {\r
1630                 memset(pick, 0, MAXSZ_BUF);\r
1631                 len_val = process_config_vars(bufp, len, pick, "roam_trigger=");\r
1632                 if (len_val)\r
1633                         conf->roam_trigger[0] = (int)simple_strtol(pick, NULL, 10);\r
1634                 printf("%s: roam_trigger = %d\n", __FUNCTION__,\r
1635                         conf->roam_trigger[0]);\r
1636 \r
1637                 memset(pick, 0, MAXSZ_BUF);\r
1638                 len_val = process_config_vars(bufp, len, pick, "roam_scan_period=");\r
1639                 if (len_val)\r
1640                         conf->roam_scan_period[0] = (int)simple_strtol(pick, NULL, 10);\r
1641                 printf("%s: roam_scan_period = %d\n", __FUNCTION__,\r
1642                         conf->roam_scan_period[0]);\r
1643 \r
1644                 memset(pick, 0, MAXSZ_BUF);\r
1645                 len_val = process_config_vars(bufp, len, pick, "roam_delta=");\r
1646                 if (len_val)\r
1647                         conf->roam_delta[0] = (int)simple_strtol(pick, NULL, 10);\r
1648                 printf("%s: roam_delta = %d\n", __FUNCTION__, conf->roam_delta[0]);\r
1649 \r
1650                 memset(pick, 0, MAXSZ_BUF);\r
1651                 len_val = process_config_vars(bufp, len, pick, "fullroamperiod=");\r
1652                 if (len_val)\r
1653                         conf->fullroamperiod = (int)simple_strtol(pick, NULL, 10);\r
1654                 printf("%s: fullroamperiod = %d\n", __FUNCTION__,\r
1655                         conf->fullroamperiod);\r
1656         }\r
1657 \r
1658         if (pick)\r
1659                 MFREE(dhd->osh, pick, MAXSZ_BUF);\r
1660 \r
1661 }\r
1662 \r
1663 void\r
1664 dhd_conf_read_country_list(dhd_pub_t *dhd, char *bufp, uint len)\r
1665 {\r
1666         uint len_val;\r
1667         int i;\r
1668         char *pick, *pch, *pick_tmp;\r
1669         struct dhd_conf *conf = dhd->conf;\r
1670 \r
1671         pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
1672         if (!pick) {\r
1673                 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
1674                         __FUNCTION__, MAXSZ_BUF));\r
1675                 return;\r
1676         }\r
1677 \r
1678         /* Process country_list:\r
1679          * country_list=[country1]:[ccode1]/[regrev1],\r
1680          * [country2]:[ccode2]/[regrev2] \\r
1681          * Ex: country_list=US:US/0, TW:TW/1\r
1682          */\r
1683         memset(pick, 0, MAXSZ_BUF);\r
1684         len_val = process_config_vars(bufp, len, pick, "country_list=");\r
1685         if (len_val) {\r
1686                 pick_tmp = pick;\r
1687                 for (i=0; i<CONFIG_COUNTRY_LIST_SIZE; i++) {\r
1688                         /* Process country code */\r
1689                         pch = bcmstrtok(&pick_tmp, ":", 0);\r
1690                         if (!pch)\r
1691                                 break;\r
1692                         strcpy(conf->country_list.cspec[i].country_abbrev, pch);\r
1693                         pch = bcmstrtok(&pick_tmp, "/", 0);\r
1694                         if (!pch)\r
1695                                 break;\r
1696                         memcpy(conf->country_list.cspec[i].ccode, pch, 2);\r
1697                         pch = bcmstrtok(&pick_tmp, ", ", 0);\r
1698                         if (!pch)\r
1699                                 break;\r
1700                         conf->country_list.cspec[i].rev = (int32)simple_strtol(pch, NULL, 10);\r
1701                         conf->country_list.count ++;\r
1702                         CONFIG_TRACE(("%s: country_list abbrev=%s, ccode=%s, regrev=%d\n", __FUNCTION__,\r
1703                                 conf->country_list.cspec[i].country_abbrev,\r
1704                                 conf->country_list.cspec[i].ccode,\r
1705                                 conf->country_list.cspec[i].rev));\r
1706                 }\r
1707                 printf("%s: %d country in list\n", __FUNCTION__, conf->country_list.count);\r
1708         }\r
1709 \r
1710         if (pick)\r
1711                 MFREE(dhd->osh, pick, MAXSZ_BUF);\r
1712 }\r
1713 \r
1714 int\r
1715 dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)\r
1716 {\r
1717         int bcmerror = -1, i;\r
1718         uint len, len_val;\r
1719         void * image = NULL;\r
1720         char * memblock = NULL;\r
1721         char *bufp, *pick = NULL, *pch, *pick_tmp;\r
1722         bool conf_file_exists;\r
1723         struct dhd_conf *conf = dhd->conf;\r
1724 \r
1725         conf_file_exists = ((conf_path != NULL) && (conf_path[0] != '\0'));\r
1726         if (!conf_file_exists) {\r
1727                 printf("%s: config path %s\n", __FUNCTION__, conf_path);\r
1728                 return (0);\r
1729         }\r
1730 \r
1731         if (conf_file_exists) {\r
1732                 image = dhd_os_open_image(conf_path);\r
1733                 if (image == NULL) {\r
1734                         printf("%s: Ignore config file %s\n", __FUNCTION__, conf_path);\r
1735                         goto err;\r
1736                 }\r
1737         }\r
1738 \r
1739         memblock = MALLOC(dhd->osh, MAXSZ_CONFIG);\r
1740         if (memblock == NULL) {\r
1741                 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
1742                         __FUNCTION__, MAXSZ_CONFIG));\r
1743                 goto err;\r
1744         }\r
1745 \r
1746         pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
1747         if (!pick) {\r
1748                 CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
1749                         __FUNCTION__, MAXSZ_BUF));\r
1750                 goto err;\r
1751         }\r
1752 \r
1753         /* Read variables */\r
1754         if (conf_file_exists) {\r
1755                 len = dhd_os_get_image_block(memblock, MAXSZ_CONFIG, image);\r
1756         }\r
1757         if (len > 0 && len < MAXSZ_CONFIG) {\r
1758                 bufp = (char *)memblock;\r
1759                 bufp[len] = 0;\r
1760 \r
1761                 /* Process log_level */\r
1762                 dhd_conf_read_log_level(dhd, bufp, len);\r
1763                 dhd_conf_read_roam_params(dhd, bufp, len);\r
1764                 dhd_conf_read_wme_ac_params(dhd, bufp, len);
1765                 dhd_conf_read_fw_by_mac(dhd, bufp, len);\r
1766                 dhd_conf_read_nv_by_mac(dhd, bufp, len);\r
1767                 dhd_conf_read_nv_by_chip(dhd, bufp, len);\r
1768                 dhd_conf_read_country_list(dhd, bufp, len);\r
1769 \r
1770                 /* Process band:\r
1771                  * band=a for 5GHz only and band=b for 2.4GHz only\r
1772                  */\r
1773                 memset(pick, 0, MAXSZ_BUF);\r
1774                 len_val = process_config_vars(bufp, len, pick, "band=");\r
1775                 if (len_val) {\r
1776                         if (!strncmp(pick, "b", len_val))\r
1777                                 conf->band = WLC_BAND_2G;\r
1778                         else if (!strncmp(pick, "a", len_val))\r
1779                                 conf->band = WLC_BAND_5G;\r
1780                         else\r
1781                                 conf->band = WLC_BAND_AUTO;\r
1782                         printf("%s: band = %d\n", __FUNCTION__, conf->band);\r
1783                 }\r
1784 \r
1785                 /* Process mimo_bw_cap */\r
1786                 memset(pick, 0, MAXSZ_BUF);\r
1787                 len_val = process_config_vars(bufp, len, pick, "mimo_bw_cap=");\r
1788                 if (len_val) {\r
1789                         conf->mimo_bw_cap = (uint)simple_strtol(pick, NULL, 10);\r
1790                         printf("%s: mimo_bw_cap = %d\n", __FUNCTION__, conf->mimo_bw_cap);\r
1791                 }\r
1792 \r
1793                 /* Process country code */\r
1794                 memset(pick, 0, MAXSZ_BUF);\r
1795                 len_val = process_config_vars(bufp, len, pick, "ccode=");\r
1796                 if (len_val) {\r
1797                         memset(&conf->cspec, 0, sizeof(wl_country_t));\r
1798                         memcpy(conf->cspec.country_abbrev, pick, len_val);\r
1799                         memcpy(conf->cspec.ccode, pick, len_val);\r
1800                         memset(pick, 0, MAXSZ_BUF);\r
1801                         len_val = process_config_vars(bufp, len, pick, "regrev=");\r
1802                         if (len_val)\r
1803                                 conf->cspec.rev = (int32)simple_strtol(pick, NULL, 10);\r
1804                 }\r
1805 \r
1806                 /* Process channels */\r
1807                 memset(pick, 0, MAXSZ_BUF);\r
1808                 len_val = process_config_vars(bufp, len, pick, "channels=");\r
1809                 pick_tmp = pick;\r
1810                 if (len_val) {\r
1811                         pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
1812                         i=0;\r
1813                         while (pch != NULL && i<WL_NUMCHANNELS) {\r
1814                                 conf->channels.channel[i] = (uint32)simple_strtol(pch, NULL, 10);\r
1815                                 pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
1816                                 i++;\r
1817                         }\r
1818                         conf->channels.count = i;\r
1819                         printf("%s: channels = ", __FUNCTION__);\r
1820                         for (i=0; i<conf->channels.count; i++)\r
1821                                 printf("%d ", conf->channels.channel[i]);\r
1822                         printf("\n");\r
1823                 }\r
1824 \r
1825                 /* Process keep alive period */\r
1826                 memset(pick, 0, MAXSZ_BUF);\r
1827                 len_val = process_config_vars(bufp, len, pick, "keep_alive_period=");\r
1828                 if (len_val) {\r
1829                         conf->keep_alive_period = (uint)simple_strtol(pick, NULL, 10);\r
1830                         printf("%s: keep_alive_period = %d\n", __FUNCTION__,\r
1831                                 conf->keep_alive_period);\r
1832                 }\r
1833 \r
1834                 /* Process STBC parameters */\r
1835                 memset(pick, 0, MAXSZ_BUF);\r
1836                 len_val = process_config_vars(bufp, len, pick, "stbc=");\r
1837                 if (len_val) {\r
1838                         conf->stbc = (int)simple_strtol(pick, NULL, 10);\r
1839                         printf("%s: stbc = %d\n", __FUNCTION__, conf->stbc);\r
1840                 }\r
1841 \r
1842                 /* Process phy_oclscdenable parameters */\r
1843                 memset(pick, 0, MAXSZ_BUF);\r
1844                 len_val = process_config_vars(bufp, len, pick, "phy_oclscdenable=");\r
1845                 if (len_val) {\r
1846                         conf->phy_oclscdenable = (int)simple_strtol(pick, NULL, 10);\r
1847                         printf("%s: phy_oclscdenable = %d\n", __FUNCTION__, conf->phy_oclscdenable);\r
1848                 }\r
1849 \r
1850 #ifdef BCMSDIO\r
1851                 /* Process dhd_doflow parameters */\r
1852                 memset(pick, 0, MAXSZ_BUF);\r
1853                 len_val = process_config_vars(bufp, len, pick, "dhd_doflow=");\r
1854                 if (len_val) {\r
1855                         if (!strncmp(pick, "0", len_val))\r
1856                                 dhd_doflow = FALSE;\r
1857                         else\r
1858                                 dhd_doflow = TRUE;\r
1859                         printf("%s: dhd_doflow = %d\n", __FUNCTION__, dhd_doflow);\r
1860                 }\r
1861 \r
1862                 /* Process dhd_slpauto parameters */\r
1863                 memset(pick, 0, MAXSZ_BUF);\r
1864                 len_val = process_config_vars(bufp, len, pick, "dhd_slpauto=");\r
1865                 if (len_val) {\r
1866                         if (!strncmp(pick, "0", len_val))\r
1867                                 dhd_slpauto = FALSE;\r
1868                         else\r
1869                                 dhd_slpauto = TRUE;\r
1870                         printf("%s: dhd_slpauto = %d\n", __FUNCTION__, dhd_slpauto);\r
1871                 }\r
1872 #endif\r
1873 \r
1874                 /* Process dhd_master_mode parameters */\r
1875                 memset(pick, 0, MAXSZ_BUF);\r
1876                 len_val = process_config_vars(bufp, len, pick, "dhd_master_mode=");\r
1877                 if (len_val) {\r
1878                         if (!strncmp(pick, "0", len_val))\r
1879                                 dhd_master_mode = FALSE;\r
1880                         else\r
1881                                 dhd_master_mode = TRUE;\r
1882                         printf("%s: dhd_master_mode = %d\n", __FUNCTION__, dhd_master_mode);\r
1883                 }\r
1884 \r
1885 #ifdef PKT_FILTER_SUPPORT\r
1886                 /* Process pkt_filter_add:\r
1887                  * All pkt: pkt_filter_add=99 0 0 0 0x000000000000 0x000000000000\r
1888                  */\r
1889                 memset(pick, 0, MAXSZ_BUF);\r
1890                 len_val = process_config_vars(bufp, len, pick, "pkt_filter_add=");\r
1891                 pick_tmp = pick;\r
1892                 if (len_val) {\r
1893                         pch = bcmstrtok(&pick_tmp, ",.-", 0);\r
1894                         i=0;\r
1895                         while (pch != NULL && i<DHD_CONF_FILTER_MAX) {\r
1896                                 strcpy(&conf->pkt_filter_add.filter[i][0], pch);\r
1897                                 printf("%s: pkt_filter_add[%d][] = %s\n", __FUNCTION__, i, &conf->pkt_filter_add.filter[i][0]);\r
1898                                 pch = bcmstrtok(&pick_tmp, ",.-", 0);\r
1899                                 i++;\r
1900                         }\r
1901                         conf->pkt_filter_add.count = i;\r
1902                 }\r
1903 \r
1904                 /* Process pkt_filter_del */\r
1905                 memset(pick, 0, MAXSZ_BUF);\r
1906                 len_val = process_config_vars(bufp, len, pick, "pkt_filter_del=");\r
1907                 pick_tmp = pick;\r
1908                 if (len_val) {\r
1909                         pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
1910                         i=0;\r
1911                         while (pch != NULL && i<DHD_CONF_FILTER_MAX) {\r
1912                                 conf->pkt_filter_del.id[i] = (uint32)simple_strtol(pch, NULL, 10);\r
1913                                 pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
1914                                 i++;\r
1915                         }\r
1916                         conf->pkt_filter_del.count = i;\r
1917                         printf("%s: pkt_filter_del id = ", __FUNCTION__);\r
1918                         for (i=0; i<conf->pkt_filter_del.count; i++)\r
1919                                 printf("%d ", conf->pkt_filter_del.id[i]);\r
1920                         printf("\n");\r
1921                 }\r
1922 #endif\r
1923 \r
1924                 /* Process srl parameters */\r
1925                 memset(pick, 0, MAXSZ_BUF);\r
1926                 len_val = process_config_vars(bufp, len, pick, "srl=");\r
1927                 if (len_val) {\r
1928                         conf->srl = (int)simple_strtol(pick, NULL, 10);\r
1929                         printf("%s: srl = %d\n", __FUNCTION__, conf->srl);\r
1930                 }\r
1931 \r
1932                 /* Process lrl parameters */\r
1933                 memset(pick, 0, MAXSZ_BUF);\r
1934                 len_val = process_config_vars(bufp, len, pick, "lrl=");\r
1935                 if (len_val) {\r
1936                         conf->lrl = (int)simple_strtol(pick, NULL, 10);\r
1937                         printf("%s: lrl = %d\n", __FUNCTION__, conf->lrl);\r
1938                 }\r
1939 \r
1940                 /* Process beacon timeout parameters */\r
1941                 memset(pick, 0, MAXSZ_BUF);\r
1942                 len_val = process_config_vars(bufp, len, pick, "bcn_timeout=");\r
1943                 if (len_val) {\r
1944                         conf->bcn_timeout= (uint)simple_strtol(pick, NULL, 10);\r
1945                         printf("%s: bcn_timeout = %d\n", __FUNCTION__, conf->bcn_timeout);\r
1946                 }\r
1947 \r
1948                 /* Process bus:txglom */\r
1949                 memset(pick, 0, MAXSZ_BUF);\r
1950                 len_val = process_config_vars(bufp, len, pick, "bus:txglom=");\r
1951                 if (len_val) {\r
1952                         conf->bus_txglom = (int)simple_strtol(pick, NULL, 10);\r
1953                         printf("%s: bus:txglom = %d\n", __FUNCTION__, conf->bus_txglom);
1954                 }\r
1955 \r
1956                 /* Process ampdu_ba_wsize parameters */\r
1957                 memset(pick, 0, MAXSZ_BUF);\r
1958                 len_val = process_config_vars(bufp, len, pick, "ampdu_ba_wsize=");\r
1959                 if (len_val) {\r
1960                         conf->ampdu_ba_wsize = (int)simple_strtol(pick, NULL, 10);\r
1961                         printf("%s: ampdu_ba_wsize = %d\n", __FUNCTION__, conf->ampdu_ba_wsize);\r
1962                 }\r
1963 \r
1964                 /* Process kso_enable parameters */\r
1965                 memset(pick, 0, MAXSZ_BUF);\r
1966                 len_val = process_config_vars(bufp, len, pick, "kso_enable=");\r
1967                 if (len_val) {\r
1968                         if (!strncmp(pick, "0", len_val))\r
1969                                 conf->kso_enable = FALSE;\r
1970                         else\r
1971                                 conf->kso_enable = TRUE;\r
1972                         printf("%s: kso_enable = %d\n", __FUNCTION__, conf->kso_enable);\r
1973                 }\r
1974 \r
1975                 /* Process spect parameters */\r
1976                 memset(pick, 0, MAXSZ_BUF);\r
1977                 len_val = process_config_vars(bufp, len, pick, "spect=");\r
1978                 if (len_val) {\r
1979                         conf->spect = (int)simple_strtol(pick, NULL, 10);\r
1980                         printf("%s: spect = %d\n", __FUNCTION__, conf->spect);\r
1981                 }\r
1982 \r
1983                 /* Process txbf parameters */\r
1984                 memset(pick, 0, MAXSZ_BUF);\r
1985                 len_val = process_config_vars(bufp, len, pick, "txbf=");\r
1986                 if (len_val) {\r
1987                         conf->txbf = (int)simple_strtol(pick, NULL, 10);\r
1988                         printf("%s: txbf = %d\n", __FUNCTION__, conf->txbf);\r
1989                 }\r
1990 \r
1991                 /* Process frameburst parameters */\r
1992                 memset(pick, 0, MAXSZ_BUF);\r
1993                 len_val = process_config_vars(bufp, len, pick, "frameburst=");\r
1994                 if (len_val) {\r
1995                         conf->frameburst = (int)simple_strtol(pick, NULL, 10);\r
1996                         printf("%s: frameburst = %d\n", __FUNCTION__, conf->frameburst);\r
1997                 }\r
1998 \r
1999                 /* Process lpc parameters */\r
2000                 memset(pick, 0, MAXSZ_BUF);\r
2001                 len_val = process_config_vars(bufp, len, pick, "lpc=");\r
2002                 if (len_val) {\r
2003                         conf->lpc = (int)simple_strtol(pick, NULL, 10);\r
2004                         printf("%s: lpc = %d\n", __FUNCTION__, conf->lpc);\r
2005                 }\r
2006 \r
2007                 /* Process use_rxchain parameters */\r
2008                 memset(pick, 0, MAXSZ_BUF);\r
2009                 len_val = process_config_vars(bufp, len, pick, "use_rxchain=");\r
2010                 if (len_val) {\r
2011                         conf->use_rxchain = (int)simple_strtol(pick, NULL, 10);\r
2012                         printf("%s: use_rxchain = %d\n", __FUNCTION__, conf->use_rxchain);\r
2013                 }\r
2014 \r
2015 #if defined(BCMSDIOH_TXGLOM)
2016                 /* Process txglomsize parameters */\r
2017                 memset(pick, 0, MAXSZ_BUF);\r
2018                 len_val = process_config_vars(bufp, len, pick, "txglomsize=");\r
2019                 if (len_val) {\r
2020                         conf->txglomsize = (uint)simple_strtol(pick, NULL, 10);\r
2021                         if (conf->txglomsize > SDPCM_MAXGLOM_SIZE)\r
2022                                 conf->txglomsize = SDPCM_MAXGLOM_SIZE;\r
2023                         printf("%s: txglomsize = %d\n", __FUNCTION__, conf->txglomsize);\r
2024                 }\r
2025
2026                 /* Process swtxglom parameters */\r
2027                 memset(pick, 0, MAXSZ_BUF);
2028                 len_val = process_config_vars(bufp, len, pick, "swtxglom=");\r
2029                 if (len_val) {
2030                         if (!strncmp(pick, "0", len_val))
2031                                 conf->swtxglom = FALSE;\r
2032                         else
2033                                 conf->swtxglom = TRUE;\r
2034                         printf("%s: swtxglom = %d\n", __FUNCTION__, conf->swtxglom);\r
2035                 }\r
2036 \r
2037                 /* Process txglom_ext parameters */
2038                 memset(pick, 0, MAXSZ_BUF);
2039                 len_val = process_config_vars(bufp, len, pick, "txglom_ext=");
2040                 if (len_val) {
2041                         if (!strncmp(pick, "0", len_val))
2042                                 conf->txglom_ext = FALSE;
2043                         else
2044                                 conf->txglom_ext = TRUE;
2045                         printf("%s: txglom_ext = %d\n", __FUNCTION__, conf->txglom_ext);
2046                         if (conf->txglom_ext) {
2047                                 if ((conf->chip == BCM43362_CHIP_ID) || (conf->chip == BCM4330_CHIP_ID))
2048                                         conf->txglom_bucket_size = 1680;
2049                                 else if (conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||
2050                                                 conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID)\r
2051                                         conf->txglom_bucket_size = 1684;
2052                         }
2053                         printf("%s: txglom_bucket_size = %d\n", __FUNCTION__, conf->txglom_bucket_size);
2054                 }
2055 #endif\r
2056 \r
2057                 /* Process disable_proptx parameters */\r
2058                 memset(pick, 0, MAXSZ_BUF);\r
2059                 len_val = process_config_vars(bufp, len, pick, "disable_proptx=");\r
2060                 if (len_val) {\r
2061                         conf->disable_proptx = (int)simple_strtol(pick, NULL, 10);
2062                         printf("%s: disable_proptx = %d\n", __FUNCTION__, conf->disable_proptx);
2063                 }\r
2064 \r
2065                 /* Process dpc_cpucore parameters */\r
2066                 memset(pick, 0, MAXSZ_BUF);\r
2067                 len_val = process_config_vars(bufp, len, pick, "dpc_cpucore=");\r
2068                 if (len_val) {\r
2069                         conf->dpc_cpucore = (int)simple_strtol(pick, NULL, 10);\r
2070                         printf("%s: dpc_cpucore = %d\n", __FUNCTION__, conf->dpc_cpucore);\r
2071                 }\r
2072 \r
2073                 /* Process bus:rxglom parameters */\r
2074                 memset(pick, 0, MAXSZ_BUF);\r
2075                 len_val = process_config_vars(bufp, len, pick, "bus:rxglom=");\r
2076                 if (len_val) {\r
2077                         if (!strncmp(pick, "0", len_val))\r
2078                                 conf->bus_rxglom = FALSE;\r
2079                         else\r
2080                                 conf->bus_rxglom = TRUE;\r
2081                         printf("%s: bus:rxglom = %d\n", __FUNCTION__, conf->bus_rxglom);\r
2082                 }\r
2083 \r
2084                 /* Process deepsleep parameters */\r
2085                 memset(pick, 0, MAXSZ_BUF);\r
2086                 len_val = process_config_vars(bufp, len, pick, "deepsleep=");\r
2087                 if (len_val) {\r
2088                         if (!strncmp(pick, "1", len_val))\r
2089                                 conf->deepsleep = TRUE;\r
2090                         else\r
2091                                 conf->deepsleep = FALSE;\r
2092                         printf("%s: deepsleep = %d\n", __FUNCTION__, conf->deepsleep);\r
2093                 }\r
2094 \r
2095                 /* Process PM parameters */\r
2096                 memset(pick, 0, MAXSZ_BUF);\r
2097                 len_val = process_config_vars(bufp, len, pick, "PM=");\r
2098                 if (len_val) {\r
2099                         conf->pm = (int)simple_strtol(pick, NULL, 10);\r
2100                         printf("%s: PM = %d\n", __FUNCTION__, conf->pm);\r
2101                 }\r
2102 \r
2103                 /* Process tcpack_sup_mode parameters */\r
2104                 memset(pick, 0, MAXSZ_BUF);\r
2105                 len_val = process_config_vars(bufp, len, pick, "tcpack_sup_mode=");\r
2106                 if (len_val) {\r
2107                         conf->tcpack_sup_mode = (uint)simple_strtol(pick, NULL, 10);\r
2108                         printf("%s: tcpack_sup_mode = %d\n", __FUNCTION__, conf->tcpack_sup_mode);\r
2109                 }\r
2110 \r
2111                 /* Process dhd_poll parameters */\r
2112                 memset(pick, 0, MAXSZ_BUF);\r
2113                 len_val = process_config_vars(bufp, len, pick, "dhd_poll=");\r
2114                 if (len_val) {\r
2115                         if (!strncmp(pick, "0", len_val))\r
2116                                 conf->dhd_poll = 0;\r
2117                         else\r
2118                                 conf->dhd_poll = 1;\r
2119                         printf("%s: dhd_poll = %d\n", __FUNCTION__, conf->dhd_poll);\r
2120                 }\r
2121 \r
2122                 /* Process deferred_tx_len parameters */\r
2123                 memset(pick, 0, MAXSZ_BUF);\r
2124                 len_val = process_config_vars(bufp, len, pick, "deferred_tx_len=");\r
2125                 if (len_val) {\r
2126                         conf->deferred_tx_len = (int)simple_strtol(pick, NULL, 10);\r
2127                         printf("%s: deferred_tx_len = %d\n", __FUNCTION__, conf->deferred_tx_len);\r
2128                 }\r
2129 \r
2130                 /* Process pktprio8021x parameters */\r
2131                 memset(pick, 0, MAXSZ_BUF);\r
2132                 len_val = process_config_vars(bufp, len, pick, "pktprio8021x=");\r
2133                 if (len_val) {\r
2134                         conf->pktprio8021x = (int)simple_strtol(pick, NULL, 10);\r
2135                         printf("%s: pktprio8021x = %d\n", __FUNCTION__, conf->pktprio8021x);\r
2136                 }
2137
2138                 /* Process txctl_tmo_fix parameters */
2139                 memset(pick, 0, MAXSZ_BUF);
2140                 len_val = process_config_vars(bufp, len, pick, "txctl_tmo_fix=");
2141                 if (len_val) {
2142                         if (!strncmp(pick, "0", len_val))
2143                                 conf->txctl_tmo_fix = FALSE;
2144                         else
2145                                 conf->txctl_tmo_fix = TRUE;
2146                         printf("%s: txctl_tmo_fix = %d\n", __FUNCTION__, conf->txctl_tmo_fix);
2147                 }
2148
2149                 /* Process tx_in_rx parameters */
2150                 memset(pick, 0, MAXSZ_BUF);
2151                 len_val = process_config_vars(bufp, len, pick, "tx_in_rx=");
2152                 if (len_val) {
2153                         if (!strncmp(pick, "0", len_val))
2154                                 conf->tx_in_rx = FALSE;
2155                         else
2156                                 conf->tx_in_rx = TRUE;
2157                         printf("%s: tx_in_rx = %d\n", __FUNCTION__, conf->tx_in_rx);
2158                 }
2159
2160                 /* Process dhd_txbound parameters */
2161                 memset(pick, 0, MAXSZ_BUF);
2162                 len_val = process_config_vars(bufp, len, pick, "dhd_txbound=");
2163                 if (len_val) {
2164                         dhd_txbound = (uint)simple_strtol(pick, NULL, 10);
2165                         printf("%s: dhd_txbound = %d\n", __FUNCTION__, dhd_txbound);
2166                 }
2167
2168                 /* Process dhd_rxbound parameters */
2169                 memset(pick, 0, MAXSZ_BUF);
2170                 len_val = process_config_vars(bufp, len, pick, "dhd_rxbound=");
2171                 if (len_val) {
2172                         dhd_rxbound = (uint)simple_strtol(pick, NULL, 10);
2173                         printf("%s: dhd_rxbound = %d\n", __FUNCTION__, dhd_rxbound);
2174                 }\r
2175 \r
2176                 /* Process tx_max_offset parameters */\r
2177                 memset(pick, 0, MAXSZ_BUF);\r
2178                 len_val = process_config_vars(bufp, len, pick, "tx_max_offset=");\r
2179                 if (len_val) {\r
2180                         conf->tx_max_offset = (int)simple_strtol(pick, NULL, 10);\r
2181                         printf("%s: tx_max_offset = %d\n", __FUNCTION__, conf->tx_max_offset);\r
2182                 }\r
2183 \r
2184                 /* Process rsdb_mode parameters */\r
2185                 memset(pick, 0, MAXSZ_BUF);\r
2186                 len_val = process_config_vars(bufp, len, pick, "rsdb_mode=");\r
2187                 if (len_val) {\r
2188                         conf->rsdb_mode = (int)simple_strtol(pick, NULL, 10);\r
2189                         printf("%s: rsdb_mode = %d\n", __FUNCTION__, conf->rsdb_mode);\r
2190                 }\r
2191
2192                 /* Process txglom_mode parameters */\r
2193                 memset(pick, 0, MAXSZ_BUF);
2194                 len_val = process_config_vars(bufp, len, pick, "txglom_mode=");\r
2195                 if (len_val) {
2196                         if (!strncmp(pick, "0", len_val))
2197                                 conf->txglom_mode = FALSE;\r
2198                         else
2199                                 conf->txglom_mode = TRUE;\r
2200                         printf("%s: txglom_mode = %d\n", __FUNCTION__, conf->txglom_mode);\r
2201                 }\r
2202 \r
2203                 bcmerror = 0;\r
2204         } else {\r
2205                 CONFIG_ERROR(("%s: error reading config file: %d\n", __FUNCTION__, len));\r
2206                 bcmerror = BCME_SDIO_ERROR;\r
2207         }\r
2208 \r
2209 err:\r
2210         if (pick)\r
2211                 MFREE(dhd->osh, pick, MAXSZ_BUF);\r
2212 \r
2213         if (memblock)\r
2214                 MFREE(dhd->osh, memblock, MAXSZ_CONFIG);\r
2215 \r
2216         if (image)\r
2217                 dhd_os_close_image(image);\r
2218 \r
2219         return bcmerror;\r
2220 }\r
2221 \r
2222 int\r
2223 dhd_conf_set_chiprev(dhd_pub_t *dhd, uint chip, uint chiprev)\r
2224 {\r
2225         printf("%s: chip=0x%x, chiprev=%d\n", __FUNCTION__, chip, chiprev);\r
2226         dhd->conf->chip = chip;\r
2227         dhd->conf->chiprev = chiprev;\r
2228         return 0;\r
2229 }\r
2230 \r
2231 uint\r
2232 dhd_conf_get_chip(void *context)\r
2233 {\r
2234         dhd_pub_t *dhd = context;\r
2235 \r
2236         if (dhd && dhd->conf)\r
2237                 return dhd->conf->chip;\r
2238         return 0;\r
2239 }\r
2240 \r
2241 uint\r
2242 dhd_conf_get_chiprev(void *context)\r
2243 {\r
2244         dhd_pub_t *dhd = context;\r
2245 \r
2246         if (dhd && dhd->conf)\r
2247                 return dhd->conf->chiprev;\r
2248         return 0;\r
2249 }\r
2250 \r
2251 void\r
2252 dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable)\r
2253 {\r
2254         struct dhd_conf *conf = dhd->conf;\r
2255 \r
2256         if (enable) {\r
2257 #if defined(SWTXGLOM)\r
2258                 if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID ||\r
2259                                 conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||\r
2260                                 conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {\r
2261                         // 43362/4330/4334/43340/43341/43241 must use 1.88.45.x swtxglom if txglom_ext is true, since 1.201.59 not support swtxglom\r
2262                         conf->swtxglom = TRUE;\r
2263                         conf->txglom_ext = TRUE;\r
2264                 }\r
2265                 if (conf->chip == BCM43362_CHIP_ID && conf->bus_txglom == 0) {\r
2266                         conf->bus_txglom = 1; // improve tcp tx tput. and cpu idle for 43362 only\r
2267                 }\r
2268 #endif\r
2269                 // other parameters set in preinit or config.txt\r
2270         } else {\r
2271                 // clear txglom parameters, but don't change swtxglom since it's possible enabled in config.txt\r
2272                 conf->txglom_ext = FALSE;\r
2273                 conf->txglom_bucket_size = 0;\r
2274                 conf->tx_in_rx = TRUE;\r
2275                 conf->tx_max_offset = 0;\r
2276                 conf->txglomsize = 0;\r
2277                 conf->deferred_tx_len = 0;\r
2278         }\r
2279         printf("%s: swtxglom=%d, txglom_ext=%d\n", __FUNCTION__,\r
2280                 conf->swtxglom, conf->txglom_ext);\r
2281         printf("%s: txglom_bucket_size=%d\n", __FUNCTION__, conf->txglom_bucket_size);\r
2282         printf("%s: txglomsize=%d, deferred_tx_len=%d, bus_txglom=%d\n", __FUNCTION__,\r
2283                 conf->txglomsize, conf->deferred_tx_len, conf->bus_txglom);\r
2284         printf("%s: tx_in_rx=%d, tx_max_offset=%d\n", __FUNCTION__,\r
2285                 conf->tx_in_rx, conf->tx_max_offset);\r
2286 \r
2287 }\r
2288 \r
2289 int\r
2290 dhd_conf_preinit(dhd_pub_t *dhd)\r
2291 {\r
2292         struct dhd_conf *conf = dhd->conf;\r
2293 \r
2294         CONFIG_TRACE(("%s: Enter\n", __FUNCTION__));\r
2295 \r
2296 #ifdef BCMSDIO\r
2297         dhd_conf_free_mac_list(&conf->fw_by_mac);\r
2298         dhd_conf_free_mac_list(&conf->nv_by_mac);\r
2299         dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
2300 #endif\r
2301         memset(&conf->country_list, 0, sizeof(conf_country_list_t));\r
2302         conf->band = WLC_BAND_AUTO;\r
2303         conf->mimo_bw_cap = -1;\r
2304         if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {\r
2305                 strcpy(conf->cspec.country_abbrev, "ALL");\r
2306                 strcpy(conf->cspec.ccode, "ALL");\r
2307                 conf->cspec.rev = 0;\r
2308         } else if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||\r
2309                         conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
2310                         conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||\r
2311                         conf->chip == BCM4359_CHIP_ID) {\r
2312                 strcpy(conf->cspec.country_abbrev, "CN");\r
2313                 strcpy(conf->cspec.ccode, "CN");\r
2314                 conf->cspec.rev = 38;\r
2315         } else {\r
2316                 strcpy(conf->cspec.country_abbrev, "CN");\r
2317                 strcpy(conf->cspec.ccode, "CN");\r
2318                 conf->cspec.rev = 0;\r
2319         }\r
2320         memset(&conf->channels, 0, sizeof(wl_channel_list_t));\r
2321         conf->roam_off = 1;\r
2322         conf->roam_off_suspend = 1;\r
2323 #ifdef CUSTOM_ROAM_TRIGGER_SETTING\r
2324         conf->roam_trigger[0] = CUSTOM_ROAM_TRIGGER_SETTING;\r
2325 #else\r
2326         conf->roam_trigger[0] = -65;\r
2327 #endif\r
2328         conf->roam_trigger[1] = WLC_BAND_ALL;\r
2329         conf->roam_scan_period[0] = 10;\r
2330         conf->roam_scan_period[1] = WLC_BAND_ALL;\r
2331 #ifdef CUSTOM_ROAM_DELTA_SETTING\r
2332         conf->roam_delta[0] = CUSTOM_ROAM_DELTA_SETTING;\r
2333 #else\r
2334         conf->roam_delta[0] = 15;\r
2335 #endif\r
2336         conf->roam_delta[1] = WLC_BAND_ALL;\r
2337 #ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC
2338         conf->fullroamperiod = 60;\r
2339 #else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */
2340         conf->fullroamperiod = 120;\r
2341 #endif /* FULL_ROAMING_SCAN_PERIOD_60_SEC */\r
2342 #ifdef CUSTOM_KEEP_ALIVE_SETTING\r
2343         conf->keep_alive_period = CUSTOM_KEEP_ALIVE_SETTING;\r
2344 #else\r
2345         conf->keep_alive_period = 28000;\r
2346 #endif\r
2347         conf->force_wme_ac = 0;\r
2348         conf->stbc = -1;\r
2349         conf->phy_oclscdenable = -1;\r
2350 #ifdef PKT_FILTER_SUPPORT\r
2351         memset(&conf->pkt_filter_add, 0, sizeof(conf_pkt_filter_add_t));\r
2352         memset(&conf->pkt_filter_del, 0, sizeof(conf_pkt_filter_del_t));\r
2353         conf->pkt_filter_magic = FALSE;\r
2354 #endif\r
2355         conf->srl = -1;\r
2356         conf->lrl = -1;\r
2357         conf->bcn_timeout = 15;\r
2358         conf->kso_enable = TRUE;\r
2359         conf->spect = -1;\r
2360         conf->txbf = -1;\r
2361         conf->lpc = -1;\r
2362         conf->disable_proptx = 0;\r
2363         conf->bus_txglom = 0;\r
2364         conf->use_rxchain = 0;\r
2365         conf->bus_rxglom = TRUE;\r
2366         conf->txglom_ext = FALSE;\r
2367         conf->tx_max_offset = 0;\r
2368         conf->deferred_tx_len = 0;\r
2369         conf->txglomsize = SDPCM_DEFGLOM_SIZE;\r
2370         conf->ampdu_ba_wsize = 0;\r
2371         conf->dpc_cpucore = 0;\r
2372         conf->frameburst = -1;\r
2373         conf->deepsleep = FALSE;\r
2374         conf->pm = -1;\r
2375 #ifdef DHDTCPACK_SUPPRESS
2376         conf->tcpack_sup_mode = TCPACK_SUP_OFF;\r
2377 #endif\r
2378         conf->dhd_poll = -1;\r
2379         conf->pktprio8021x = -1;
2380         conf->txctl_tmo_fix = FALSE;
2381         conf->tx_in_rx = TRUE;\r
2382         conf->rsdb_mode = -2;\r
2383         conf->txglom_mode = SDPCM_TXGLOM_CPY;
2384         if ((conf->chip == BCM43362_CHIP_ID) || (conf->chip == BCM4330_CHIP_ID)) {\r
2385                 conf->disable_proptx = 1;\r
2386                 conf->use_rxchain = 0;\r
2387         }
2388         if (conf->chip == BCM4354_CHIP_ID) {
2389                 conf->disable_proptx = 1;
2390         }
2391         if (conf->chip == BCM43430_CHIP_ID) {\r
2392                 conf->bus_rxglom = FALSE;\r
2393                 conf->use_rxchain = 0;\r
2394         }
2395         if (conf->chip == BCM4339_CHIP_ID) {\r
2396                 conf->txbf = 1;\r
2397         }\r
2398         if (conf->chip == BCM4345_CHIP_ID) {\r
2399                 conf->txbf = 1;\r
2400         }\r
2401         if (conf->chip == BCM4354_CHIP_ID) {\r
2402                 conf->txbf = 1;\r
2403         }\r
2404         if (conf->chip == BCM4356_CHIP_ID) {\r
2405                 conf->txbf = 1;\r
2406         }\r
2407         if (conf->chip == BCM4371_CHIP_ID) {\r
2408                 conf->txbf = 1;\r
2409         }\r
2410         if (conf->chip == BCM4359_CHIP_ID) {\r
2411                 conf->txbf = 1;\r
2412                 conf->rsdb_mode = 0;\r
2413         }\r
2414 #ifdef BCMSDIO\r
2415         if (conf->chip == BCM4356_CHIP_ID) {\r
2416                 conf->txbf = 1;\r
2417         }\r
2418 #elif defined(BCMPCIE)\r
2419         if (conf->chip == BCM4356_CHIP_ID) {\r
2420                 conf->txbf = 1;\r
2421         }\r
2422 #endif\r
2423 \r
2424 #if defined(SWTXGLOM)\r
2425         if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID ||\r
2426                         conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||\r
2427                         conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {\r
2428                 conf->swtxglom = FALSE; // disabled by default\r
2429                 conf->txglom_ext = TRUE; // enabled by default\r
2430                 conf->use_rxchain = 0; // use_rxchain have been disabled if swtxglom enabled\r
2431                 conf->txglomsize = 16;\r
2432         } else {\r
2433                 conf->swtxglom = FALSE; // use 1.201.59.x txglom by default\r
2434                 conf->txglom_ext = FALSE;\r
2435         }\r
2436 \r
2437         if (conf->chip == BCM43362_CHIP_ID) {\r
2438                 conf->txglom_bucket_size = 1680; // fixed value, don't change\r
2439                 conf->tx_in_rx = FALSE;\r
2440                 conf->tx_max_offset = 1;\r
2441         }\r
2442         if (conf->chip == BCM4330_CHIP_ID) {\r
2443                 conf->txglom_bucket_size = 1680; // fixed value, don't change\r
2444                 conf->tx_in_rx = FALSE;\r
2445                 conf->tx_max_offset = 0;\r
2446         }\r
2447         if (conf->chip == BCM4334_CHIP_ID) {\r
2448                 conf->txglom_bucket_size = 1684; // fixed value, don't change\r
2449                 conf->tx_in_rx = TRUE; // improve tcp tx tput. and cpu idle\r
2450                 conf->tx_max_offset = 0; // reduce udp tx: dhdsdio_readframes: got unlikely tx max 109 with tx_seq 110\r
2451         }\r
2452         if (conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID) {\r
2453                 conf->txglom_bucket_size = 1684; // fixed value, don't change\r
2454                 conf->tx_in_rx = TRUE; // improve tcp tx tput. and cpu idle\r
2455                 conf->tx_max_offset = 1;\r
2456         }\r
2457         if (conf->chip == BCM4324_CHIP_ID) {\r
2458                 conf->txglom_bucket_size = 1684; // fixed value, don't change\r
2459                 conf->tx_in_rx = TRUE; // improve tcp tx tput. and cpu idle\r
2460                 conf->tx_max_offset = 0;\r
2461         }\r
2462 #endif\r
2463 #if defined(BCMSDIOH_TXGLOM_EXT)\r
2464         conf->txglom_mode = SDPCM_TXGLOM_CPY;\r
2465         if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID ||\r
2466                         conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||\r
2467                         conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {\r
2468                 conf->txglom_ext = TRUE;\r
2469                 conf->use_rxchain = 0;\r
2470                 conf->tx_in_rx = TRUE;\r
2471                 conf->tx_max_offset = 1;\r
2472         } else {\r
2473                 conf->txglom_ext = FALSE;\r
2474         }\r
2475         if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {\r
2476                 conf->txglom_bucket_size = 1680; // fixed value, don't change\r
2477                 conf->txglomsize = 6;\r
2478         }\r
2479         if (conf->chip == BCM4334_CHIP_ID || conf->chip == BCM43340_CHIP_ID ||\r
2480                         conf->chip == BCM43341_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {\r
2481                 conf->txglom_bucket_size = 1684; // fixed value, don't change\r
2482                 conf->txglomsize = 16;\r
2483         }\r
2484 #endif\r
2485         if (conf->txglomsize > SDPCM_MAXGLOM_SIZE)\r
2486                 conf->txglomsize = SDPCM_MAXGLOM_SIZE;\r
2487         conf->deferred_tx_len = conf->txglomsize;\r
2488 \r
2489         return 0;\r
2490 }\r
2491 \r
2492 int\r
2493 dhd_conf_reset(dhd_pub_t *dhd)\r
2494 {\r
2495 #ifdef BCMSDIO\r
2496         dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);\r
2497         dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);\r
2498         dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);\r
2499 #endif\r
2500         memset(dhd->conf, 0, sizeof(dhd_conf_t));\r
2501         return 0;\r
2502 }\r
2503 \r
2504 int\r
2505 dhd_conf_attach(dhd_pub_t *dhd)\r
2506 {\r
2507         dhd_conf_t *conf;\r
2508 \r
2509         CONFIG_TRACE(("%s: Enter\n", __FUNCTION__));\r
2510 \r
2511         if (dhd->conf != NULL) {\r
2512                 printf("%s: config is attached before!\n", __FUNCTION__);\r
2513                 return 0;\r
2514         }\r
2515         /* Allocate private bus interface state */\r
2516         if (!(conf = MALLOC(dhd->osh, sizeof(dhd_conf_t)))) {\r
2517                 CONFIG_ERROR(("%s: MALLOC failed\n", __FUNCTION__));\r
2518                 goto fail;\r
2519         }\r
2520         memset(conf, 0, sizeof(dhd_conf_t));\r
2521 \r
2522         dhd->conf = conf;\r
2523 \r
2524         return 0;\r
2525 \r
2526 fail:\r
2527         if (conf != NULL)\r
2528                 MFREE(dhd->osh, conf, sizeof(dhd_conf_t));\r
2529         return BCME_NOMEM;\r
2530 }\r
2531 \r
2532 void\r
2533 dhd_conf_detach(dhd_pub_t *dhd)\r
2534 {\r
2535         CONFIG_TRACE(("%s: Enter\n", __FUNCTION__));\r
2536 \r
2537         if (dhd->conf) {\r
2538 #ifdef BCMSDIO\r
2539                 dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);\r
2540                 dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);\r
2541                 dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);\r
2542 #endif\r
2543                 MFREE(dhd->osh, dhd->conf, sizeof(dhd_conf_t));\r
2544         }\r
2545         dhd->conf = NULL;\r
2546 }\r