net: wireless: rockchip_wlan: add rtl8723cs support
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723cs / hal / hal_halmac.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2015 - 2016 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _HAL_HALMAC_C_
21
22 #include <drv_types.h>          /* PADAPTER, struct dvobj_priv, SDIO_ERR_VAL8 and etc. */
23 #include <hal_data.h>           /* efuse, PHAL_DATA_TYPE and etc. */
24 #include "halmac/halmac_api.h"  /* HALMAC_FW_SIZE_MAX_88XX and etc. */
25 #include "hal_halmac.h"         /* dvobj_to_halmac() and ect. */
26
27 #define DEFAULT_INDICATOR_TIMELMT       1000    /* ms */
28 #define FIRMWARE_MAX_SIZE               HALMAC_FW_SIZE_MAX_88XX
29
30 /*
31  * Driver API for HALMAC operations
32  */
33
34 #ifdef CONFIG_SDIO_HCI
35 #include <rtw_sdio.h>
36
37 static u8 _halmac_mac_reg_page0_chk(const char *func, struct dvobj_priv *dvobj, u32 offset)
38 {
39 #if defined(CONFIG_IO_CHECK_IN_ANA_LOW_CLK) && defined(CONFIG_LPS_LCLK)
40         struct pwrctrl_priv *pwrpriv = &dvobj->pwrctl_priv;
41         u32 mac_reg_offset = 0;
42
43         if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
44                 return _TRUE;
45
46         if (pwrpriv->rpwm >= PS_STATE_S2)
47                 return _TRUE;
48
49         if (offset & (WLAN_IOREG_DEVICE_ID << 13))  { /*WLAN_IOREG_OFFSET*/
50                 mac_reg_offset = offset & HALMAC_WLAN_MAC_REG_MSK;
51                 if (mac_reg_offset < 0x100) {
52                         RTW_ERR(FUNC_ADPT_FMT "access MAC REG -0x%04x in PS-mode:0x%02x\n",
53                                 FUNC_ADPT_ARG(dvobj_get_primary_adapter(dvobj)), mac_reg_offset, pwrpriv->pwr_mode);
54                         rtw_warn_on(1);
55                         return _FALSE;
56                 }
57         }
58 #endif
59         return _TRUE;
60 }
61
62 static u8 _halmac_sdio_cmd52_read(void *p, u32 offset)
63 {
64         struct dvobj_priv *d;
65         u8 val;
66         u8 ret;
67
68
69         d = (struct dvobj_priv *)p;
70         _halmac_mac_reg_page0_chk(__func__, d, offset);
71         ret = rtw_sdio_read_cmd52(d, offset, &val, 1);
72         if (_FAIL == ret) {
73                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
74                 return SDIO_ERR_VAL8;
75         }
76
77         return val;
78 }
79
80 static void _halmac_sdio_cmd52_write(void *p, u32 offset, u8 val)
81 {
82         struct dvobj_priv *d;
83         u8 ret;
84
85
86         d = (struct dvobj_priv *)p;
87         _halmac_mac_reg_page0_chk(__func__, d, offset);
88         ret = rtw_sdio_write_cmd52(d, offset, &val, 1);
89         if (_FAIL == ret)
90                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
91 }
92
93 static u8 _halmac_sdio_reg_read_8(void *p, u32 offset)
94 {
95         struct dvobj_priv *d;
96         u8 *pbuf;
97         u8 val;
98         int err;
99
100
101         d = (struct dvobj_priv *)p;
102         val = SDIO_ERR_VAL8;
103         _halmac_mac_reg_page0_chk(__func__, d, offset);
104         pbuf = rtw_zmalloc(1);
105         if (!pbuf)
106                 return val;
107
108         err = d->intf_ops->read(d, offset, pbuf, 1, 0);
109         if (err) {
110                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
111                 goto exit;
112         }
113
114         val = *pbuf;
115
116 exit:
117         rtw_mfree(pbuf, 1);
118
119         return val;
120 }
121
122 static u16 _halmac_sdio_reg_read_16(void *p, u32 offset)
123 {
124         struct dvobj_priv *d;
125         u8 *pbuf;
126         u16 val;
127         int err;
128
129
130         d = (struct dvobj_priv *)p;
131         val = SDIO_ERR_VAL16;
132         _halmac_mac_reg_page0_chk(__func__, d, offset);
133         pbuf = rtw_zmalloc(2);
134         if (!pbuf)
135                 return val;
136
137         err = d->intf_ops->read(d, offset, pbuf, 2, 0);
138         if (err) {
139                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
140                 goto exit;
141         }
142
143         val = le16_to_cpu(*(u16 *)pbuf);
144
145 exit:
146         rtw_mfree(pbuf, 2);
147
148         return val;
149 }
150
151 static u32 _halmac_sdio_reg_read_32(void *p, u32 offset)
152 {
153         struct dvobj_priv *d;
154         u8 *pbuf;
155         u32 val;
156         int err;
157
158
159         d = (struct dvobj_priv *)p;
160         val = SDIO_ERR_VAL32;
161         _halmac_mac_reg_page0_chk(__func__, d, offset);
162         pbuf = rtw_zmalloc(4);
163         if (!pbuf)
164                 return val;
165
166         err = d->intf_ops->read(d, offset, pbuf, 4, 0);
167         if (err) {
168                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
169                 goto exit;
170         }
171
172         val = le32_to_cpu(*(u32 *)pbuf);
173
174 exit:
175         rtw_mfree(pbuf, 4);
176
177         return val;
178 }
179
180 static u8 _halmac_sdio_reg_read_n(void *p, u32 offset, u32 size, u8 *data)
181 {
182         struct dvobj_priv *d = (struct dvobj_priv *)p;
183         PSDIO_DATA psdio = &d->intf_data;
184
185         u8 *pbuf;
186         int err;
187         u8 rst = _FALSE;
188         u32 sdio_read_size;
189
190         sdio_read_size = RND4(size);
191         if (sdio_read_size > psdio->block_transfer_len)
192                 sdio_read_size = _RND(sdio_read_size, psdio->block_transfer_len);
193
194         pbuf = rtw_zmalloc(sdio_read_size);
195         if ((!pbuf) || (!data))
196                 return rst;
197
198         err = d->intf_ops->read(d, offset, pbuf, sdio_read_size, 0);
199         if (err) {
200                 RTW_ERR("%s: [ERROR] I/O FAIL!\n", __func__);
201                 goto exit;
202         }
203
204         _rtw_memcpy(data, pbuf, size);
205         rst = _TRUE;
206 exit:
207         rtw_mfree(pbuf, sdio_read_size);
208
209         return rst;
210 }
211
212 static void _halmac_sdio_reg_write_8(void *p, u32 offset, u8 val)
213 {
214         struct dvobj_priv *d;
215         u8 *pbuf;
216         int err;
217
218
219         d = (struct dvobj_priv *)p;
220         _halmac_mac_reg_page0_chk(__func__, d, offset);
221         pbuf = rtw_zmalloc(1);
222         if (!pbuf)
223                 return;
224         _rtw_memcpy(pbuf, &val, 1);
225
226         err = d->intf_ops->write(d, offset, pbuf, 1, 0);
227         if (err)
228                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
229
230         rtw_mfree(pbuf, 1);
231 }
232
233 static void _halmac_sdio_reg_write_16(void *p, u32 offset, u16 val)
234 {
235         struct dvobj_priv *d;
236         u8 *pbuf;
237         int err;
238
239
240         d = (struct dvobj_priv *)p;
241         _halmac_mac_reg_page0_chk(__func__, d, offset);
242         val = cpu_to_le16(val);
243         pbuf = rtw_zmalloc(2);
244         if (!pbuf)
245                 return;
246         _rtw_memcpy(pbuf, &val, 2);
247
248         err = d->intf_ops->write(d, offset, pbuf, 2, 0);
249         if (err)
250                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
251
252         rtw_mfree(pbuf, 2);
253 }
254
255 static void _halmac_sdio_reg_write_32(void *p, u32 offset, u32 val)
256 {
257         struct dvobj_priv *d;
258         u8 *pbuf;
259         int err;
260
261
262         d = (struct dvobj_priv *)p;
263         _halmac_mac_reg_page0_chk(__func__, d, offset);
264         val = cpu_to_le32(val);
265         pbuf = rtw_zmalloc(4);
266         if (!pbuf)
267                 return;
268         _rtw_memcpy(pbuf, &val, 4);
269
270         err = d->intf_ops->write(d, offset, pbuf, 4, 0);
271         if (err)
272                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
273
274         rtw_mfree(pbuf, 4);
275 }
276
277 #else /* !CONFIG_SDIO_HCI */
278
279 static u8 _halmac_reg_read_8(void *p, u32 offset)
280 {
281         struct dvobj_priv *d;
282         PADAPTER adapter;
283
284
285         d = (struct dvobj_priv *)p;
286         adapter = dvobj_get_primary_adapter(d);
287
288         return rtw_read8(adapter, offset);
289 }
290
291 static u16 _halmac_reg_read_16(void *p, u32 offset)
292 {
293         struct dvobj_priv *d;
294         PADAPTER adapter;
295
296
297         d = (struct dvobj_priv *)p;
298         adapter = dvobj_get_primary_adapter(d);
299
300         return rtw_read16(adapter, offset);
301 }
302
303 static u32 _halmac_reg_read_32(void *p, u32 offset)
304 {
305         struct dvobj_priv *d;
306         PADAPTER adapter;
307
308
309         d = (struct dvobj_priv *)p;
310         adapter = dvobj_get_primary_adapter(d);
311
312         return rtw_read32(adapter, offset);
313 }
314
315 static void _halmac_reg_write_8(void *p, u32 offset, u8 val)
316 {
317         struct dvobj_priv *d;
318         PADAPTER adapter;
319         int err;
320
321
322         d = (struct dvobj_priv *)p;
323         adapter = dvobj_get_primary_adapter(d);
324
325         err = rtw_write8(adapter, offset, val);
326         if (err == _FAIL)
327                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
328 }
329
330 static void _halmac_reg_write_16(void *p, u32 offset, u16 val)
331 {
332         struct dvobj_priv *d;
333         PADAPTER adapter;
334         int err;
335
336
337         d = (struct dvobj_priv *)p;
338         adapter = dvobj_get_primary_adapter(d);
339
340         err = rtw_write16(adapter, offset, val);
341         if (err == _FAIL)
342                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
343 }
344
345 static void _halmac_reg_write_32(void *p, u32 offset, u32 val)
346 {
347         struct dvobj_priv *d;
348         PADAPTER adapter;
349         int err;
350
351
352         d = (struct dvobj_priv *)p;
353         adapter = dvobj_get_primary_adapter(d);
354
355         err = rtw_write32(adapter, offset, val);
356         if (err == _FAIL)
357                 RTW_INFO("%s: [ERROR] I/O FAIL!\n", __FUNCTION__);
358 }
359 #endif /* !CONFIG_SDIO_HCI */
360
361 static u8 _halmac_mfree(void *p, void *buffer, u32 size)
362 {
363         rtw_mfree(buffer, size);
364         return _TRUE;
365 }
366
367 static void *_halmac_malloc(void *p, u32 size)
368 {
369         return rtw_zmalloc(size);
370 }
371
372 static u8 _halmac_memcpy(void *p, void *dest, void *src, u32 size)
373 {
374         _rtw_memcpy(dest, src, size);
375         return _TRUE;
376 }
377
378 static u8 _halmac_memset(void *p, void *addr, u8 value, u32 size)
379 {
380         _rtw_memset(addr, value, size);
381         return _TRUE;
382 }
383
384 static void _halmac_udelay(void *p, u32 us)
385 {
386         rtw_udelay_os(us);
387 }
388
389 static u8 _halmac_mutex_init(void *p, HALMAC_MUTEX *pMutex)
390 {
391         _rtw_mutex_init(pMutex);
392         return _TRUE;
393 }
394
395 static u8 _halmac_mutex_deinit(void *p, HALMAC_MUTEX *pMutex)
396 {
397         _rtw_mutex_free(pMutex);
398         return _TRUE;
399 }
400
401 static u8 _halmac_mutex_lock(void *p, HALMAC_MUTEX *pMutex)
402 {
403         int err;
404
405         err = _enter_critical_mutex(pMutex, NULL);
406         if (err)
407                 return _FALSE;
408
409         return _TRUE;
410 }
411
412 static u8 _halmac_mutex_unlock(void *p, HALMAC_MUTEX *pMutex)
413 {
414         _exit_critical_mutex(pMutex, NULL);
415         return _TRUE;
416 }
417
418 static u8 _halmac_msg_print(void *p, u32 msg_type, u8 msg_level, s8 *fmt, ...)
419 {
420 #define MSG_LEN         100
421 #define MSG_PREFIX      "[HALMAC]"
422         va_list args;
423         u8 str[MSG_LEN] = {0};
424
425
426         str[0] = '\n';
427         va_start(args, fmt);
428         vsnprintf(str, MSG_LEN, fmt, args);
429         va_end(args);
430
431         if (msg_level <= HALMAC_DBG_ERR)
432                 RTW_ERR(MSG_PREFIX "%s", str);
433         else if (msg_level <= HALMAC_DBG_WARN)
434                 RTW_WARN(MSG_PREFIX "%s", str);
435         else
436                 RTW_DBG(MSG_PREFIX "%s", str);
437
438         return _TRUE;
439 }
440
441 static u8 _halmac_buff_print(void *p, u32 msg_type, u8 msg_level, s8 *buf, u32 size)
442 {
443 #define MSG_PREFIX      "[HALMAC]"
444
445         if (msg_level <= HALMAC_DBG_WARN)
446                 RTW_INFO_DUMP(MSG_PREFIX, buf, size);
447         else
448                 RTW_DBG_DUMP(MSG_PREFIX, buf, size);
449
450         return _TRUE;
451 }
452
453
454 const char *const RTW_HALMAC_FEATURE_NAME[] = {
455         "HALMAC_FEATURE_CFG_PARA",
456         "HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE",
457         "HALMAC_FEATURE_DUMP_LOGICAL_EFUSE",
458         "HALMAC_FEATURE_UPDATE_PACKET",
459         "HALMAC_FEATURE_UPDATE_DATAPACK",
460         "HALMAC_FEATURE_RUN_DATAPACK",
461         "HALMAC_FEATURE_CHANNEL_SWITCH",
462         "HALMAC_FEATURE_IQK",
463         "HALMAC_FEATURE_POWER_TRACKING",
464         "HALMAC_FEATURE_PSD",
465         "HALMAC_FEATURE_ALL"
466 };
467
468 static inline u8 is_valid_id_status(HALMAC_FEATURE_ID id, HALMAC_CMD_PROCESS_STATUS status)
469 {
470         switch (id) {
471         case HALMAC_FEATURE_CFG_PARA:
472                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
473                 break;
474         case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
475                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
476                 if (HALMAC_CMD_PROCESS_DONE != status)
477                         RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
478                                  __FUNCTION__, id, status);
479                 break;
480         case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
481                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
482                 if (HALMAC_CMD_PROCESS_DONE != status)
483                         RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
484                                  __FUNCTION__, id, status);
485                 break;
486         case HALMAC_FEATURE_UPDATE_PACKET:
487                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
488                 break;
489         case HALMAC_FEATURE_UPDATE_DATAPACK:
490                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
491                 break;
492         case HALMAC_FEATURE_RUN_DATAPACK:
493                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
494                 break;
495         case HALMAC_FEATURE_CHANNEL_SWITCH:
496                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
497                 break;
498         case HALMAC_FEATURE_IQK:
499                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
500                 break;
501         case HALMAC_FEATURE_POWER_TRACKING:
502                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
503                 break;
504         case HALMAC_FEATURE_PSD:
505                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
506                 break;
507         case HALMAC_FEATURE_ALL:
508                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
509                 break;
510         default:
511                 RTW_ERR("%s: unknown feature id(%d)\n", __FUNCTION__, id);
512                 return _FALSE;
513         }
514
515         return _TRUE;
516 }
517
518 static int init_halmac_event_with_waittime(struct dvobj_priv *d, HALMAC_FEATURE_ID id, u8 *buf, u32 size, u32 time)
519 {
520         struct submit_ctx *sctx;
521
522
523         if (!d->hmpriv.indicator[id].sctx) {
524                 sctx = (struct submit_ctx *)rtw_zmalloc(sizeof(*sctx));
525                 if (!sctx)
526                         return -1;
527         } else {
528                 RTW_WARN("%s: id(%d) sctx is not NULL!!\n", __FUNCTION__, id);
529                 sctx = d->hmpriv.indicator[id].sctx;
530                 d->hmpriv.indicator[id].sctx = NULL;
531         }
532
533         rtw_sctx_init(sctx, time);
534         d->hmpriv.indicator[id].buffer = buf;
535         d->hmpriv.indicator[id].buf_size = size;
536         d->hmpriv.indicator[id].ret_size = 0;
537         d->hmpriv.indicator[id].status = 0;
538         /* fill sctx at least to sure other variables are all ready! */
539         d->hmpriv.indicator[id].sctx = sctx;
540
541         return 0;
542 }
543
544 static inline int init_halmac_event(struct dvobj_priv *d, HALMAC_FEATURE_ID id, u8 *buf, u32 size)
545 {
546         return init_halmac_event_with_waittime(d, id, buf, size, DEFAULT_INDICATOR_TIMELMT);
547 }
548
549 static void free_halmac_event(struct dvobj_priv *d, HALMAC_FEATURE_ID id)
550 {
551         struct submit_ctx *sctx;
552
553
554         if (!d->hmpriv.indicator[id].sctx)
555                 return;
556
557         sctx = d->hmpriv.indicator[id].sctx;
558         d->hmpriv.indicator[id].sctx = NULL;
559         rtw_mfree((u8 *)sctx, sizeof(*sctx));
560 }
561
562 static int wait_halmac_event(struct dvobj_priv *d, HALMAC_FEATURE_ID id)
563 {
564         PHALMAC_ADAPTER mac;
565         PHALMAC_API api;
566         struct submit_ctx *sctx;
567         int ret;
568
569
570         sctx = d->hmpriv.indicator[id].sctx;
571         if (!sctx)
572                 return -1;
573
574         ret = rtw_sctx_wait(sctx, RTW_HALMAC_FEATURE_NAME[id]);
575         free_halmac_event(d, id);
576         if (_SUCCESS == ret)
577                 return 0;
578
579         /* timeout! We have to reset halmac state */
580         RTW_ERR("%s: Wait id(%d, %s) TIMEOUT! Reset HALMAC state!\n",
581                 __FUNCTION__, id, RTW_HALMAC_FEATURE_NAME[id]);
582         mac = dvobj_to_halmac(d);
583         api = HALMAC_GET_API(mac);
584         api->halmac_reset_feature(mac, id);
585
586         return -1;
587 }
588
589 /*
590  * Return:
591  *      Always return _TRUE, HALMAC don't care the return value.
592  */
593 static u8 _halmac_event_indication(void *p, HALMAC_FEATURE_ID feature_id, HALMAC_CMD_PROCESS_STATUS process_status, u8 *buf, u32 size)
594 {
595         struct dvobj_priv *d;
596         PADAPTER adapter;
597         PHAL_DATA_TYPE hal;
598         struct halmac_indicator *tbl, *indicator;
599         struct submit_ctx *sctx;
600         u32 cpsz;
601         u8 ret;
602
603
604         d = (struct dvobj_priv *)p;
605         adapter = dvobj_get_primary_adapter(d);
606         hal = GET_HAL_DATA(adapter);
607         tbl = d->hmpriv.indicator;
608
609         /* Filter(Skip) middle status indication */
610         ret = is_valid_id_status(feature_id, process_status);
611         if (_FALSE == ret)
612                 goto exit;
613
614         indicator = &tbl[feature_id];
615         indicator->status = process_status;
616         indicator->ret_size = size;
617         if (!indicator->sctx) {
618                 RTW_WARN("%s: No feature id(%d, %s) waiting!!\n", __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
619                 goto exit;
620         }
621         sctx = indicator->sctx;
622
623         if (HALMAC_CMD_PROCESS_ERROR == process_status) {
624                 RTW_ERR("%s: Something wrong id(%d, %s)!!\n", __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
625                 rtw_sctx_done_err(&sctx, RTW_SCTX_DONE_UNKNOWN);
626                 goto exit;
627         }
628
629         if (size > indicator->buf_size) {
630                 RTW_WARN("%s: id(%d, %s) buffer is not enough(%d<%d), data will be truncated!\n",
631                          __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id], indicator->buf_size, size);
632                 cpsz = indicator->buf_size;
633         } else {
634                 cpsz = size;
635         }
636         if (cpsz && indicator->buffer)
637                 _rtw_memcpy(indicator->buffer, buf, cpsz);
638
639         rtw_sctx_done(&sctx);
640
641 exit:
642         return _TRUE;
643 }
644
645 HALMAC_PLATFORM_API rtw_halmac_platform_api = {
646         /* R/W register */
647 #ifdef CONFIG_SDIO_HCI
648         .SDIO_CMD52_READ = _halmac_sdio_cmd52_read,
649         .SDIO_CMD53_READ_8 = _halmac_sdio_reg_read_8,
650         .SDIO_CMD53_READ_16 = _halmac_sdio_reg_read_16,
651         .SDIO_CMD53_READ_32 = _halmac_sdio_reg_read_32,
652         .SDIO_CMD53_READ_N = _halmac_sdio_reg_read_n,
653         .SDIO_CMD52_WRITE = _halmac_sdio_cmd52_write,
654         .SDIO_CMD53_WRITE_8 = _halmac_sdio_reg_write_8,
655         .SDIO_CMD53_WRITE_16 = _halmac_sdio_reg_write_16,
656         .SDIO_CMD53_WRITE_32 = _halmac_sdio_reg_write_32,
657
658 #endif /* CONFIG_SDIO_HCI */
659 #if defined(CONFIG_USB_HCI) || defined(CONFIG_PCIE_HCI)
660         .REG_READ_8 = _halmac_reg_read_8,
661         .REG_READ_16 = _halmac_reg_read_16,
662         .REG_READ_32 = _halmac_reg_read_32,
663         .REG_WRITE_8 = _halmac_reg_write_8,
664         .REG_WRITE_16 = _halmac_reg_write_16,
665         .REG_WRITE_32 = _halmac_reg_write_32,
666 #endif /* CONFIG_USB_HCI || CONFIG_PCIE_HCI */
667
668         /* Write data */
669 #if 0
670         /* impletement in HAL-IC level */
671         .SEND_RSVD_PAGE = sdio_write_data_rsvd_page,
672         .SEND_H2C_PKT = sdio_write_data_h2c,
673 #endif
674         /* Memory allocate */
675         .RTL_FREE = _halmac_mfree,
676         .RTL_MALLOC = _halmac_malloc,
677         .RTL_MEMCPY = _halmac_memcpy,
678         .RTL_MEMSET = _halmac_memset,
679
680         /* Sleep */
681         .RTL_DELAY_US = _halmac_udelay,
682
683         /* Process Synchronization */
684         .MUTEX_INIT = _halmac_mutex_init,
685         .MUTEX_DEINIT = _halmac_mutex_deinit,
686         .MUTEX_LOCK = _halmac_mutex_lock,
687         .MUTEX_UNLOCK = _halmac_mutex_unlock,
688
689         .MSG_PRINT = _halmac_msg_print,
690         .BUFF_PRINT = _halmac_buff_print,
691         .EVENT_INDICATION = _halmac_event_indication,
692 };
693
694 u8 rtw_halmac_read8(struct intf_hdl *pintfhdl, u32 addr)
695 {
696         PHALMAC_ADAPTER mac;
697         PHALMAC_API api;
698
699
700         /* WARNING: pintf_dev should not be null! */
701         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
702         api = HALMAC_GET_API(mac);
703
704         return api->halmac_reg_read_8(mac, addr);
705 }
706
707 u16 rtw_halmac_read16(struct intf_hdl *pintfhdl, u32 addr)
708 {
709         PHALMAC_ADAPTER mac;
710         PHALMAC_API api;
711
712
713         /* WARNING: pintf_dev should not be null! */
714         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
715         api = HALMAC_GET_API(mac);
716
717         return api->halmac_reg_read_16(mac, addr);
718 }
719
720 u32 rtw_halmac_read32(struct intf_hdl *pintfhdl, u32 addr)
721 {
722         PHALMAC_ADAPTER mac;
723         PHALMAC_API api;
724
725
726         /* WARNING: pintf_dev should not be null! */
727         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
728         api = HALMAC_GET_API(mac);
729
730         return api->halmac_reg_read_32(mac, addr);
731 }
732
733 void rtw_halmac_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem)
734 {
735 #if defined(CONFIG_SDIO_HCI)
736         PHALMAC_ADAPTER mac;
737         PHALMAC_API api;
738
739         if (pmem == NULL) {
740                 RTW_ERR("pmem is NULL\n");
741                 return;
742         }
743         /* WARNING: pintf_dev should not be null! */
744         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
745         api = HALMAC_GET_API(mac);
746
747         api->halmac_reg_sdio_cmd53_read_n(mac, addr, cnt, pmem);
748 #endif
749 }
750
751 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
752 u8 rtw_halmac_iread8(struct intf_hdl *pintfhdl, u32 addr)
753 {
754         PHALMAC_ADAPTER mac;
755         PHALMAC_API api;
756
757         /* WARNING: pintf_dev should not be null! */
758         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
759         api = HALMAC_GET_API(mac);
760
761         /*return api->halmac_reg_read_indirect_8(mac, addr);*/
762         return api->halmac_reg_read_8(mac, addr);
763 }
764
765 u16 rtw_halmac_iread16(struct intf_hdl *pintfhdl, u32 addr)
766 {
767         PHALMAC_ADAPTER mac;
768         PHALMAC_API api;
769         u16 val16 = 0;
770
771         /* WARNING: pintf_dev should not be null! */
772         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
773         api = HALMAC_GET_API(mac);
774
775         /*return api->halmac_reg_read_indirect_16(mac, addr);*/
776         return api->halmac_reg_read_16(mac, addr);
777 }
778
779 u32 rtw_halmac_iread32(struct intf_hdl *pintfhdl, u32 addr)
780 {
781         PHALMAC_ADAPTER mac;
782         PHALMAC_API api;
783
784
785         /* WARNING: pintf_dev should not be null! */
786         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
787         api = HALMAC_GET_API(mac);
788
789         return api->halmac_reg_read_indirect_32(mac, addr);
790 }
791 #endif
792
793 int rtw_halmac_write8(struct intf_hdl *pintfhdl, u32 addr, u8 value)
794 {
795         PHALMAC_ADAPTER mac;
796         PHALMAC_API api;
797         HALMAC_RET_STATUS status;
798
799
800         /* WARNING: pintf_dev should not be null! */
801         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
802         api = HALMAC_GET_API(mac);
803
804         status = api->halmac_reg_write_8(mac, addr, value);
805
806         if (status == HALMAC_RET_SUCCESS)
807                 return 0;
808
809         return -1;
810 }
811
812 int rtw_halmac_write16(struct intf_hdl *pintfhdl, u32 addr, u16 value)
813 {
814         PHALMAC_ADAPTER mac;
815         PHALMAC_API api;
816         HALMAC_RET_STATUS status;
817
818
819         /* WARNING: pintf_dev should not be null! */
820         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
821         api = HALMAC_GET_API(mac);
822
823         status = api->halmac_reg_write_16(mac, addr, value);
824
825         if (status == HALMAC_RET_SUCCESS)
826                 return 0;
827
828         return -1;
829 }
830
831 int rtw_halmac_write32(struct intf_hdl *pintfhdl, u32 addr, u32 value)
832 {
833         PHALMAC_ADAPTER mac;
834         PHALMAC_API api;
835         HALMAC_RET_STATUS status;
836
837
838         /* WARNING: pintf_dev should not be null! */
839         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
840         api = HALMAC_GET_API(mac);
841
842         status = api->halmac_reg_write_32(mac, addr, value);
843
844         if (status == HALMAC_RET_SUCCESS)
845                 return 0;
846
847         return -1;
848 }
849
850 static int init_priv(struct halmacpriv *priv)
851 {
852         struct halmac_indicator *indicator;
853         u32 count, size;
854
855
856         size = sizeof(*priv);
857         _rtw_memset(priv, 0, size);
858
859         count = HALMAC_FEATURE_ALL + 1;
860         size = sizeof(*indicator) * count;
861         indicator = (struct halmac_indicator *)rtw_zmalloc(size);
862         if (!indicator)
863                 return -1;
864         priv->indicator = indicator;
865
866         return 0;
867 }
868
869 static void deinit_priv(struct halmacpriv *priv)
870 {
871         struct halmac_indicator *indicator;
872
873
874         indicator = priv->indicator;
875         priv->indicator = NULL;
876         if (indicator) {
877                 u32 count, size;
878
879                 count = HALMAC_FEATURE_ALL + 1;
880 #ifdef CONFIG_RTW_DEBUG
881                 {
882                         struct submit_ctx *sctx;
883                         u32 i;
884
885                         for (i = 0; i < count; i++) {
886                                 if (!indicator[i].sctx)
887                                         continue;
888
889                                 RTW_INFO("%s: <WARN> %s id(%d) sctx still exist!!\n",
890                                         __FUNCTION__, RTW_HALMAC_FEATURE_NAME[i], i);
891                                 sctx = indicator[i].sctx;
892                                 indicator[i].sctx = NULL;
893                                 rtw_mfree((u8 *)sctx, sizeof(*sctx));
894                         }
895                 }
896 #endif /* !CONFIG_RTW_DEBUG */
897                 size = sizeof(*indicator) * count;
898                 rtw_mfree((u8 *)indicator, size);
899         }
900 }
901
902 void rtw_dump_halmac_info(void *sel)
903 {
904         HALMAC_RET_STATUS status;
905         HALMAC_VER halmac_version;
906
907         status = halmac_get_version(&halmac_version);
908         if (status != HALMAC_RET_SUCCESS)
909                 return;
910
911         RTW_PRINT_SEL(sel, "HALMAC VER -%x.%x.%x\n", halmac_version.major_ver, halmac_version.prototype_ver, halmac_version.minor_ver);
912 }
913
914 int rtw_halmac_init_adapter(struct dvobj_priv *d, PHALMAC_PLATFORM_API pf_api)
915 {
916         PHALMAC_ADAPTER halmac;
917         PHALMAC_API api;
918         HALMAC_INTERFACE intf;
919         HALMAC_RET_STATUS status;
920         int err = 0;
921
922
923         halmac = dvobj_to_halmac(d);
924         if (halmac) {
925                 err = 0;
926                 goto out;
927         }
928
929         err = init_priv(&d->hmpriv);
930         if (err)
931                 goto out;
932
933 #ifdef CONFIG_SDIO_HCI
934         intf = HALMAC_INTERFACE_SDIO;
935 #elif defined(CONFIG_USB_HCI)
936         intf = HALMAC_INTERFACE_USB;
937 #elif defined(CONFIG_PCIE_HCI)
938         intf = HALMAC_INTERFACE_PCIE;
939 #else
940 #warning "INTERFACE(CONFIG_XXX_HCI) not be defined!!"
941         intf = HALMAC_INTERFACE_UNDEFINE;
942 #endif
943         status = halmac_init_adapter(d, pf_api, intf, &halmac, &api);
944         if (HALMAC_RET_SUCCESS != status) {
945                 RTW_INFO("%s: halmac_init_adapter fail!(status=%d)\n", __FUNCTION__, status);
946                 err = -1;
947                 goto out;
948         }
949
950         dvobj_set_halmac(d, halmac);
951
952 out:
953         if (err)
954                 rtw_halmac_deinit_adapter(d);
955
956         return err;
957 }
958
959 int rtw_halmac_deinit_adapter(struct dvobj_priv *d)
960 {
961         PHALMAC_ADAPTER halmac;
962         HALMAC_RET_STATUS status;
963         int err = 0;
964
965
966         halmac = dvobj_to_halmac(d);
967         if (!halmac) {
968                 err = 0;
969                 goto out;
970         }
971
972         deinit_priv(&d->hmpriv);
973
974         status = halmac_deinit_adapter(halmac);
975         dvobj_set_halmac(d, NULL);
976         if (status != HALMAC_RET_SUCCESS) {
977                 err = -1;
978                 goto out;
979         }
980
981 out:
982         return err;
983 }
984
985 /*
986  * Description:
987  *      Power on device hardware.
988  *      [Notice!] If device's power state is on before,
989  *      it would be power off first and turn on power again.
990  *
991  * Return:
992  *      0       power on success
993  *      -1      power on fail
994  *      -2      power state unchange
995  */
996 int rtw_halmac_poweron(struct dvobj_priv *d)
997 {
998         PHALMAC_ADAPTER halmac;
999         PHALMAC_API api;
1000         HALMAC_RET_STATUS status;
1001         int err = -1;
1002
1003
1004         halmac = dvobj_to_halmac(d);
1005         if (!halmac)
1006                 goto out;
1007
1008         api = HALMAC_GET_API(halmac);
1009
1010         status = api->halmac_pre_init_system_cfg(halmac);
1011         if (status != HALMAC_RET_SUCCESS)
1012                 goto out;
1013
1014 #ifdef CONFIG_SDIO_HCI
1015         status = api->halmac_sdio_cmd53_4byte(halmac, 1);
1016         if (status != HALMAC_RET_SUCCESS)
1017                 goto out;
1018 #endif
1019
1020         status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_ON);
1021         if (HALMAC_RET_PWR_UNCHANGE == status) {
1022                 /*
1023                  * Work around for warm reboot but device not power off,
1024                  * but it would also fall into this case when auto power on is enabled.
1025                  */
1026                 api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_OFF);
1027                 status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_ON);
1028                 RTW_WARN("%s: Power state abnormal, try to recover...%s\n",
1029                          __FUNCTION__, (HALMAC_RET_SUCCESS == status)?"OK":"FAIL!");
1030         }
1031         if (HALMAC_RET_SUCCESS != status) {
1032                 if (HALMAC_RET_PWR_UNCHANGE == status)
1033                         err = -2;
1034                 goto out;
1035         }
1036
1037         status = api->halmac_init_system_cfg(halmac);
1038         if (status != HALMAC_RET_SUCCESS)
1039                 goto out;
1040
1041         err = 0;
1042 out:
1043         return err;
1044 }
1045
1046 /*
1047  * Description:
1048  *      Power off device hardware.
1049  *
1050  * Return:
1051  *      0       Power off success
1052  *      -1      Power off fail
1053  */
1054 int rtw_halmac_poweroff(struct dvobj_priv *d)
1055 {
1056         PHALMAC_ADAPTER halmac;
1057         PHALMAC_API api;
1058         HALMAC_RET_STATUS status;
1059         int err = -1;
1060
1061
1062         halmac = dvobj_to_halmac(d);
1063         if (!halmac)
1064                 goto out;
1065
1066         api = HALMAC_GET_API(halmac);
1067
1068         status = api->halmac_mac_power_switch(halmac, HALMAC_MAC_POWER_OFF);
1069         if ((HALMAC_RET_SUCCESS != status)
1070             && (HALMAC_RET_PWR_UNCHANGE != status))
1071                 goto out;
1072
1073         err = 0;
1074 out:
1075         return err;
1076 }
1077
1078 /*
1079  * Note:
1080  *      When this function return, the register REG_RCR may be changed.
1081  */
1082 int rtw_halmac_config_rx_info(struct dvobj_priv *d, HALMAC_DRV_INFO info)
1083 {
1084         PHALMAC_ADAPTER halmac;
1085         PHALMAC_API api;
1086         HALMAC_RET_STATUS status;
1087         int err = -1;
1088
1089
1090         halmac = dvobj_to_halmac(d);
1091         api = HALMAC_GET_API(halmac);
1092
1093         status = api->halmac_cfg_drv_info(halmac, info);
1094         if (status != HALMAC_RET_SUCCESS)
1095                 goto out;
1096
1097         err = 0;
1098 out:
1099         return err;
1100 }
1101
1102 #ifdef CONFIG_SUPPORT_TRX_SHARED
1103 static inline HALMAC_RX_FIFO_EXPANDING_MODE _trx_share_mode_drv2halmac(u8 trx_share_mode)
1104 {
1105         if (0 == trx_share_mode)
1106                 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
1107         else if (1 == trx_share_mode)
1108                 return HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK;
1109         else if (2 == trx_share_mode)
1110                 return HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK;
1111         else if (3 == trx_share_mode)
1112                 return HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK;
1113         else
1114                 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
1115 }
1116 static HALMAC_RX_FIFO_EXPANDING_MODE _rtw_get_trx_share_mode(_adapter *adapter)
1117 {
1118         struct registry_priv  *registry_par = &adapter->registrypriv;
1119
1120         return _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
1121 }
1122 void dump_trx_share_mode(void *sel, _adapter *adapter)
1123 {
1124         struct registry_priv  *registry_par = &adapter->registrypriv;
1125         u8 mode =  _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
1126
1127         if (HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK == mode)
1128                 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_1");
1129         else if (HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK == mode)
1130                 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_2");
1131         else if (HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK == mode)
1132                 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_3");
1133         else
1134                 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "DISABLE");
1135 }
1136 #endif
1137
1138 static u8 _get_drv_rsvd_page(HALMAC_DRV_RSVD_PG_NUM rsvd_page_number)
1139 {
1140         if (HALMAC_RSVD_PG_NUM16 == rsvd_page_number)
1141                 return 16;
1142         else if (HALMAC_RSVD_PG_NUM24 == rsvd_page_number)
1143                 return 24;
1144         else if (HALMAC_RSVD_PG_NUM32 == rsvd_page_number)
1145                 return 32;
1146
1147         RTW_ERR("%s unknown HALMAC_RSVD_PG type :%d\n", __func__, rsvd_page_number);
1148         rtw_warn_on(1);
1149         return 0;
1150 }
1151
1152 static HALMAC_TRX_MODE _choose_trx_mode(struct dvobj_priv *d)
1153 {
1154         PADAPTER p;
1155
1156
1157         p = dvobj_get_primary_adapter(d);
1158
1159         if (p->registrypriv.wifi_spec)
1160                 return HALMAC_TRX_MODE_WMM;
1161
1162 #ifdef CONFIG_SUPPORT_TRX_SHARED
1163         if (_rtw_get_trx_share_mode(p))
1164                 return HALMAC_TRX_MODE_TRXSHARE;
1165 #endif
1166
1167         return HALMAC_TRX_MODE_NORMAL;
1168 }
1169
1170 static inline HALMAC_RF_TYPE _rf_type_drv2halmac(RT_RF_TYPE_DEF_E rf_drv)
1171 {
1172         HALMAC_RF_TYPE rf_mac;
1173
1174
1175         switch (rf_drv) {
1176         case RF_1T2R:
1177                 rf_mac = HALMAC_RF_1T2R;
1178                 break;
1179         case RF_2T4R:
1180                 rf_mac = HALMAC_RF_2T4R;
1181                 break;
1182         case RF_2T2R:
1183                 rf_mac = HALMAC_RF_2T2R;
1184                 break;
1185         case RF_1T1R:
1186                 rf_mac = HALMAC_RF_1T1R;
1187                 break;
1188         case RF_2T2R_GREEN:
1189                 rf_mac = HALMAC_RF_2T2R_GREEN;
1190                 break;
1191         case RF_2T3R:
1192                 rf_mac = HALMAC_RF_2T3R;
1193                 break;
1194         case RF_3T3R:
1195                 rf_mac = HALMAC_RF_3T3R;
1196                 break;
1197         case RF_3T4R:
1198                 rf_mac = HALMAC_RF_3T4R;
1199                 break;
1200         case RF_4T4R:
1201                 rf_mac = HALMAC_RF_4T4R;
1202                 break;
1203         default:
1204                 rf_mac = (HALMAC_RF_TYPE)rf_drv;
1205                 break;
1206         }
1207
1208         return rf_mac;
1209 }
1210
1211 static int _send_general_info(struct dvobj_priv *d)
1212 {
1213         PADAPTER adapter;
1214         PHAL_DATA_TYPE hal;
1215         PHALMAC_ADAPTER halmac;
1216         PHALMAC_API api;
1217         HALMAC_GENERAL_INFO info;
1218         HALMAC_RET_STATUS status;
1219         u8 val8;
1220
1221
1222         adapter = dvobj_get_primary_adapter(d);
1223         hal = GET_HAL_DATA(adapter);
1224         halmac = dvobj_to_halmac(d);
1225         if (!halmac)
1226                 return -1;
1227         api = HALMAC_GET_API(halmac);
1228
1229         _rtw_memset(&info, 0, sizeof(info));
1230         info.rfe_type = (u8)hal->rfe_type;
1231         rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, &val8);
1232         info.rf_type = _rf_type_drv2halmac(val8);
1233
1234         status = api->halmac_send_general_info(halmac, &info);
1235         switch (status) {
1236         case HALMAC_RET_SUCCESS:
1237                 break;
1238         case HALMAC_RET_NO_DLFW:
1239                 RTW_WARN("%s: halmac_send_general_info() fail because fw not dl!\n",
1240                          __FUNCTION__);
1241                 /* go through */
1242         default:
1243                 return -1;
1244         }
1245
1246         return 0;
1247 }
1248
1249 /*
1250  * Description:
1251  *      Downlaod Firmware Flow
1252  *
1253  * Parameters:
1254  *      d       pointer of struct dvobj_priv
1255  *      fw      firmware array
1256  *      fwsize  firmware size
1257  *      re_dl   re-download firmware or not
1258  *              0: run in init hal flow, not re-download
1259  *              1: it is a stand alone operation, not in init hal flow
1260  *
1261  * Return:
1262  *      0       Success
1263  *      others  Fail
1264  */
1265 static int download_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize, u8 re_dl)
1266 {
1267         PHALMAC_ADAPTER mac;
1268         PHALMAC_API api;
1269         HALMAC_RET_STATUS status;
1270         int err = 0;
1271         PHAL_DATA_TYPE hal;
1272         HALMAC_FW_VERSION fw_vesion;
1273
1274
1275         mac = dvobj_to_halmac(d);
1276         api = HALMAC_GET_API(mac);
1277         hal = GET_HAL_DATA(dvobj_get_primary_adapter(d));
1278
1279         if ((!fw) || (!fwsize))
1280                 return -1;
1281
1282         /* 1. Driver Stop Tx */
1283         /* ToDo */
1284
1285         /* 2. Driver Check Tx FIFO is empty */
1286         /* ToDo */
1287
1288         /* 3. Config MAX download size */
1289 #ifdef CONFIG_USB_HCI
1290         /* for USB do not exceed MAX_CMDBUF_SZ */
1291         api->halmac_cfg_max_dl_size(mac, 0x1000);
1292 #elif defined CONFIG_PCIE_HCI
1293         /* required a even length from u32 */
1294         api->halmac_cfg_max_dl_size(mac, (MAX_CMDBUF_SZ - TXDESC_OFFSET) & 0xFFFFFFFE);
1295 #endif
1296
1297         /* 4. Download Firmware */
1298         status = api->halmac_download_firmware(mac, fw, fwsize);
1299         if (HALMAC_RET_SUCCESS != status)
1300                 return -1;
1301
1302         /* 5. Driver resume TX if needed */
1303         /* ToDo */
1304
1305         if (re_dl) {
1306                 HALMAC_TRX_MODE mode;
1307
1308                 /* 6. Init TRX Configuration */
1309                 mode = _choose_trx_mode(d);
1310                 status = api->halmac_init_trx_cfg(mac, mode);
1311                 if (HALMAC_RET_SUCCESS != status)
1312                         return -1;
1313
1314                 /* 7. Config RX Aggregation */
1315                 err = rtw_halmac_rx_agg_switch(d, _TRUE);
1316                 if (err)
1317                         return -1;
1318
1319                 /* 8. Send General Info */
1320                 err = _send_general_info(d);
1321                 if (err)
1322                         return -1;
1323         }
1324
1325         /* 9. Reset driver variables if needed */
1326         hal->LastHMEBoxNum = 0;
1327
1328         /* 10. Get FW version */
1329         status = api->halmac_get_fw_version(mac, &fw_vesion);
1330         if (status == HALMAC_RET_SUCCESS) {
1331                 hal->firmware_version = fw_vesion.version;
1332                 hal->firmware_sub_version = fw_vesion.sub_version;
1333         }
1334
1335         return err;
1336 }
1337
1338 static HALMAC_RET_STATUS init_mac_flow(struct dvobj_priv *d)
1339 {
1340         PADAPTER p;
1341         PHALMAC_ADAPTER halmac;
1342         PHALMAC_API api;
1343         HALMAC_WLAN_ADDR hwa;
1344         HALMAC_TRX_MODE trx_mode;
1345         HALMAC_RET_STATUS status;
1346         u8 nettype;
1347         int err;
1348         PHAL_DATA_TYPE hal;
1349         HALMAC_DRV_RSVD_PG_NUM rsvd_page_number = HALMAC_RSVD_PG_NUM16;/*HALMAC_RSVD_PG_NUM24/HALMAC_RSVD_PG_NUM32*/
1350
1351         p = dvobj_get_primary_adapter(d);
1352         hal = GET_HAL_DATA(p);
1353         halmac = dvobj_to_halmac(d);
1354         api = HALMAC_GET_API(halmac);
1355
1356 #ifdef CONFIG_SUPPORT_TRX_SHARED
1357         status = api->halmac_cfg_rx_fifo_expanding_mode(halmac, _rtw_get_trx_share_mode(p));
1358         if (status != HALMAC_RET_SUCCESS)
1359                 goto out;
1360 #endif
1361
1362 #ifdef CONFIG_PNO_SUPPORT
1363         rsvd_page_number = HALMAC_RSVD_PG_NUM32;
1364 #endif
1365         status = api->halmac_cfg_drv_rsvd_pg_num(halmac, rsvd_page_number);
1366         if (status != HALMAC_RET_SUCCESS)
1367                 goto out;
1368         hal->drv_rsvd_page_number = _get_drv_rsvd_page(rsvd_page_number);
1369
1370 #ifdef CONFIG_USB_HCI
1371         status = api->halmac_set_bulkout_num(halmac, d->RtNumOutPipes);
1372         if (status != HALMAC_RET_SUCCESS)
1373                 goto out;
1374 #endif /* CONFIG_USB_HCI */
1375
1376         trx_mode = _choose_trx_mode(d);
1377         status = api->halmac_init_mac_cfg(halmac, trx_mode);
1378         if (status != HALMAC_RET_SUCCESS)
1379                 goto out;
1380
1381         err = rtw_halmac_rx_agg_switch(d, _TRUE);
1382         if (err)
1383                 goto out;
1384
1385         nettype = dvobj_to_regsty(d)->wireless_mode;
1386         if (is_supported_vht(nettype) == _TRUE)
1387                 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_AC);
1388         else if (is_supported_ht(nettype) == _TRUE)
1389                 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_N);
1390         else if (IsSupportedTxOFDM(nettype) == _TRUE)
1391                 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_G);
1392         else
1393                 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_B);
1394         if (status != HALMAC_RET_SUCCESS)
1395                 goto out;
1396
1397 out:
1398         return status;
1399 }
1400
1401 /*
1402  * Notices:
1403  *      Make sure
1404  *      1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
1405  *      2. HAL_DATA_TYPE.rfe_type
1406  *      already ready for use before calling this function.
1407  */
1408 static int _halmac_init_hal(struct dvobj_priv *d, u8 *fw, u32 fwsize)
1409 {
1410         PADAPTER adapter;
1411         PHALMAC_ADAPTER halmac;
1412         PHALMAC_API api;
1413         HALMAC_RET_STATUS status;
1414         u32 ok = _TRUE;
1415         u8 fw_ok = _FALSE;
1416         int err, err_ret = -1;
1417
1418
1419         adapter = dvobj_get_primary_adapter(d);
1420         halmac = dvobj_to_halmac(d);
1421         if (!halmac)
1422                 goto out;
1423         api = HALMAC_GET_API(halmac);
1424
1425         /* StatePowerOff */
1426
1427         /* SKIP: halmac_init_adapter (Already done before) */
1428
1429         /* halmac_pre_Init_system_cfg */
1430         /* halmac_mac_power_switch(on) */
1431         /* halmac_Init_system_cfg */
1432         ok = rtw_hal_power_on(adapter);
1433         if (_FAIL == ok)
1434                 goto out;
1435
1436         /* StatePowerOn */
1437
1438         /* DownloadFW */
1439         if (fw && fwsize) {
1440                 err = download_fw(d, fw, fwsize, 0);
1441                 if (err)
1442                         goto out;
1443                 fw_ok = _TRUE;
1444         }
1445
1446         /* InitMACFlow */
1447         status = init_mac_flow(d);
1448         if (status != HALMAC_RET_SUCCESS)
1449                 goto out;
1450
1451         /* halmac_send_general_info */
1452         if (_TRUE == fw_ok) {
1453                 err = _send_general_info(d);
1454                 if (err)
1455                         goto out;
1456         }
1457
1458         /* Init Phy parameter-MAC */
1459         ok = rtw_hal_init_mac_register(adapter);
1460         if (_FALSE == ok)
1461                 goto out;
1462
1463         /* StateMacInitialized */
1464
1465         /* halmac_cfg_drv_info */
1466         err = rtw_halmac_config_rx_info(d, HALMAC_DRV_INFO_PHY_STATUS);
1467         if (err)
1468                 goto out;
1469
1470         /* halmac_set_hw_value(HALMAC_HW_EN_BB_RF) */
1471         /* Init BB, RF */
1472         ok = rtw_hal_init_phy(adapter);
1473         if (_FALSE == ok)
1474                 goto out;
1475
1476         status = api->halmac_init_interface_cfg(halmac);
1477         if (status != HALMAC_RET_SUCCESS)
1478                 goto out;
1479
1480         /* SKIP: halmac_verify_platform_api */
1481         /* SKIP: halmac_h2c_lb */
1482
1483         /* StateRxIdle */
1484
1485         err_ret = 0;
1486 out:
1487         return err_ret;
1488 }
1489
1490 int rtw_halmac_init_hal(struct dvobj_priv *d)
1491 {
1492         return _halmac_init_hal(d, NULL, 0);
1493 }
1494
1495 /*
1496  * Notices:
1497  *      Make sure
1498  *      1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
1499  *      2. HAL_DATA_TYPE.rfe_type
1500  *      already ready for use before calling this function.
1501  */
1502 int rtw_halmac_init_hal_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
1503 {
1504         return _halmac_init_hal(d, fw, fwsize);
1505 }
1506
1507 /*
1508  * Notices:
1509  *      Make sure
1510  *      1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
1511  *      2. HAL_DATA_TYPE.rfe_type
1512  *      already ready for use before calling this function.
1513  */
1514 int rtw_halmac_init_hal_fw_file(struct dvobj_priv *d, u8 *fwpath)
1515 {
1516         u8 *fw = NULL;
1517         u32 fwmaxsize, size = 0;
1518         int err = 0;
1519
1520
1521         fwmaxsize = FIRMWARE_MAX_SIZE;
1522         fw = rtw_zmalloc(fwmaxsize);
1523         if (!fw)
1524                 return -1;
1525
1526         size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
1527         if (!size) {
1528                 err = -1;
1529                 goto exit;
1530         }
1531
1532         err = _halmac_init_hal(d, fw, size);
1533
1534 exit:
1535         rtw_mfree(fw, fwmaxsize);
1536         fw = NULL;
1537
1538         return err;
1539 }
1540
1541 int rtw_halmac_deinit_hal(struct dvobj_priv *d)
1542 {
1543         PADAPTER adapter;
1544         PHALMAC_ADAPTER halmac;
1545         PHALMAC_API api;
1546         HALMAC_RET_STATUS status;
1547         int err = -1;
1548
1549
1550         adapter = dvobj_get_primary_adapter(d);
1551         halmac = dvobj_to_halmac(d);
1552         if (!halmac)
1553                 goto out;
1554         api = HALMAC_GET_API(halmac);
1555
1556         status = api->halmac_deinit_interface_cfg(halmac);
1557         if (status != HALMAC_RET_SUCCESS)
1558                 goto out;
1559
1560         rtw_hal_power_off(adapter);
1561
1562         err = 0;
1563 out:
1564         return err;
1565 }
1566
1567 int rtw_halmac_self_verify(struct dvobj_priv *d)
1568 {
1569         PHALMAC_ADAPTER mac;
1570         PHALMAC_API api;
1571         HALMAC_RET_STATUS status;
1572         int err = -1;
1573
1574
1575         mac = dvobj_to_halmac(d);
1576         api = HALMAC_GET_API(mac);
1577
1578         status = api->halmac_verify_platform_api(mac);
1579         if (status != HALMAC_RET_SUCCESS)
1580                 goto out;
1581
1582         status = api->halmac_h2c_lb(mac);
1583         if (status != HALMAC_RET_SUCCESS)
1584                 goto out;
1585
1586         err = 0;
1587 out:
1588         return err;
1589 }
1590
1591 int rtw_halmac_redl_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
1592 {
1593         int err = 0;
1594
1595         return err;
1596 }
1597
1598 /*
1599  * Return:
1600  *      0       Success
1601  *      -22     Invalid arguemnt
1602  */
1603 int rtw_halmac_dlfw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
1604 {
1605         PADAPTER adapter;
1606         HALMAC_RET_STATUS status;
1607         u32 ok = _TRUE;
1608         int err, err_ret = -1;
1609
1610
1611         if (!fw || !fwsize)
1612                 return -22;
1613
1614         adapter = dvobj_get_primary_adapter(d);
1615
1616         /* re-download firmware */
1617         if (rtw_is_hw_init_completed(adapter))
1618                 return download_fw(d, fw, fwsize, 1);
1619
1620         /* Download firmware before hal init */
1621         /* Power on, download firmware and init mac */
1622         ok = rtw_hal_power_on(adapter);
1623         if (_FAIL == ok)
1624                 goto out;
1625
1626         err = download_fw(d, fw, fwsize, 0);
1627         if (err) {
1628                 err_ret = err;
1629                 goto out;
1630         }
1631
1632         status = init_mac_flow(d);
1633         if (status != HALMAC_RET_SUCCESS)
1634                 goto out;
1635
1636         err = _send_general_info(d);
1637         if (err)
1638                 goto out;
1639
1640         err_ret = 0;
1641
1642 out:
1643         return err_ret;
1644 }
1645
1646 int rtw_halmac_dlfw_from_file(struct dvobj_priv *d, u8 *fwpath)
1647 {
1648         u8 *fw = NULL;
1649         u32 fwmaxsize, size = 0;
1650         int err = 0;
1651
1652
1653         fwmaxsize = FIRMWARE_MAX_SIZE;
1654         fw = rtw_zmalloc(fwmaxsize);
1655         if (!fw)
1656                 return -1;
1657
1658         size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
1659         if (size)
1660                 err = rtw_halmac_dlfw(d, fw, size);
1661         else
1662                 err = -1;
1663
1664         rtw_mfree(fw, fwmaxsize);
1665         fw = NULL;
1666
1667         return err;
1668 }
1669
1670 /*
1671  * Description:
1672  *      Power on/off BB/RF domain.
1673  *
1674  * Parameters:
1675  *      enable  _TRUE/_FALSE for power on/off
1676  *
1677  * Return:
1678  *      0       Success
1679  *      others  Fail
1680  */
1681 int rtw_halmac_phy_power_switch(struct dvobj_priv *d, u8 enable)
1682 {
1683         PADAPTER adapter;
1684         PHALMAC_ADAPTER halmac;
1685         PHALMAC_API api;
1686         HALMAC_RET_STATUS status;
1687
1688
1689         adapter = dvobj_get_primary_adapter(d);
1690         halmac = dvobj_to_halmac(d);
1691         if (!halmac)
1692                 return -1;
1693         api = HALMAC_GET_API(halmac);
1694
1695         status = api->halmac_set_hw_value(halmac, HALMAC_HW_EN_BB_RF, &enable);
1696         if (status != HALMAC_RET_SUCCESS)
1697                 return -1;
1698
1699         return 0;
1700 }
1701
1702 static u8 _is_fw_read_cmd_down(PADAPTER adapter, u8 msgbox_num)
1703 {
1704         u8 read_down = _FALSE;
1705         int retry_cnts = 100;
1706         u8 valid;
1707
1708         /* RTW_INFO("_is_fw_read_cmd_down, reg_1cc(%x), msg_box(%d)...\n", rtw_read8(adapter, REG_HMETFR), msgbox_num); */
1709
1710         do {
1711                 valid = rtw_read8(adapter, REG_HMETFR) & BIT(msgbox_num);
1712                 if (0 == valid)
1713                         read_down = _TRUE;
1714                 else
1715                         rtw_msleep_os(1);
1716         } while ((!read_down) && (retry_cnts--));
1717
1718         return read_down;
1719 }
1720
1721 int rtw_halmac_send_h2c(struct dvobj_priv *d, u8 *h2c)
1722 {
1723         PADAPTER adapter = dvobj_get_primary_adapter(d);
1724         PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
1725         u8 h2c_box_num = 0;
1726         u32 msgbox_addr = 0;
1727         u32 msgbox_ex_addr = 0;
1728         u32 h2c_cmd = 0;
1729         u32 h2c_cmd_ex = 0;
1730         s32 ret = _FAIL;
1731
1732         if (adapter->bFWReady == _FALSE) {
1733                 RTW_INFO("%s: return H2C cmd because fw is not ready\n", __FUNCTION__);
1734                 return ret;
1735         }
1736
1737         if (!h2c) {
1738                 RTW_INFO("%s: pbuf is NULL\n", __FUNCTION__);
1739                 return ret;
1740         }
1741
1742         if (rtw_is_surprise_removed(adapter)) {
1743                 RTW_INFO("%s: surprise removed\n", __FUNCTION__);
1744                 return ret;
1745         }
1746
1747         _enter_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
1748
1749         /* pay attention to if race condition happened in  H2C cmd setting */
1750         h2c_box_num = hal->LastHMEBoxNum;
1751
1752         if (!_is_fw_read_cmd_down(adapter, h2c_box_num)) {
1753                 RTW_INFO(" fw read cmd failed...\n");
1754                 goto exit;
1755         }
1756
1757         /* Write Ext command(byte 4 -7) */
1758         msgbox_ex_addr = REG_HMEBOX_E0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
1759         _rtw_memcpy((u8 *)(&h2c_cmd_ex), h2c + 4, EX_MESSAGE_BOX_SIZE);
1760         h2c_cmd_ex = le32_to_cpu(h2c_cmd_ex);
1761         rtw_write32(adapter, msgbox_ex_addr, h2c_cmd_ex);
1762
1763         /* Write command (byte 0 -3 ) */
1764         msgbox_addr = REG_HMEBOX0 + (h2c_box_num * MESSAGE_BOX_SIZE);
1765         _rtw_memcpy((u8 *)(&h2c_cmd), h2c, 4);
1766         h2c_cmd = le32_to_cpu(h2c_cmd);
1767         rtw_write32(adapter, msgbox_addr, h2c_cmd);
1768
1769         /* update last msg box number */
1770         hal->LastHMEBoxNum = (h2c_box_num + 1) % MAX_H2C_BOX_NUMS;
1771         ret = _SUCCESS;
1772
1773 #ifdef DBG_H2C_CONTENT
1774         RTW_INFO_DUMP("[H2C] - ", h2c, RTW_HALMAC_H2C_MAX_SIZE);
1775 #endif
1776 exit:
1777         _exit_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
1778         return ret;
1779 }
1780
1781 int rtw_halmac_c2h_handle(struct dvobj_priv *d, u8 *c2h, u32 size)
1782 {
1783         PHALMAC_ADAPTER mac;
1784         PHALMAC_API api;
1785         HALMAC_RET_STATUS status;
1786
1787
1788         mac = dvobj_to_halmac(d);
1789         api = HALMAC_GET_API(mac);
1790
1791         status = api->halmac_get_c2h_info(mac, c2h, size);
1792         if (HALMAC_RET_SUCCESS != status)
1793                 return -1;
1794
1795         return 0;
1796 }
1797
1798 int rtw_halmac_get_available_efuse_size(struct dvobj_priv *d, u32 *size)
1799 {
1800         PHALMAC_ADAPTER mac;
1801         PHALMAC_API api;
1802         HALMAC_RET_STATUS status;
1803         u32 val;
1804
1805
1806         mac = dvobj_to_halmac(d);
1807         api = HALMAC_GET_API(mac);
1808
1809         status = api->halmac_get_efuse_available_size(mac, &val);
1810         if (HALMAC_RET_SUCCESS != status)
1811                 return -1;
1812
1813         *size = val;
1814         return 0;
1815 }
1816
1817 int rtw_halmac_get_physical_efuse_size(struct dvobj_priv *d, u32 *size)
1818 {
1819         PHALMAC_ADAPTER mac;
1820         PHALMAC_API api;
1821         HALMAC_RET_STATUS status;
1822         u32 val;
1823
1824
1825         mac = dvobj_to_halmac(d);
1826         api = HALMAC_GET_API(mac);
1827
1828         status = api->halmac_get_efuse_size(mac, &val);
1829         if (HALMAC_RET_SUCCESS != status)
1830                 return -1;
1831
1832         *size = val;
1833         return 0;
1834 }
1835
1836 int rtw_halmac_read_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
1837 {
1838         PHALMAC_ADAPTER mac;
1839         PHALMAC_API api;
1840         HALMAC_RET_STATUS status;
1841         HALMAC_FEATURE_ID id;
1842         int ret;
1843
1844
1845         mac = dvobj_to_halmac(d);
1846         api = HALMAC_GET_API(mac);
1847         id = HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE;
1848
1849         ret = init_halmac_event(d, id, map, size);
1850         if (ret)
1851                 return -1;
1852
1853         status = api->halmac_dump_efuse_map(mac, HALMAC_EFUSE_R_AUTO);
1854         if (HALMAC_RET_SUCCESS != status) {
1855                 free_halmac_event(d, id);
1856                 return -1;
1857         }
1858
1859         ret = wait_halmac_event(d, id);
1860         if (ret)
1861                 return -1;
1862
1863         return 0;
1864 }
1865
1866 int rtw_halmac_read_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
1867 {
1868         PHALMAC_ADAPTER mac;
1869         PHALMAC_API api;
1870         HALMAC_RET_STATUS status;
1871         u8 v;
1872         u32 i;
1873
1874
1875         mac = dvobj_to_halmac(d);
1876         api = HALMAC_GET_API(mac);
1877
1878         for (i = 0; i < cnt; i++) {
1879                 status = api->halmac_read_efuse(mac, offset + i, &v);
1880                 if (HALMAC_RET_SUCCESS != status)
1881                         return -1;
1882                 data[i] = v;
1883         }
1884
1885         return 0;
1886 }
1887
1888 int rtw_halmac_write_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
1889 {
1890         PHALMAC_ADAPTER mac;
1891         PHALMAC_API api;
1892         HALMAC_RET_STATUS status;
1893         u32 i;
1894
1895
1896         mac = dvobj_to_halmac(d);
1897         api = HALMAC_GET_API(mac);
1898
1899         for (i = 0; i < cnt; i++) {
1900                 status = api->halmac_write_efuse(mac, offset + i, data[i]);
1901                 if (HALMAC_RET_SUCCESS != status)
1902                         return -1;
1903         }
1904
1905         return 0;
1906 }
1907
1908 int rtw_halmac_get_logical_efuse_size(struct dvobj_priv *d, u32 *size)
1909 {
1910         PHALMAC_ADAPTER mac;
1911         PHALMAC_API api;
1912         HALMAC_RET_STATUS status;
1913         u32 val;
1914
1915
1916         mac = dvobj_to_halmac(d);
1917         api = HALMAC_GET_API(mac);
1918
1919         status = api->halmac_get_logical_efuse_size(mac, &val);
1920         if (HALMAC_RET_SUCCESS != status)
1921                 return -1;
1922
1923         *size = val;
1924         return 0;
1925 }
1926
1927 int rtw_halmac_read_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
1928 {
1929         PHALMAC_ADAPTER mac;
1930         PHALMAC_API api;
1931         HALMAC_RET_STATUS status;
1932         HALMAC_FEATURE_ID id;
1933         int ret;
1934
1935
1936         mac = dvobj_to_halmac(d);
1937         api = HALMAC_GET_API(mac);
1938         id = HALMAC_FEATURE_DUMP_LOGICAL_EFUSE;
1939
1940         ret = init_halmac_event(d, id, map, size);
1941         if (ret)
1942                 return -1;
1943
1944         status = api->halmac_dump_logical_efuse_map(mac, HALMAC_EFUSE_R_DRV);
1945         if (HALMAC_RET_SUCCESS != status) {
1946                 free_halmac_event(d, id);
1947                 return -1;
1948         }
1949
1950         ret = wait_halmac_event(d, id);
1951         if (ret)
1952                 return -1;
1953
1954         return 0;
1955 }
1956
1957 int rtw_halmac_write_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size, u8 *maskmap, u32 masksize)
1958 {
1959         PHALMAC_ADAPTER mac;
1960         PHALMAC_API api;
1961         HALMAC_PG_EFUSE_INFO pginfo;
1962         HALMAC_RET_STATUS status;
1963
1964
1965         mac = dvobj_to_halmac(d);
1966         api = HALMAC_GET_API(mac);
1967
1968         pginfo.pEfuse_map = map;
1969         pginfo.efuse_map_size = size;
1970         pginfo.pEfuse_mask = maskmap;
1971         pginfo.efuse_mask_size = masksize;
1972
1973         status = api->halmac_pg_efuse_by_map(mac, &pginfo, HALMAC_EFUSE_R_AUTO);
1974         if (HALMAC_RET_SUCCESS != status)
1975                 return -1;
1976
1977         return 0;
1978 }
1979
1980 int rtw_halmac_read_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
1981 {
1982         PHALMAC_ADAPTER mac;
1983         PHALMAC_API api;
1984         HALMAC_RET_STATUS status;
1985         u8 v;
1986         u32 i;
1987
1988
1989         mac = dvobj_to_halmac(d);
1990         api = HALMAC_GET_API(mac);
1991
1992         for (i = 0; i < cnt; i++) {
1993                 status = api->halmac_read_logical_efuse(mac, offset + i, &v);
1994                 if (HALMAC_RET_SUCCESS != status)
1995                         return -1;
1996                 data[i] = v;
1997         }
1998
1999         return 0;
2000 }
2001
2002 int rtw_halmac_write_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
2003 {
2004         PHALMAC_ADAPTER mac;
2005         PHALMAC_API api;
2006         HALMAC_RET_STATUS status;
2007         u32 i;
2008
2009
2010         mac = dvobj_to_halmac(d);
2011         api = HALMAC_GET_API(mac);
2012
2013         for (i = 0; i < cnt; i++) {
2014                 status = api->halmac_write_logical_efuse(mac, offset + i, data[i]);
2015                 if (HALMAC_RET_SUCCESS != status)
2016                         return -1;
2017         }
2018
2019         return 0;
2020 }
2021
2022 int rtw_halmac_write_bt_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
2023 {
2024         PHALMAC_ADAPTER mac;
2025         PHALMAC_API api;
2026         HALMAC_RET_STATUS status;
2027         u32 i;
2028         u8 bank = 1;
2029
2030         mac = dvobj_to_halmac(d);
2031         api = HALMAC_GET_API(mac);
2032
2033         for (i = 0; i < cnt; i++) {
2034                 status = api->halmac_write_efuse_bt(mac, offset + i, data[i], bank);
2035                 if (HALMAC_RET_SUCCESS != status) {
2036                         printk("%s: halmac_write_efuse_bt status = %d\n", __FUNCTION__, status);
2037                         return -1;
2038                 }
2039         }
2040         printk("%s: halmac_write_efuse_bt status = HALMAC_RET_SUCCESS %d\n", __FUNCTION__, status);
2041         return 0;
2042 }
2043
2044
2045 int rtw_halmac_read_bt_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
2046 {
2047         PHALMAC_ADAPTER mac;
2048         PHALMAC_API api;
2049         HALMAC_RET_STATUS status;
2050         HALMAC_FEATURE_ID id;
2051         int ret;
2052         int bank = 1;
2053
2054         mac = dvobj_to_halmac(d);
2055         api = HALMAC_GET_API(mac);
2056
2057         status = api->halmac_dump_efuse_map_bt(mac, bank, size, map);
2058         if (HALMAC_RET_SUCCESS != status) {
2059                 printk("%s: halmac_dump_efuse_map_bt fail!\n", __FUNCTION__);
2060                 return -1;
2061         }
2062
2063         printk("%s: OK!\n", __FUNCTION__);
2064
2065         return 0;
2066 }
2067
2068 static inline u8 _hw_port_drv2halmac(enum _hw_port hwport)
2069 {
2070         u8 port = 0;
2071
2072
2073         switch (hwport) {
2074         case HW_PORT0:
2075                 port = 0;
2076                 break;
2077         case HW_PORT1:
2078                 port = 1;
2079                 break;
2080         case HW_PORT2:
2081                 port = 2;
2082                 break;
2083         case HW_PORT3:
2084                 port = 3;
2085                 break;
2086         case HW_PORT4:
2087                 port = 4;
2088                 break;
2089         default:
2090                 port = hwport;
2091                 break;
2092         }
2093
2094         return port;
2095 }
2096
2097 int rtw_halmac_set_mac_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2098 {
2099         PHALMAC_ADAPTER halmac;
2100         PHALMAC_API api;
2101         u8 port;
2102         HALMAC_WLAN_ADDR hwa;
2103         HALMAC_RET_STATUS status;
2104         int err = -1;
2105
2106
2107         halmac = dvobj_to_halmac(d);
2108         api = HALMAC_GET_API(halmac);
2109
2110         port = _hw_port_drv2halmac(hwport);
2111         _rtw_memset(&hwa, 0, sizeof(hwa));
2112         _rtw_memcpy(hwa.Address, addr, 6);
2113
2114         status = api->halmac_cfg_mac_addr(halmac, port, &hwa);
2115         if (status != HALMAC_RET_SUCCESS)
2116                 goto out;
2117
2118         err = 0;
2119 out:
2120         return err;
2121 }
2122
2123 int rtw_halmac_set_bssid(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2124 {
2125         PHALMAC_ADAPTER halmac;
2126         PHALMAC_API api;
2127         u8 port;
2128         HALMAC_WLAN_ADDR hwa;
2129         HALMAC_RET_STATUS status;
2130         int err = -1;
2131
2132         halmac = dvobj_to_halmac(d);
2133         api = HALMAC_GET_API(halmac);
2134         port = _hw_port_drv2halmac(hwport);
2135
2136         _rtw_memset(&hwa, 0, sizeof(HALMAC_WLAN_ADDR));
2137         _rtw_memcpy(hwa.Address, addr, 6);
2138         status = api->halmac_cfg_bssid(halmac, port, &hwa);
2139         if (status != HALMAC_RET_SUCCESS)
2140                 goto out;
2141
2142         err = 0;
2143 out:
2144         return err;
2145 }
2146
2147 int rtw_halmac_set_bandwidth(struct dvobj_priv *d, u8 channel, u8 pri_ch_idx, u8 bw)
2148 {
2149         PHALMAC_ADAPTER mac;
2150         PHALMAC_API api;
2151         HALMAC_RET_STATUS status;
2152
2153
2154         mac = dvobj_to_halmac(d);
2155         api = HALMAC_GET_API(mac);
2156
2157         status = api->halmac_cfg_ch_bw(mac, channel, pri_ch_idx, bw);
2158         if (HALMAC_RET_SUCCESS != status)
2159                 return -1;
2160
2161         return 0;
2162 }
2163
2164 int rtw_halmac_get_hw_value(struct dvobj_priv *d, HALMAC_HW_ID hw_id, VOID *pvalue)
2165 {
2166         PHALMAC_ADAPTER mac;
2167         PHALMAC_API api;
2168         HALMAC_RET_STATUS status;
2169
2170
2171         mac = dvobj_to_halmac(d);
2172         api = HALMAC_GET_API(mac);
2173
2174         status = api->halmac_get_hw_value(mac, hw_id, pvalue);
2175         if (HALMAC_RET_SUCCESS != status)
2176                 return -1;
2177
2178         return 0;
2179 }
2180
2181 static HAL_FIFO_SEL _fifo_sel_drv2halmac(u8 fifo_sel)
2182 {
2183         if (0 == fifo_sel)
2184                 return HAL_FIFO_SEL_TX;
2185         else if (1 == fifo_sel)
2186                 return HAL_FIFO_SEL_RX;
2187         else if (2 == fifo_sel)
2188                 return HAL_FIFO_SEL_RSVD_PAGE;
2189         else if (3 == fifo_sel)
2190                 return HAL_FIFO_SEL_REPORT;
2191         else if (4 == fifo_sel)
2192                 return HAL_FIFO_SEL_LLT;
2193         else
2194                 return HAL_FIFO_SEL_RSVD_PAGE;
2195 }
2196
2197 #define CONFIG_HALMAC_FIFO_DUMP
2198 int rtw_halmac_dump_fifo(struct dvobj_priv *d, u8 fifo_sel, u32 addr, u32 size, u8 *buffer)
2199 {
2200         PHALMAC_ADAPTER mac;
2201         PHALMAC_API api;
2202         HALMAC_RET_STATUS status;
2203         u8 *pfifo_map = NULL;
2204         u32 fifo_size = 0;
2205         s8 ret = 0;/* 0:success, -1:error */
2206         u8 mem_created = _FALSE;
2207
2208         HAL_FIFO_SEL halmac_fifo_sel;
2209
2210         mac = dvobj_to_halmac(d);
2211         api = HALMAC_GET_API(mac);
2212
2213         if ((size != 0) && (buffer == NULL))
2214                 return -1;
2215
2216         halmac_fifo_sel = _fifo_sel_drv2halmac(fifo_sel);
2217
2218         if ((size) && (buffer)) {
2219                 pfifo_map = buffer;
2220                 fifo_size = size;
2221         } else {
2222                 fifo_size = api->halmac_get_fifo_size(mac, halmac_fifo_sel);
2223
2224                 if (fifo_size)
2225                         pfifo_map = rtw_zvmalloc(fifo_size);
2226                 if (pfifo_map == NULL)
2227                         return -1;
2228                 mem_created = _TRUE;
2229         }
2230
2231         status = api->halmac_dump_fifo(mac, halmac_fifo_sel, addr, fifo_size, pfifo_map);
2232         if (HALMAC_RET_SUCCESS != status) {
2233                 ret = -1;
2234                 goto _exit;
2235         }
2236
2237 #ifdef CONFIG_HALMAC_FIFO_DUMP
2238         {
2239                 static const char * const fifo_sel_str[] = {
2240                         "TX", "RX", "RSVD_PAGE", "REPORT", "LLT"
2241                 };
2242
2243                 RTW_INFO("%s FIFO DUMP [start_addr:0x%04x , size:%d]\n", fifo_sel_str[halmac_fifo_sel], addr, fifo_size);
2244                 RTW_INFO_DUMP("\n", pfifo_map, fifo_size);
2245                 RTW_INFO(" ==================================================\n");
2246         }
2247 #endif
2248
2249 _exit:
2250         if (mem_created && pfifo_map)
2251                 rtw_vmfree(pfifo_map, fifo_size);
2252         return ret;
2253
2254 }
2255
2256 int rtw_halmac_rx_agg_switch(struct dvobj_priv *d, u8 enable)
2257 {
2258         PADAPTER adapter;
2259         PHAL_DATA_TYPE hal;
2260         PHALMAC_ADAPTER halmac;
2261         PHALMAC_API api;
2262         HALMAC_RXAGG_CFG rxaggcfg;
2263         HALMAC_RET_STATUS status;
2264         int err = -1;
2265
2266
2267         adapter = dvobj_get_primary_adapter(d);
2268         hal = GET_HAL_DATA(adapter);
2269         halmac = dvobj_to_halmac(d);
2270         api = HALMAC_GET_API(halmac);
2271         _rtw_memset((void *)&rxaggcfg, 0, sizeof(rxaggcfg));
2272
2273         if (_TRUE == enable) {
2274 #ifdef CONFIG_SDIO_HCI
2275                 rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
2276                 rxaggcfg.threshold.drv_define = 0;
2277 #elif defined(CONFIG_USB_HCI) && defined(CONFIG_USB_RX_AGGREGATION)
2278                 switch (hal->rxagg_mode) {
2279                 case RX_AGG_DISABLE:
2280                         rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
2281                         break;
2282
2283                 case RX_AGG_DMA:
2284                         rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
2285                         if (hal->rxagg_dma_size || hal->rxagg_dma_timeout) {
2286                                 rxaggcfg.threshold.drv_define = 1;
2287                                 rxaggcfg.threshold.timeout = hal->rxagg_dma_timeout;
2288                                 rxaggcfg.threshold.size = hal->rxagg_dma_size;
2289                         }
2290                         break;
2291
2292                 case RX_AGG_USB:
2293                 case RX_AGG_MIX:
2294                         rxaggcfg.mode = HALMAC_RX_AGG_MODE_USB;
2295                         if (hal->rxagg_usb_size || hal->rxagg_usb_timeout) {
2296                                 rxaggcfg.threshold.drv_define = 1;
2297                                 rxaggcfg.threshold.timeout = hal->rxagg_usb_timeout;
2298                                 rxaggcfg.threshold.size = hal->rxagg_usb_size;
2299                         }
2300                         break;
2301                 }
2302 #endif /* CONFIG_USB_HCI */
2303         } else
2304                 rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
2305
2306         status = api->halmac_cfg_rx_aggregation(halmac, &rxaggcfg);
2307         if (status != HALMAC_RET_SUCCESS)
2308                 goto out;
2309
2310         err = 0;
2311 out:
2312         return err;
2313 }
2314
2315 /*
2316  * Description:
2317  *      Get RX driver info size. RX driver info is a small memory space between
2318  *      scriptor and RX payload.
2319  *
2320  *      +-------------------------+
2321  *      | RX descriptor           |
2322  *      | usually 24 bytes        |
2323  *      +-------------------------+
2324  *      | RX driver info          |
2325  *      | depends on driver cfg   |
2326  *      +-------------------------+
2327  *      | RX paylad               |
2328  *      |                         |
2329  *      +-------------------------+
2330  *
2331  * Parameter:
2332  *      d       pointer to struct dvobj_priv of driver
2333  *      sz      rx driver info size in bytes.
2334  *
2335  * Rteurn:
2336  *      0       Success
2337  *      other   Fail
2338  */
2339 int rtw_halmac_get_drv_info_sz(struct dvobj_priv *d, u8 *sz)
2340 {
2341         HALMAC_RET_STATUS status;
2342         PHALMAC_ADAPTER halmac = dvobj_to_halmac(d);
2343         PHALMAC_API api = HALMAC_GET_API(halmac);
2344         u8 dw = 0;
2345
2346         status = api->halmac_get_hw_value(halmac, HALMAC_HW_DRV_INFO_SIZE, &dw);
2347         if (status != HALMAC_RET_SUCCESS)
2348                 return -1;
2349
2350         *sz = dw * 8;
2351         return 0;
2352 }
2353 int rtw_halmac_get_rsvd_drv_pg_bndy(struct dvobj_priv *dvobj, u16 *drv_pg)
2354 {
2355         HALMAC_RET_STATUS status;
2356         PHALMAC_ADAPTER halmac = dvobj_to_halmac(dvobj);
2357         PHALMAC_API api = HALMAC_GET_API(halmac);
2358
2359         status = api->halmac_get_hw_value(halmac, HALMAC_HW_RSVD_PG_BNDY, drv_pg);
2360         if (status != HALMAC_RET_SUCCESS)
2361                 return -1;
2362
2363         return 0;
2364 }
2365
2366 int rtw_halmac_download_rsvd_page(struct dvobj_priv *dvobj, u8 pg_offset, u8 *pbuf, u32 size)
2367 {
2368         HALMAC_RET_STATUS status = HALMAC_RET_SUCCESS;
2369         PHALMAC_ADAPTER halmac = dvobj_to_halmac(dvobj);
2370         PHALMAC_API api = HALMAC_GET_API(halmac);
2371
2372         status = api->halmac_dl_drv_rsvd_page(halmac, pg_offset, pbuf, size);
2373         if (status != HALMAC_RET_SUCCESS)
2374                 return -1;
2375
2376         return 0;
2377
2378 }
2379
2380 /*
2381  * Description
2382  *      Fill following spec info from HALMAC API:
2383  *      sec_cam_ent_num
2384  *
2385  * Return
2386  *      0       Success
2387  *      others  Fail
2388  */
2389 int rtw_halmac_fill_hal_spec(struct dvobj_priv *dvobj, struct hal_spec_t *spec)
2390 {
2391         HALMAC_RET_STATUS status;
2392         PHALMAC_ADAPTER halmac;
2393         PHALMAC_API api;
2394         u8 cam = 0;     /* Security Cam Entry Number */
2395
2396
2397         halmac = dvobj_to_halmac(dvobj);
2398         api = HALMAC_GET_API(halmac);
2399
2400         /* Prepare data from HALMAC */
2401         status = api->halmac_get_hw_value(halmac, HALMAC_HW_CAM_ENTRY_NUM, &cam);
2402         if (status != HALMAC_RET_SUCCESS)
2403                 return -1;
2404
2405         /* Fill data to hal_spec_t */
2406         spec->sec_cam_ent_num = cam;
2407
2408         return 0;
2409 }
2410
2411 #ifdef CONFIG_SDIO_HCI
2412
2413 /*
2414  * Description:
2415  *      Update queue allocated page number to driver
2416  *
2417  * Parameter:
2418  *      d       pointer to struct dvobj_priv of driver
2419  *
2420  * Rteurn:
2421  *      0       Success, "page" is valid.
2422  *      others  Fail, "page" is invalid.
2423  */
2424 int rtw_halmac_query_tx_page_num(struct dvobj_priv *d)
2425 {
2426         PADAPTER adapter;
2427         struct halmacpriv *hmpriv;
2428         PHALMAC_ADAPTER halmac;
2429         PHALMAC_API api;
2430         HALMAC_RQPN_MAP rqpn;
2431         HALMAC_DMA_MAPPING dmaqueue;
2432         HALMAC_TXFF_ALLOCATION fifosize;
2433         HALMAC_RET_STATUS status;
2434         u8 i;
2435
2436
2437         adapter = dvobj_get_primary_adapter(d);
2438         hmpriv = &d->hmpriv;
2439         halmac = dvobj_to_halmac(d);
2440         api = HALMAC_GET_API(halmac);
2441         _rtw_memset((void *)&rqpn, 0, sizeof(rqpn));
2442         _rtw_memset((void *)&fifosize, 0, sizeof(fifosize));
2443
2444         status = api->halmac_get_hw_value(halmac, HALMAC_HW_RQPN_MAPPING, &rqpn);
2445         if (status != HALMAC_RET_SUCCESS)
2446                 return -1;
2447         status = api->halmac_get_hw_value(halmac, HALMAC_HW_TXFF_ALLOCATION, &fifosize);
2448         if (status != HALMAC_RET_SUCCESS)
2449                 return -1;
2450
2451         for (i = 0; i < HW_QUEUE_ENTRY; i++) {
2452                 hmpriv->txpage[i] = 0;
2453
2454                 /* Driver index mapping to HALMAC DMA queue */
2455                 dmaqueue = HALMAC_DMA_MAPPING_UNDEFINE;
2456                 switch (i) {
2457                 case VO_QUEUE_INX:
2458                         dmaqueue = rqpn.dma_map_vo;
2459                         break;
2460                 case VI_QUEUE_INX:
2461                         dmaqueue = rqpn.dma_map_vi;
2462                         break;
2463                 case BE_QUEUE_INX:
2464                         dmaqueue = rqpn.dma_map_be;
2465                         break;
2466                 case BK_QUEUE_INX:
2467                         dmaqueue = rqpn.dma_map_bk;
2468                         break;
2469                 case MGT_QUEUE_INX:
2470                         dmaqueue = rqpn.dma_map_mg;
2471                         break;
2472                 case HIGH_QUEUE_INX:
2473                         dmaqueue = rqpn.dma_map_hi;
2474                         break;
2475                 case BCN_QUEUE_INX:
2476                 case TXCMD_QUEUE_INX:
2477                         /* Unlimited */
2478                         hmpriv->txpage[i] = 0xFFFF;
2479                         continue;
2480                 }
2481
2482                 switch (dmaqueue) {
2483                 case HALMAC_DMA_MAPPING_EXTRA:
2484                         hmpriv->txpage[i] = fifosize.extra_queue_pg_num;
2485                         break;
2486                 case HALMAC_DMA_MAPPING_LOW:
2487                         hmpriv->txpage[i] = fifosize.low_queue_pg_num;
2488                         break;
2489                 case HALMAC_DMA_MAPPING_NORMAL:
2490                         hmpriv->txpage[i] = fifosize.normal_queue_pg_num;
2491                         break;
2492                 case HALMAC_DMA_MAPPING_HIGH:
2493                         hmpriv->txpage[i] = fifosize.high_queue_pg_num;
2494                         break;
2495                 case HALMAC_DMA_MAPPING_UNDEFINE:
2496                         break;
2497                 }
2498                 hmpriv->txpage[i] += fifosize.pub_queue_pg_num;
2499         }
2500
2501         return 0;
2502 }
2503
2504 /*
2505  * Description:
2506  *      Get specific queue allocated page number
2507  *
2508  * Parameter:
2509  *      d       pointer to struct dvobj_priv of driver
2510  *      queue   target queue to query, VO/VI/BE/BK/.../TXCMD_QUEUE_INX
2511  *      page    return allocated page number
2512  *
2513  * Rteurn:
2514  *      0       Success, "page" is valid.
2515  *      others  Fail, "page" is invalid.
2516  */
2517 int rtw_halmac_get_tx_queue_page_num(struct dvobj_priv *d, u8 queue, u32 *page)
2518 {
2519         *page = 0;
2520         if (queue < HW_QUEUE_ENTRY)
2521                 *page = d->hmpriv.txpage[queue];
2522
2523         return 0;
2524 }
2525
2526 /*
2527  * Return:
2528  *      address for SDIO command
2529  */
2530 u32 rtw_halmac_sdio_get_tx_addr(struct dvobj_priv *d, u8 *desc, u32 size)
2531 {
2532         PHALMAC_ADAPTER mac;
2533         PHALMAC_API api;
2534         HALMAC_RET_STATUS status;
2535         u32 addr;
2536
2537
2538         mac = dvobj_to_halmac(d);
2539         api = HALMAC_GET_API(mac);
2540
2541         status = api->halmac_get_sdio_tx_addr(mac, desc, size, &addr);
2542         if (HALMAC_RET_SUCCESS != status)
2543                 return 0;
2544
2545         return addr;
2546 }
2547
2548 int rtw_halmac_sdio_tx_allowed(struct dvobj_priv *d, u8 *buf, u32 size)
2549 {
2550         PHALMAC_ADAPTER mac;
2551         PHALMAC_API api;
2552         HALMAC_RET_STATUS status;
2553
2554
2555         mac = dvobj_to_halmac(d);
2556         api = HALMAC_GET_API(mac);
2557
2558         status = api->halmac_tx_allowed_sdio(mac, buf, size);
2559         if (HALMAC_RET_SUCCESS != status)
2560                 return -1;
2561
2562         return 0;
2563 }
2564
2565 u32 rtw_halmac_sdio_get_rx_addr(struct dvobj_priv *d, u8 *seq)
2566 {
2567         u8 id;
2568
2569 #define RTW_SDIO_ADDR_RX_RX0FF_PRFIX    0x0E000
2570 #define RTW_SDIO_ADDR_RX_RX0FF_GEN(a)   (RTW_SDIO_ADDR_RX_RX0FF_PRFIX|(a&0x3))
2571
2572         id = *seq;
2573         (*seq)++;
2574         return RTW_SDIO_ADDR_RX_RX0FF_GEN(id);
2575 }
2576 #endif /* CONFIG_SDIO_HCI */
2577
2578 #ifdef CONFIG_USB_HCI
2579 u8 rtw_halmac_usb_get_bulkout_id(struct dvobj_priv *d, u8 *buf, u32 size)
2580 {
2581         PHALMAC_ADAPTER mac;
2582         PHALMAC_API api;
2583         HALMAC_RET_STATUS status;
2584         u8 bulkout_id;
2585
2586
2587         mac = dvobj_to_halmac(d);
2588         api = HALMAC_GET_API(mac);
2589
2590         status = api->halmac_get_usb_bulkout_id(mac, buf, size, &bulkout_id);
2591         if (HALMAC_RET_SUCCESS != status)
2592                 return 0;
2593
2594         return bulkout_id;
2595 }
2596
2597 static inline HALMAC_USB_MODE _usb_mode_drv2halmac(enum RTW_USB_SPEED usb_mode)
2598 {
2599         HALMAC_USB_MODE halmac_usb_mode = HALMAC_USB_MODE_U2;
2600
2601         switch (usb_mode) {
2602         case RTW_USB_SPEED_2:
2603                 halmac_usb_mode = HALMAC_USB_MODE_U2;
2604                 break;
2605         case RTW_USB_SPEED_3:
2606                 halmac_usb_mode = HALMAC_USB_MODE_U3;
2607                 break;
2608         default:
2609                 halmac_usb_mode = HALMAC_USB_MODE_U2;
2610                 break;
2611         }
2612
2613         return halmac_usb_mode;
2614 }
2615
2616 u8 rtw_halmac_switch_usb_mode(struct dvobj_priv *d, enum RTW_USB_SPEED usb_mode)
2617 {
2618         PHALMAC_ADAPTER mac;
2619         PHALMAC_API api;
2620         HALMAC_RET_STATUS status;
2621         PADAPTER adapter;
2622         HALMAC_USB_MODE halmac_usb_mode;
2623
2624         adapter = dvobj_get_primary_adapter(d);
2625         mac = dvobj_to_halmac(d);
2626         api = HALMAC_GET_API(mac);
2627         halmac_usb_mode = _usb_mode_drv2halmac(usb_mode);
2628         status = api->halmac_set_hw_value(mac, HALMAC_HW_USB_MODE, (void *)&halmac_usb_mode);
2629
2630         if (HALMAC_RET_SUCCESS != status)
2631                 return _FAIL;
2632
2633         return _SUCCESS;
2634 }
2635 #endif /* CONFIG_USB_HCI */