OSDN Git Service

Add rtl8821ce driver version 5.5.2
[android-x86/external-kernel-drivers.git] / rtl8821ce / hal / hal_halmac.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2015 - 2018 Realtek Corporation.
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  *****************************************************************************/
15 #define _HAL_HALMAC_C_
16
17 #include <drv_types.h>          /* PADAPTER, struct dvobj_priv, SDIO_ERR_VAL8 and etc. */
18 #include <hal_data.h>           /* efuse, PHAL_DATA_TYPE and etc. */
19 #include "hal_halmac.h"         /* dvobj_to_halmac() and ect. */
20
21 /*
22  * HALMAC take return value 0 for fail and 1 for success to replace
23  * _FALSE/_TRUE after V1_04_09
24  */
25 #define RTW_HALMAC_FAIL                 0
26 #define RTW_HALMAC_SUCCESS              1
27
28 #define DEFAULT_INDICATOR_TIMELMT       1000    /* ms */
29 #define MSG_PREFIX                      "[HALMAC]"
30
31 #define RTW_HALMAC_DLFW_MEM_NO_STOP_TX
32
33 /*
34  * Driver API for HALMAC operations
35  */
36
37 #ifdef CONFIG_SDIO_HCI
38 #include <rtw_sdio.h>
39
40 static u8 _halmac_mac_reg_page0_chk(const char *func, struct dvobj_priv *dvobj, u32 offset)
41 {
42 #if defined(CONFIG_IO_CHECK_IN_ANA_LOW_CLK) && defined(CONFIG_LPS_LCLK)
43         struct pwrctrl_priv *pwrpriv = &dvobj->pwrctl_priv;
44         u32 mac_reg_offset = 0;
45
46         if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
47                 return _TRUE;
48
49         if (pwrpriv->lps_level == LPS_NORMAL)
50                 return _TRUE;
51
52         if (pwrpriv->rpwm >= PS_STATE_S2)
53                 return _TRUE;
54
55         if (offset & (WLAN_IOREG_DEVICE_ID << 13))  { /*WLAN_IOREG_OFFSET*/
56                 mac_reg_offset = offset & HALMAC_WLAN_MAC_REG_MSK;
57                 if (mac_reg_offset < 0x100) {
58                         RTW_ERR(FUNC_ADPT_FMT
59                                 "access MAC REG -0x%04x in PS-mode:0x%02x (rpwm:0x%02x, lps_level:0x%02x)\n",
60                                 FUNC_ADPT_ARG(dvobj_get_primary_adapter(dvobj)), mac_reg_offset,
61                                 pwrpriv->pwr_mode, pwrpriv->rpwm, pwrpriv->lps_level);
62                         rtw_warn_on(1);
63                         return _FALSE;
64                 }
65         }
66 #endif
67         return _TRUE;
68 }
69
70 static u8 _halmac_sdio_cmd52_read(void *p, u32 offset)
71 {
72         struct dvobj_priv *d;
73         u8 val;
74         u8 ret;
75
76
77         d = (struct dvobj_priv *)p;
78         _halmac_mac_reg_page0_chk(__func__, d, offset);
79         ret = rtw_sdio_read_cmd52(d, offset, &val, 1);
80         if (_FAIL == ret) {
81                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
82                 return SDIO_ERR_VAL8;
83         }
84
85         return val;
86 }
87
88 static void _halmac_sdio_cmd52_write(void *p, u32 offset, u8 val)
89 {
90         struct dvobj_priv *d;
91         u8 ret;
92
93
94         d = (struct dvobj_priv *)p;
95         _halmac_mac_reg_page0_chk(__func__, d, offset);
96         ret = rtw_sdio_write_cmd52(d, offset, &val, 1);
97         if (_FAIL == ret)
98                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
99 }
100
101 static u8 _halmac_sdio_reg_read_8(void *p, u32 offset)
102 {
103         struct dvobj_priv *d;
104         u8 *pbuf;
105         u8 val;
106         u8 ret;
107
108
109         d = (struct dvobj_priv *)p;
110         val = SDIO_ERR_VAL8;
111         _halmac_mac_reg_page0_chk(__func__, d, offset);
112         pbuf = rtw_zmalloc(1);
113         if (!pbuf)
114                 return val;
115
116         ret = rtw_sdio_read_cmd53(d, offset, pbuf, 1);
117         if (ret == _FAIL) {
118                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
119                 goto exit;
120         }
121
122         val = *pbuf;
123
124 exit:
125         rtw_mfree(pbuf, 1);
126
127         return val;
128 }
129
130 static u16 _halmac_sdio_reg_read_16(void *p, u32 offset)
131 {
132         struct dvobj_priv *d;
133         u8 *pbuf;
134         u16 val;
135         u8 ret;
136
137
138         d = (struct dvobj_priv *)p;
139         val = SDIO_ERR_VAL16;
140         _halmac_mac_reg_page0_chk(__func__, d, offset);
141         pbuf = rtw_zmalloc(2);
142         if (!pbuf)
143                 return val;
144
145         ret = rtw_sdio_read_cmd53(d, offset, pbuf, 2);
146         if (ret == _FAIL) {
147                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
148                 goto exit;
149         }
150
151         val = le16_to_cpu(*(u16 *)pbuf);
152
153 exit:
154         rtw_mfree(pbuf, 2);
155
156         return val;
157 }
158
159 static u32 _halmac_sdio_reg_read_32(void *p, u32 offset)
160 {
161         struct dvobj_priv *d;
162         u8 *pbuf;
163         u32 val;
164         u8 ret;
165
166
167         d = (struct dvobj_priv *)p;
168         val = SDIO_ERR_VAL32;
169         _halmac_mac_reg_page0_chk(__func__, d, offset);
170         pbuf = rtw_zmalloc(4);
171         if (!pbuf)
172                 return val;
173
174         ret = rtw_sdio_read_cmd53(d, offset, pbuf, 4);
175         if (ret == _FAIL) {
176                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
177                 goto exit;
178         }
179
180         val = le32_to_cpu(*(u32 *)pbuf);
181
182 exit:
183         rtw_mfree(pbuf, 4);
184
185         return val;
186 }
187
188 static u8 _halmac_sdio_reg_read_n(void *p, u32 offset, u32 size, u8 *data)
189 {
190         struct dvobj_priv *d = (struct dvobj_priv *)p;
191         u8 *pbuf;
192         u8 ret;
193         u8 rst = RTW_HALMAC_FAIL;
194         u32 sdio_read_size;
195
196
197         sdio_read_size = RND4(size);
198         sdio_read_size = rtw_sdio_cmd53_align_size(d, sdio_read_size);
199
200         pbuf = rtw_zmalloc(sdio_read_size);
201         if ((!pbuf) || (!data))
202                 return rst;
203
204         ret = rtw_sdio_read_cmd53(d, offset, pbuf, sdio_read_size);
205         if (ret == _FAIL) {
206                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
207                 goto exit;
208         }
209
210         _rtw_memcpy(data, pbuf, size);
211         rst = RTW_HALMAC_SUCCESS;
212 exit:
213         rtw_mfree(pbuf, sdio_read_size);
214
215         return rst;
216 }
217
218 static void _halmac_sdio_reg_write_8(void *p, u32 offset, u8 val)
219 {
220         struct dvobj_priv *d;
221         u8 *pbuf;
222         u8 ret;
223
224
225         d = (struct dvobj_priv *)p;
226         _halmac_mac_reg_page0_chk(__func__, d, offset);
227         pbuf = rtw_zmalloc(1);
228         if (!pbuf)
229                 return;
230         _rtw_memcpy(pbuf, &val, 1);
231
232         ret = rtw_sdio_write_cmd53(d, offset, pbuf, 1);
233         if (ret == _FAIL)
234                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
235
236         rtw_mfree(pbuf, 1);
237 }
238
239 static void _halmac_sdio_reg_write_16(void *p, u32 offset, u16 val)
240 {
241         struct dvobj_priv *d;
242         u8 *pbuf;
243         u8 ret;
244
245
246         d = (struct dvobj_priv *)p;
247         _halmac_mac_reg_page0_chk(__func__, d, offset);
248         val = cpu_to_le16(val);
249         pbuf = rtw_zmalloc(2);
250         if (!pbuf)
251                 return;
252         _rtw_memcpy(pbuf, &val, 2);
253
254         ret = rtw_sdio_write_cmd53(d, offset, pbuf, 2);
255         if (ret == _FAIL)
256                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
257
258         rtw_mfree(pbuf, 2);
259 }
260
261 static void _halmac_sdio_reg_write_32(void *p, u32 offset, u32 val)
262 {
263         struct dvobj_priv *d;
264         u8 *pbuf;
265         u8 ret;
266
267
268         d = (struct dvobj_priv *)p;
269         _halmac_mac_reg_page0_chk(__func__, d, offset);
270         val = cpu_to_le32(val);
271         pbuf = rtw_zmalloc(4);
272         if (!pbuf)
273                 return;
274         _rtw_memcpy(pbuf, &val, 4);
275
276         ret = rtw_sdio_write_cmd53(d, offset, pbuf, 4);
277         if (ret == _FAIL)
278                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
279
280         rtw_mfree(pbuf, 4);
281 }
282
283 static u8 _halmac_sdio_read_cia(void *p, u32 offset)
284 {
285         struct dvobj_priv *d;
286         u8 data = 0;
287         u8 ret;
288
289
290         d = (struct dvobj_priv *)p;
291
292         ret = rtw_sdio_f0_read(d, offset, &data, 1);
293         if (ret == _FAIL)
294                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
295
296         return data;
297 }
298
299 #else /* !CONFIG_SDIO_HCI */
300
301 static u8 _halmac_reg_read_8(void *p, u32 offset)
302 {
303         struct dvobj_priv *d;
304         PADAPTER adapter;
305
306
307         d = (struct dvobj_priv *)p;
308         adapter = dvobj_get_primary_adapter(d);
309
310         return rtw_read8(adapter, offset);
311 }
312
313 static u16 _halmac_reg_read_16(void *p, u32 offset)
314 {
315         struct dvobj_priv *d;
316         PADAPTER adapter;
317
318
319         d = (struct dvobj_priv *)p;
320         adapter = dvobj_get_primary_adapter(d);
321
322         return rtw_read16(adapter, offset);
323 }
324
325 static u32 _halmac_reg_read_32(void *p, u32 offset)
326 {
327         struct dvobj_priv *d;
328         PADAPTER adapter;
329
330
331         d = (struct dvobj_priv *)p;
332         adapter = dvobj_get_primary_adapter(d);
333
334         return rtw_read32(adapter, offset);
335 }
336
337 static void _halmac_reg_write_8(void *p, u32 offset, u8 val)
338 {
339         struct dvobj_priv *d;
340         PADAPTER adapter;
341         int err;
342
343
344         d = (struct dvobj_priv *)p;
345         adapter = dvobj_get_primary_adapter(d);
346
347         err = rtw_write8(adapter, offset, val);
348         if (err == _FAIL)
349                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
350 }
351
352 static void _halmac_reg_write_16(void *p, u32 offset, u16 val)
353 {
354         struct dvobj_priv *d;
355         PADAPTER adapter;
356         int err;
357
358
359         d = (struct dvobj_priv *)p;
360         adapter = dvobj_get_primary_adapter(d);
361
362         err = rtw_write16(adapter, offset, val);
363         if (err == _FAIL)
364                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
365 }
366
367 static void _halmac_reg_write_32(void *p, u32 offset, u32 val)
368 {
369         struct dvobj_priv *d;
370         PADAPTER adapter;
371         int err;
372
373
374         d = (struct dvobj_priv *)p;
375         adapter = dvobj_get_primary_adapter(d);
376
377         err = rtw_write32(adapter, offset, val);
378         if (err == _FAIL)
379                 RTW_ERR("%s: I/O FAIL!\n", __FUNCTION__);
380 }
381 #endif /* !CONFIG_SDIO_HCI */
382
383 static u8 _halmac_mfree(void *p, void *buffer, u32 size)
384 {
385         rtw_mfree(buffer, size);
386         return RTW_HALMAC_SUCCESS;
387 }
388
389 static void *_halmac_malloc(void *p, u32 size)
390 {
391         return rtw_zmalloc(size);
392 }
393
394 static u8 _halmac_memcpy(void *p, void *dest, void *src, u32 size)
395 {
396         _rtw_memcpy(dest, src, size);
397         return RTW_HALMAC_SUCCESS;
398 }
399
400 static u8 _halmac_memset(void *p, void *addr, u8 value, u32 size)
401 {
402         _rtw_memset(addr, value, size);
403         return RTW_HALMAC_SUCCESS;
404 }
405
406 static void _halmac_udelay(void *p, u32 us)
407 {
408         /* Most hardware polling wait time < 50us) */
409         if (us <= 50)
410                 rtw_udelay_os(us);
411         else if (us <= 1000)
412                 rtw_usleep_os(us);
413         else
414                 rtw_msleep_os(RTW_DIV_ROUND_UP(us, 1000));
415 }
416
417 static u8 _halmac_mutex_init(void *p, HALMAC_MUTEX *pMutex)
418 {
419         _rtw_mutex_init(pMutex);
420         return RTW_HALMAC_SUCCESS;
421 }
422
423 static u8 _halmac_mutex_deinit(void *p, HALMAC_MUTEX *pMutex)
424 {
425         _rtw_mutex_free(pMutex);
426         return RTW_HALMAC_SUCCESS;
427 }
428
429 static u8 _halmac_mutex_lock(void *p, HALMAC_MUTEX *pMutex)
430 {
431         int err;
432
433         err = _enter_critical_mutex(pMutex, NULL);
434         if (err)
435                 return RTW_HALMAC_FAIL;
436
437         return RTW_HALMAC_SUCCESS;
438 }
439
440 static u8 _halmac_mutex_unlock(void *p, HALMAC_MUTEX *pMutex)
441 {
442         _exit_critical_mutex(pMutex, NULL);
443         return RTW_HALMAC_SUCCESS;
444 }
445
446 static u8 _halmac_msg_print(void *p, u32 msg_type, u8 msg_level, s8 *fmt, ...)
447 {
448 #define MSG_LEN         100
449         va_list args;
450         u8 str[MSG_LEN] = {0};
451         int err;
452         u8 ret = RTW_HALMAC_SUCCESS;
453
454
455         str[0] = '\n';
456         va_start(args, fmt);
457         err = vsnprintf(str, MSG_LEN, fmt, args);
458         va_end(args);
459
460         /* An output error is encountered */
461         if (err < 0)
462                 return RTW_HALMAC_FAIL;
463         /* Output may be truncated due to size limit */
464         if ((err == (MSG_LEN - 1)) && (str[MSG_LEN - 2] != '\n'))
465                 ret = RTW_HALMAC_FAIL;
466
467         if (msg_level == HALMAC_DBG_ALWAYS)
468                 RTW_PRINT(MSG_PREFIX "%s", str);
469         else if (msg_level <= HALMAC_DBG_ERR)
470                 RTW_ERR(MSG_PREFIX "%s", str);
471         else if (msg_level <= HALMAC_DBG_WARN)
472                 RTW_WARN(MSG_PREFIX "%s", str);
473         else
474                 RTW_DBG(MSG_PREFIX "%s", str);
475
476         return ret;
477 }
478
479 static u8 _halmac_buff_print(void *p, u32 msg_type, u8 msg_level, s8 *buf, u32 size)
480 {
481         if (msg_level <= HALMAC_DBG_WARN)
482                 RTW_INFO_DUMP(MSG_PREFIX, buf, size);
483         else
484                 RTW_DBG_DUMP(MSG_PREFIX, buf, size);
485
486         return RTW_HALMAC_SUCCESS;
487 }
488
489
490 const char *const RTW_HALMAC_FEATURE_NAME[] = {
491         "HALMAC_FEATURE_CFG_PARA",
492         "HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE",
493         "HALMAC_FEATURE_DUMP_LOGICAL_EFUSE",
494         "HALMAC_FEATURE_UPDATE_PACKET",
495         "HALMAC_FEATURE_UPDATE_DATAPACK",
496         "HALMAC_FEATURE_RUN_DATAPACK",
497         "HALMAC_FEATURE_CHANNEL_SWITCH",
498         "HALMAC_FEATURE_IQK",
499         "HALMAC_FEATURE_POWER_TRACKING",
500         "HALMAC_FEATURE_PSD",
501         "HALMAC_FEATURE_FW_SNDING",
502         "HALMAC_FEATURE_ALL"
503 };
504
505 static inline u8 is_valid_id_status(enum halmac_feature_id id, enum halmac_cmd_process_status status)
506 {
507         switch (id) {
508         case HALMAC_FEATURE_CFG_PARA:
509                 RTW_DBG("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
510                 break;
511         case HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE:
512                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
513                 if (HALMAC_CMD_PROCESS_DONE != status)
514                         RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
515                                  __FUNCTION__, id, status);
516                 break;
517         case HALMAC_FEATURE_DUMP_LOGICAL_EFUSE:
518                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
519                 if (HALMAC_CMD_PROCESS_DONE != status)
520                         RTW_INFO("%s: id(%d) unspecified status(%d)!\n",
521                                  __FUNCTION__, id, status);
522                 break;
523         case HALMAC_FEATURE_UPDATE_PACKET:
524                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
525                 break;
526         case HALMAC_FEATURE_UPDATE_DATAPACK:
527                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
528                 break;
529         case HALMAC_FEATURE_RUN_DATAPACK:
530                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
531                 break;
532         case HALMAC_FEATURE_CHANNEL_SWITCH:
533                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
534                 break;
535         case HALMAC_FEATURE_IQK:
536                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
537                 break;
538         case HALMAC_FEATURE_POWER_TRACKING:
539                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
540                 break;
541         case HALMAC_FEATURE_PSD:
542                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
543                 break;
544         case HALMAC_FEATURE_FW_SNDING:
545                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
546                 break;
547         case HALMAC_FEATURE_ALL:
548                 RTW_INFO("%s: %s\n", __FUNCTION__, RTW_HALMAC_FEATURE_NAME[id]);
549                 break;
550         default:
551                 RTW_ERR("%s: unknown feature id(%d)\n", __FUNCTION__, id);
552                 return _FALSE;
553         }
554
555         return _TRUE;
556 }
557
558 static int init_halmac_event_with_waittime(struct dvobj_priv *d, enum halmac_feature_id id, u8 *buf, u32 size, u32 time)
559 {
560         struct submit_ctx *sctx;
561
562
563         if (!d->hmpriv.indicator[id].sctx) {
564                 sctx = (struct submit_ctx *)rtw_zmalloc(sizeof(*sctx));
565                 if (!sctx)
566                         return -1;
567         } else {
568                 RTW_WARN("%s: id(%d) sctx is not NULL!!\n", __FUNCTION__, id);
569                 sctx = d->hmpriv.indicator[id].sctx;
570                 d->hmpriv.indicator[id].sctx = NULL;
571         }
572
573         rtw_sctx_init(sctx, time);
574         d->hmpriv.indicator[id].buffer = buf;
575         d->hmpriv.indicator[id].buf_size = size;
576         d->hmpriv.indicator[id].ret_size = 0;
577         d->hmpriv.indicator[id].status = 0;
578         /* fill sctx at least to sure other variables are all ready! */
579         d->hmpriv.indicator[id].sctx = sctx;
580
581         return 0;
582 }
583
584 static inline int init_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id, u8 *buf, u32 size)
585 {
586         return init_halmac_event_with_waittime(d, id, buf, size, DEFAULT_INDICATOR_TIMELMT);
587 }
588
589 static void free_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id)
590 {
591         struct submit_ctx *sctx;
592
593
594         if (!d->hmpriv.indicator[id].sctx)
595                 return;
596
597         sctx = d->hmpriv.indicator[id].sctx;
598         d->hmpriv.indicator[id].sctx = NULL;
599         rtw_mfree((u8 *)sctx, sizeof(*sctx));
600 }
601
602 static int wait_halmac_event(struct dvobj_priv *d, enum halmac_feature_id id)
603 {
604         struct halmac_adapter *mac;
605         struct halmac_api *api;
606         struct submit_ctx *sctx;
607         int ret;
608
609
610         sctx = d->hmpriv.indicator[id].sctx;
611         if (!sctx)
612                 return -1;
613
614         ret = rtw_sctx_wait(sctx, RTW_HALMAC_FEATURE_NAME[id]);
615         free_halmac_event(d, id);
616         if (_SUCCESS == ret)
617                 return 0;
618
619         /* timeout! We have to reset halmac state */
620         RTW_ERR("%s: Wait id(%d, %s) TIMEOUT! Reset HALMAC state!\n",
621                 __FUNCTION__, id, RTW_HALMAC_FEATURE_NAME[id]);
622         mac = dvobj_to_halmac(d);
623         api = HALMAC_GET_API(mac);
624         api->halmac_reset_feature(mac, id);
625
626         return -1;
627 }
628
629 /*
630  * Return:
631  *      Always return RTW_HALMAC_SUCCESS, HALMAC don't care the return value.
632  */
633 static u8 _halmac_event_indication(void *p, enum halmac_feature_id feature_id, enum halmac_cmd_process_status process_status, u8 *buf, u32 size)
634 {
635         struct dvobj_priv *d;
636         PADAPTER adapter;
637         PHAL_DATA_TYPE hal;
638         struct halmac_indicator *tbl, *indicator;
639         struct submit_ctx *sctx;
640         u32 cpsz;
641         u8 ret;
642
643
644         d = (struct dvobj_priv *)p;
645         adapter = dvobj_get_primary_adapter(d);
646         hal = GET_HAL_DATA(adapter);
647         tbl = d->hmpriv.indicator;
648
649         /* Filter(Skip) middle status indication */
650         ret = is_valid_id_status(feature_id, process_status);
651         if (_FALSE == ret)
652                 goto exit;
653
654         indicator = &tbl[feature_id];
655         indicator->status = process_status;
656         indicator->ret_size = size;
657         if (!indicator->sctx) {
658                 RTW_WARN("%s: No feature id(%d, %s) waiting!!\n", __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
659                 goto exit;
660         }
661         sctx = indicator->sctx;
662
663         if (HALMAC_CMD_PROCESS_ERROR == process_status) {
664                 RTW_ERR("%s: Something wrong id(%d, %s)!!\n", __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id]);
665                 rtw_sctx_done_err(&sctx, RTW_SCTX_DONE_UNKNOWN);
666                 goto exit;
667         }
668
669         if (size > indicator->buf_size) {
670                 RTW_WARN("%s: id(%d, %s) buffer is not enough(%d<%d), data will be truncated!\n",
671                          __FUNCTION__, feature_id, RTW_HALMAC_FEATURE_NAME[feature_id], indicator->buf_size, size);
672                 cpsz = indicator->buf_size;
673         } else {
674                 cpsz = size;
675         }
676         if (cpsz && indicator->buffer)
677                 _rtw_memcpy(indicator->buffer, buf, cpsz);
678
679         rtw_sctx_done(&sctx);
680
681 exit:
682         return RTW_HALMAC_SUCCESS;
683 }
684
685 struct halmac_platform_api rtw_halmac_platform_api = {
686         /* R/W register */
687 #ifdef CONFIG_SDIO_HCI
688         .SDIO_CMD52_READ = _halmac_sdio_cmd52_read,
689         .SDIO_CMD53_READ_8 = _halmac_sdio_reg_read_8,
690         .SDIO_CMD53_READ_16 = _halmac_sdio_reg_read_16,
691         .SDIO_CMD53_READ_32 = _halmac_sdio_reg_read_32,
692         .SDIO_CMD53_READ_N = _halmac_sdio_reg_read_n,
693         .SDIO_CMD52_WRITE = _halmac_sdio_cmd52_write,
694         .SDIO_CMD53_WRITE_8 = _halmac_sdio_reg_write_8,
695         .SDIO_CMD53_WRITE_16 = _halmac_sdio_reg_write_16,
696         .SDIO_CMD53_WRITE_32 = _halmac_sdio_reg_write_32,
697         .SDIO_CMD52_CIA_READ = _halmac_sdio_read_cia,
698 #endif /* CONFIG_SDIO_HCI */
699 #if defined(CONFIG_USB_HCI) || defined(CONFIG_PCI_HCI)
700         .REG_READ_8 = _halmac_reg_read_8,
701         .REG_READ_16 = _halmac_reg_read_16,
702         .REG_READ_32 = _halmac_reg_read_32,
703         .REG_WRITE_8 = _halmac_reg_write_8,
704         .REG_WRITE_16 = _halmac_reg_write_16,
705         .REG_WRITE_32 = _halmac_reg_write_32,
706 #endif /* CONFIG_USB_HCI || CONFIG_PCI_HCI */
707
708         /* Write data */
709 #if 0
710         /* impletement in HAL-IC level */
711         .SEND_RSVD_PAGE = sdio_write_data_rsvd_page,
712         .SEND_H2C_PKT = sdio_write_data_h2c,
713 #endif
714         /* Memory allocate */
715         .RTL_FREE = _halmac_mfree,
716         .RTL_MALLOC = _halmac_malloc,
717         .RTL_MEMCPY = _halmac_memcpy,
718         .RTL_MEMSET = _halmac_memset,
719
720         /* Sleep */
721         .RTL_DELAY_US = _halmac_udelay,
722
723         /* Process Synchronization */
724         .MUTEX_INIT = _halmac_mutex_init,
725         .MUTEX_DEINIT = _halmac_mutex_deinit,
726         .MUTEX_LOCK = _halmac_mutex_lock,
727         .MUTEX_UNLOCK = _halmac_mutex_unlock,
728
729         .MSG_PRINT = _halmac_msg_print,
730         .BUFF_PRINT = _halmac_buff_print,
731         .EVENT_INDICATION = _halmac_event_indication,
732 };
733
734 u8 rtw_halmac_read8(struct intf_hdl *pintfhdl, u32 addr)
735 {
736         struct halmac_adapter *mac;
737         struct halmac_api *api;
738
739
740         /* WARNING: pintf_dev should not be null! */
741         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
742         api = HALMAC_GET_API(mac);
743
744         return api->halmac_reg_read_8(mac, addr);
745 }
746
747 u16 rtw_halmac_read16(struct intf_hdl *pintfhdl, u32 addr)
748 {
749         struct halmac_adapter *mac;
750         struct halmac_api *api;
751
752
753         /* WARNING: pintf_dev should not be null! */
754         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
755         api = HALMAC_GET_API(mac);
756
757         return api->halmac_reg_read_16(mac, addr);
758 }
759
760 u32 rtw_halmac_read32(struct intf_hdl *pintfhdl, u32 addr)
761 {
762         struct halmac_adapter *mac;
763         struct halmac_api *api;
764
765
766         /* WARNING: pintf_dev should not be null! */
767         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
768         api = HALMAC_GET_API(mac);
769
770         return api->halmac_reg_read_32(mac, addr);
771 }
772
773 static void _read_register(struct dvobj_priv *d, u32 addr, u32 cnt, u8 *buf)
774 {
775 #if 1
776         struct _ADAPTER *a;
777         u32 i, n;
778         u16 val16;
779         u32 val32;
780
781
782         a = dvobj_get_primary_adapter(d);
783
784         i = addr & 0x3;
785         /* Handle address not start from 4 bytes alignment case */
786         if (i) {
787                 val32 = cpu_to_le32(rtw_read32(a, addr & ~0x3));
788                 n = 4 - i;
789                 _rtw_memcpy(buf, ((u8 *)&val32) + i, n);
790                 i = n;
791                 cnt -= n;
792         }
793
794         while (cnt) {
795                 if (cnt >= 4)
796                         n = 4;
797                 else if (cnt >= 2)
798                         n = 2;
799                 else
800                         n = 1;
801                 cnt -= n;
802
803                 switch (n) {
804                 case 1:
805                         buf[i] = rtw_read8(a, addr+i);
806                         i++;
807                         break;
808                 case 2:
809                         val16 = cpu_to_le16(rtw_read16(a, addr+i));
810                         _rtw_memcpy(&buf[i], &val16, 2);
811                         i += 2;
812                         break;
813                 case 4:
814                         val32 = cpu_to_le32(rtw_read32(a, addr+i));
815                         _rtw_memcpy(&buf[i], &val32, 4);
816                         i += 4;
817                         break;
818                 }
819         }
820 #else
821         struct _ADAPTER *a;
822         u32 i;
823
824
825         a = dvobj_get_primary_adapter(d);
826         for (i = 0; i < cnt; i++)
827                 buf[i] = rtw_read8(a, addr + i);
828 #endif
829 }
830
831 #ifdef CONFIG_SDIO_HCI
832 static int _sdio_read_local(struct dvobj_priv *d, u32 addr, u32 cnt, u8 *buf)
833 {
834         struct halmac_adapter *mac;
835         struct halmac_api *api;
836         enum halmac_ret_status status;
837
838
839         if (buf == NULL)
840                 return -1;
841
842         mac = dvobj_to_halmac(d);
843         api = HALMAC_GET_API(mac);
844
845         status = api->halmac_reg_sdio_cmd53_read_n(mac, addr, cnt, buf);
846         if (status != HALMAC_RET_SUCCESS) {
847                 RTW_ERR("%s: addr=0x%08x cnt=%d err=%d\n",
848                         __FUNCTION__, addr, cnt, status);
849                 return -1;
850         }
851
852         return 0;
853 }
854 #endif /* CONFIG_SDIO_HCI */
855
856 void rtw_halmac_read_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem)
857 {
858         struct dvobj_priv *d;
859
860
861         if (pmem == NULL) {
862                 RTW_ERR("pmem is NULL\n");
863                 return;
864         }
865
866         d = pintfhdl->pintf_dev;
867
868 #ifdef CONFIG_SDIO_HCI
869         if (addr & 0xFFFF0000) {
870                 int err = 0;
871
872                 err = _sdio_read_local(d, addr, cnt, pmem);
873                 if (!err)
874                         return;
875         }
876 #endif /* CONFIG_SDIO_HCI */
877
878         _read_register(d, addr, cnt, pmem);
879 }
880
881 #ifdef CONFIG_SDIO_INDIRECT_ACCESS
882 u8 rtw_halmac_iread8(struct intf_hdl *pintfhdl, u32 addr)
883 {
884         struct halmac_adapter *mac;
885         struct halmac_api *api;
886
887         /* WARNING: pintf_dev should not be null! */
888         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
889         api = HALMAC_GET_API(mac);
890
891         /*return api->halmac_reg_read_indirect_8(mac, addr);*/
892         return api->halmac_reg_read_8(mac, addr);
893 }
894
895 u16 rtw_halmac_iread16(struct intf_hdl *pintfhdl, u32 addr)
896 {
897         struct halmac_adapter *mac;
898         struct halmac_api *api;
899         u16 val16 = 0;
900
901         /* WARNING: pintf_dev should not be null! */
902         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
903         api = HALMAC_GET_API(mac);
904
905         /*return api->halmac_reg_read_indirect_16(mac, addr);*/
906         return api->halmac_reg_read_16(mac, addr);
907 }
908
909 u32 rtw_halmac_iread32(struct intf_hdl *pintfhdl, u32 addr)
910 {
911         struct halmac_adapter *mac;
912         struct halmac_api *api;
913
914
915         /* WARNING: pintf_dev should not be null! */
916         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
917         api = HALMAC_GET_API(mac);
918
919         return api->halmac_reg_read_indirect_32(mac, addr);
920 }
921 #endif /* CONFIG_SDIO_INDIRECT_ACCESS */
922
923 int rtw_halmac_write8(struct intf_hdl *pintfhdl, u32 addr, u8 value)
924 {
925         struct halmac_adapter *mac;
926         struct halmac_api *api;
927         enum halmac_ret_status status;
928
929
930         /* WARNING: pintf_dev should not be null! */
931         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
932         api = HALMAC_GET_API(mac);
933
934         status = api->halmac_reg_write_8(mac, addr, value);
935
936         if (status == HALMAC_RET_SUCCESS)
937                 return 0;
938
939         return -1;
940 }
941
942 int rtw_halmac_write16(struct intf_hdl *pintfhdl, u32 addr, u16 value)
943 {
944         struct halmac_adapter *mac;
945         struct halmac_api *api;
946         enum halmac_ret_status status;
947
948
949         /* WARNING: pintf_dev should not be null! */
950         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
951         api = HALMAC_GET_API(mac);
952
953         status = api->halmac_reg_write_16(mac, addr, value);
954
955         if (status == HALMAC_RET_SUCCESS)
956                 return 0;
957
958         return -1;
959 }
960
961 int rtw_halmac_write32(struct intf_hdl *pintfhdl, u32 addr, u32 value)
962 {
963         struct halmac_adapter *mac;
964         struct halmac_api *api;
965         enum halmac_ret_status status;
966
967
968         /* WARNING: pintf_dev should not be null! */
969         mac = dvobj_to_halmac(pintfhdl->pintf_dev);
970         api = HALMAC_GET_API(mac);
971
972         status = api->halmac_reg_write_32(mac, addr, value);
973
974         if (status == HALMAC_RET_SUCCESS)
975                 return 0;
976
977         return -1;
978 }
979
980 static int init_write_rsvd_page_size(struct dvobj_priv *d)
981 {
982         struct halmac_adapter *mac;
983         struct halmac_api *api;
984         u32 size = 0;
985         struct halmac_ofld_func_info ofld_info;
986         enum halmac_ret_status status;
987         int err = 0;
988
989
990 #ifdef CONFIG_USB_HCI
991         /* for USB do not exceed MAX_CMDBUF_SZ */
992         size = 0x1000;
993 #elif defined(CONFIG_PCI_HCI)
994         size = MAX_CMDBUF_SZ - TXDESC_OFFSET;
995 #elif defined(CONFIG_SDIO_HCI)
996         size = 0x7000; /* 28KB */
997 #endif
998
999         /* If size==0, use HALMAC default setting and don't call any function */
1000         if (!size)
1001                 return 0;
1002
1003         err = rtw_halmac_set_max_dl_fw_size(d, size);
1004         if (err) {
1005                 RTW_ERR("%s: Fail to set max download fw size!\n", __FUNCTION__);
1006                 return -1;
1007         }
1008
1009         mac = dvobj_to_halmac(d);
1010         api = HALMAC_GET_API(mac);
1011
1012         _rtw_memset(&ofld_info, 0, sizeof(ofld_info));
1013         ofld_info.halmac_malloc_max_sz = 0xFFFFFFFF;
1014         ofld_info.rsvd_pg_drv_buf_max_sz = size;
1015         status = api->halmac_ofld_func_cfg(mac, &ofld_info);
1016         if (status != HALMAC_RET_SUCCESS) {
1017                 RTW_ERR("%s: Fail to config offload parameters!\n", __FUNCTION__);
1018                 return -1;
1019         }
1020
1021         return 0;
1022 }
1023
1024 static int init_priv(struct halmacpriv *priv)
1025 {
1026         struct halmac_indicator *indicator;
1027         u32 count, size;
1028
1029
1030         if (priv->indicator)
1031                 RTW_WARN("%s: HALMAC private data is not CLEAR!\n", __FUNCTION__);
1032         count = HALMAC_FEATURE_ALL + 1;
1033         size = sizeof(*indicator) * count;
1034         indicator = (struct halmac_indicator *)rtw_zmalloc(size);
1035         if (!indicator)
1036                 return -1;
1037         priv->indicator = indicator;
1038
1039         return 0;
1040 }
1041
1042 static void deinit_priv(struct halmacpriv *priv)
1043 {
1044         struct halmac_indicator *indicator;
1045
1046
1047         indicator = priv->indicator;
1048         priv->indicator = NULL;
1049         if (indicator) {
1050                 u32 count, size;
1051
1052                 count = HALMAC_FEATURE_ALL + 1;
1053 #ifdef CONFIG_RTW_DEBUG
1054                 {
1055                         struct submit_ctx *sctx;
1056                         u32 i;
1057
1058                         for (i = 0; i < count; i++) {
1059                                 if (!indicator[i].sctx)
1060                                         continue;
1061
1062                                 RTW_WARN("%s: %s id(%d) sctx still exist!!\n",
1063                                         __FUNCTION__, RTW_HALMAC_FEATURE_NAME[i], i);
1064                                 sctx = indicator[i].sctx;
1065                                 indicator[i].sctx = NULL;
1066                                 rtw_mfree((u8 *)sctx, sizeof(*sctx));
1067                         }
1068                 }
1069 #endif /* !CONFIG_RTW_DEBUG */
1070                 size = sizeof(*indicator) * count;
1071                 rtw_mfree((u8 *)indicator, size);
1072         }
1073 }
1074
1075 #ifdef CONFIG_SDIO_HCI
1076 static enum halmac_sdio_spec_ver _sdio_ver_drv2halmac(struct dvobj_priv *d)
1077 {
1078         bool v3;
1079         enum halmac_sdio_spec_ver ver;
1080
1081
1082         v3 = rtw_is_sdio30(dvobj_get_primary_adapter(d));
1083         if (v3)
1084                 ver = HALMAC_SDIO_SPEC_VER_3_00;
1085         else
1086                 ver = HALMAC_SDIO_SPEC_VER_2_00;
1087
1088         return ver;
1089 }
1090 #endif /* CONFIG_SDIO_HCI */
1091
1092 void rtw_halmac_get_version(char *str, u32 len)
1093 {
1094         enum halmac_ret_status status;
1095         struct halmac_ver ver;
1096
1097
1098         status = halmac_get_version(&ver);
1099         if (status != HALMAC_RET_SUCCESS)
1100                 return;
1101
1102         rtw_sprintf(str, len, "V%d_%02d_%02d",
1103                     ver.major_ver, ver.prototype_ver, ver.minor_ver);
1104 }
1105
1106 int rtw_halmac_init_adapter(struct dvobj_priv *d, struct halmac_platform_api *pf_api)
1107 {
1108         struct halmac_adapter *halmac;
1109         struct halmac_api *api;
1110         enum halmac_interface intf;
1111         enum halmac_ret_status status;
1112         int err = 0;
1113 #ifdef CONFIG_SDIO_HCI
1114         struct halmac_sdio_hw_info info;
1115 #endif /* CONFIG_SDIO_HCI */
1116
1117
1118         halmac = dvobj_to_halmac(d);
1119         if (halmac) {
1120                 RTW_WARN("%s: initialize already completed!\n", __FUNCTION__);
1121                 goto error;
1122         }
1123
1124         err = init_priv(&d->hmpriv);
1125         if (err)
1126                 goto error;
1127
1128 #ifdef CONFIG_SDIO_HCI
1129         intf = HALMAC_INTERFACE_SDIO;
1130 #elif defined(CONFIG_USB_HCI)
1131         intf = HALMAC_INTERFACE_USB;
1132 #elif defined(CONFIG_PCI_HCI)
1133         intf = HALMAC_INTERFACE_PCIE;
1134 #else
1135 #warning "INTERFACE(CONFIG_XXX_HCI) not be defined!!"
1136         intf = HALMAC_INTERFACE_UNDEFINE;
1137 #endif
1138         status = halmac_init_adapter(d, pf_api, intf, &halmac, &api);
1139         if (HALMAC_RET_SUCCESS != status) {
1140                 RTW_ERR("%s: halmac_init_adapter fail!(status=%d)\n", __FUNCTION__, status);
1141                 err = -1;
1142                 if (halmac)
1143                         goto deinit;
1144                 goto free;
1145         }
1146
1147         dvobj_set_halmac(d, halmac);
1148
1149         status = api->halmac_interface_integration_tuning(halmac);
1150         if (status != HALMAC_RET_SUCCESS) {
1151                 RTW_ERR("%s: halmac_interface_integration_tuning fail!(status=%d)\n", __FUNCTION__, status);
1152                 err = -1;
1153                 goto deinit;
1154         }
1155
1156         status = api->halmac_phy_cfg(halmac, HALMAC_INTF_PHY_PLATFORM_ALL);
1157         if (status != HALMAC_RET_SUCCESS) {
1158                 RTW_ERR("%s: halmac_phy_cfg fail!(status=%d)\n", __FUNCTION__, status);
1159                 err = -1;
1160                 goto deinit;
1161         }
1162
1163         init_write_rsvd_page_size(d);
1164
1165 #ifdef CONFIG_SDIO_HCI
1166         _rtw_memset(&info, 0, sizeof(info));
1167         info.spec_ver = _sdio_ver_drv2halmac(d);
1168         /* Convert clock speed unit to MHz from Hz */
1169         info.clock_speed = RTW_DIV_ROUND_UP(rtw_sdio_get_clock(d), 1000000);
1170         info.block_size = rtw_sdio_get_block_size(d);
1171         RTW_DBG("%s: SDIO ver=%u clock=%uMHz blk_size=%u bytes\n",
1172                 __FUNCTION__, info.spec_ver+2, info.clock_speed,
1173                 info.block_size);
1174         status = api->halmac_sdio_hw_info(halmac, &info);
1175         if (status != HALMAC_RET_SUCCESS) {
1176                 RTW_ERR("%s: halmac_sdio_hw_info fail!(status=%d)\n",
1177                         __FUNCTION__, status);
1178                 err = -1;
1179                 goto deinit;
1180         }
1181 #endif /* CONFIG_SDIO_HCI */
1182
1183         return 0;
1184
1185 deinit:
1186         status = halmac_deinit_adapter(halmac);
1187         dvobj_set_halmac(d, NULL);
1188         if (status != HALMAC_RET_SUCCESS)
1189                 RTW_ERR("%s: halmac_deinit_adapter fail!(status=%d)\n",
1190                         __FUNCTION__, status);
1191
1192 free:
1193         deinit_priv(&d->hmpriv);
1194
1195 error:
1196         return err;
1197 }
1198
1199 int rtw_halmac_deinit_adapter(struct dvobj_priv *d)
1200 {
1201         struct halmac_adapter *halmac;
1202         enum halmac_ret_status status;
1203         int err = 0;
1204
1205
1206         halmac = dvobj_to_halmac(d);
1207         if (halmac) {
1208                 status = halmac_deinit_adapter(halmac);
1209                 dvobj_set_halmac(d, NULL);
1210                 if (status != HALMAC_RET_SUCCESS)
1211                         err = -1;
1212         }
1213
1214         deinit_priv(&d->hmpriv);
1215
1216         return err;
1217 }
1218
1219 static inline enum halmac_portid _hw_port_drv2halmac(enum _hw_port hwport)
1220 {
1221         enum halmac_portid port = HALMAC_PORTID_NUM;
1222
1223
1224         switch (hwport) {
1225         case HW_PORT0:
1226                 port = HALMAC_PORTID0;
1227                 break;
1228         case HW_PORT1:
1229                 port = HALMAC_PORTID1;
1230                 break;
1231         case HW_PORT2:
1232                 port = HALMAC_PORTID2;
1233                 break;
1234         case HW_PORT3:
1235                 port = HALMAC_PORTID3;
1236                 break;
1237         case HW_PORT4:
1238                 port = HALMAC_PORTID4;
1239                 break;
1240         default:
1241                 break;
1242         }
1243
1244         return port;
1245 }
1246
1247 static enum halmac_network_type_select _network_type_drv2halmac(u8 type)
1248 {
1249         enum halmac_network_type_select network = HALMAC_NETWORK_UNDEFINE;
1250
1251
1252         switch (type) {
1253         case _HW_STATE_NOLINK_:
1254         case _HW_STATE_MONITOR_:
1255                 network = HALMAC_NETWORK_NO_LINK;
1256                 break;
1257
1258         case _HW_STATE_ADHOC_:
1259                 network = HALMAC_NETWORK_ADHOC;
1260                 break;
1261
1262         case _HW_STATE_STATION_:
1263                 network = HALMAC_NETWORK_INFRASTRUCTURE;
1264                 break;
1265
1266         case _HW_STATE_AP_:
1267                 network = HALMAC_NETWORK_AP;
1268                 break;
1269         }
1270
1271         return network;
1272 }
1273
1274 static u8 _network_type_halmac2drv(enum halmac_network_type_select network)
1275 {
1276         u8 type = _HW_STATE_NOLINK_;
1277
1278
1279         switch (network) {
1280         case HALMAC_NETWORK_NO_LINK:
1281         case HALMAC_NETWORK_UNDEFINE:
1282                 type = _HW_STATE_NOLINK_;
1283                 break;
1284
1285         case HALMAC_NETWORK_ADHOC:
1286                 type = _HW_STATE_ADHOC_;
1287                 break;
1288
1289         case HALMAC_NETWORK_INFRASTRUCTURE:
1290                 type = _HW_STATE_STATION_;
1291                 break;
1292
1293         case HALMAC_NETWORK_AP:
1294                 type = _HW_STATE_AP_;
1295                 break;
1296         }
1297
1298         return type;
1299 }
1300
1301 static void _beacon_ctrl_halmac2drv(struct halmac_bcn_ctrl *ctrl,
1302                                 struct rtw_halmac_bcn_ctrl *drv_ctrl)
1303 {
1304         drv_ctrl->rx_bssid_fit = ctrl->dis_rx_bssid_fit ? 0 : 1;
1305         drv_ctrl->txbcn_rpt = ctrl->en_txbcn_rpt ? 1 : 0;
1306         drv_ctrl->tsf_update = ctrl->dis_tsf_udt ? 0 : 1;
1307         drv_ctrl->enable_bcn = ctrl->en_bcn ? 1 : 0;
1308         drv_ctrl->rxbcn_rpt = ctrl->en_rxbcn_rpt ? 1 : 0;
1309         drv_ctrl->p2p_ctwin = ctrl->en_p2p_ctwin ? 1 : 0;
1310         drv_ctrl->p2p_bcn_area = ctrl->en_p2p_bcn_area ? 1 : 0;
1311 }
1312
1313 static void _beacon_ctrl_drv2halmac(struct rtw_halmac_bcn_ctrl *drv_ctrl,
1314                                 struct halmac_bcn_ctrl *ctrl)
1315 {
1316         ctrl->dis_rx_bssid_fit = drv_ctrl->rx_bssid_fit ? 0 : 1;
1317         ctrl->en_txbcn_rpt = drv_ctrl->txbcn_rpt ? 1 : 0;
1318         ctrl->dis_tsf_udt = drv_ctrl->tsf_update ? 0 : 1;
1319         ctrl->en_bcn = drv_ctrl->enable_bcn ? 1 : 0;
1320         ctrl->en_rxbcn_rpt = drv_ctrl->rxbcn_rpt ? 1 : 0;
1321         ctrl->en_p2p_ctwin = drv_ctrl->p2p_ctwin ? 1 : 0;
1322         ctrl->en_p2p_bcn_area = drv_ctrl->p2p_bcn_area ? 1 : 0;
1323 }
1324
1325 int rtw_halmac_get_hw_value(struct dvobj_priv *d, enum halmac_hw_id hw_id, void *pvalue)
1326 {
1327         struct halmac_adapter *mac;
1328         struct halmac_api *api;
1329         enum halmac_ret_status status;
1330
1331
1332         mac = dvobj_to_halmac(d);
1333         api = HALMAC_GET_API(mac);
1334
1335         status = api->halmac_get_hw_value(mac, hw_id, pvalue);
1336         if (HALMAC_RET_SUCCESS != status)
1337                 return -1;
1338
1339         return 0;
1340 }
1341
1342 /**
1343  * rtw_halmac_get_tx_fifo_size() - TX FIFO size
1344  * @d:          struct dvobj_priv*
1345  * @size:       TX FIFO size, unit is byte.
1346  *
1347  * Get TX FIFO size(byte) from HALMAC.
1348  *
1349  * Rteurn 0 for OK, otherwise fail.
1350  */
1351 int rtw_halmac_get_tx_fifo_size(struct dvobj_priv *d, u32 *size)
1352 {
1353         struct halmac_adapter *halmac;
1354         struct halmac_api *api;
1355         enum halmac_ret_status status;
1356         u32 val = 0;
1357
1358
1359         halmac = dvobj_to_halmac(d);
1360         api = HALMAC_GET_API(halmac);
1361
1362         status = api->halmac_get_hw_value(halmac, HALMAC_HW_TXFIFO_SIZE, &val);
1363         if (status != HALMAC_RET_SUCCESS)
1364                 return -1;
1365
1366         *size = val;
1367
1368         return 0;
1369 }
1370
1371 /**
1372  * rtw_halmac_get_rx_fifo_size() - RX FIFO size
1373  * @d:          struct dvobj_priv*
1374  * @size:       RX FIFO size, unit is byte
1375  *
1376  * Get RX FIFO size(byte) from HALMAC.
1377  *
1378  * Rteurn 0 for OK, otherwise fail.
1379  */
1380 int rtw_halmac_get_rx_fifo_size(struct dvobj_priv *d, u32 *size)
1381 {
1382         struct halmac_adapter *halmac;
1383         struct halmac_api *api;
1384         enum halmac_ret_status status;
1385         u32 val = 0;
1386
1387
1388         halmac = dvobj_to_halmac(d);
1389         api = HALMAC_GET_API(halmac);
1390
1391         status = api->halmac_get_hw_value(halmac, HALMAC_HW_RXFIFO_SIZE, &val);
1392         if (status != HALMAC_RET_SUCCESS)
1393                 return -1;
1394
1395         *size = val;
1396
1397         return 0;
1398 }
1399
1400 /**
1401  * rtw_halmac_get_rsvd_drv_pg_bndy() - Reserve page boundary of driver
1402  * @d:          struct dvobj_priv*
1403  * @size:       Page size, unit is byte
1404  *
1405  * Get reserve page boundary of driver from HALMAC.
1406  *
1407  * Rteurn 0 for OK, otherwise fail.
1408  */
1409 int rtw_halmac_get_rsvd_drv_pg_bndy(struct dvobj_priv *d, u16 *bndy)
1410 {
1411         struct halmac_adapter *halmac;
1412         struct halmac_api *api;
1413         enum halmac_ret_status status;
1414         u16 val = 0;
1415
1416
1417         halmac = dvobj_to_halmac(d);
1418         api = HALMAC_GET_API(halmac);
1419
1420         status = api->halmac_get_hw_value(halmac, HALMAC_HW_RSVD_PG_BNDY, &val);
1421         if (status != HALMAC_RET_SUCCESS)
1422                 return -1;
1423
1424         *bndy = val;
1425
1426         return 0;
1427 }
1428
1429 /**
1430  * rtw_halmac_get_page_size() - Page size
1431  * @d:          struct dvobj_priv*
1432  * @size:       Page size, unit is byte
1433  *
1434  * Get TX/RX page size(byte) from HALMAC.
1435  *
1436  * Rteurn 0 for OK, otherwise fail.
1437  */
1438 int rtw_halmac_get_page_size(struct dvobj_priv *d, u32 *size)
1439 {
1440         struct halmac_adapter *halmac;
1441         struct halmac_api *api;
1442         enum halmac_ret_status status;
1443         u32 val = 0;
1444
1445
1446         halmac = dvobj_to_halmac(d);
1447         api = HALMAC_GET_API(halmac);
1448
1449         status = api->halmac_get_hw_value(halmac, HALMAC_HW_PAGE_SIZE, &val);
1450         if (status != HALMAC_RET_SUCCESS)
1451                 return -1;
1452
1453         *size = val;
1454
1455         return 0;
1456 }
1457
1458 /**
1459  * rtw_halmac_get_tx_agg_align_size() - TX aggregation align size
1460  * @d:          struct dvobj_priv*
1461  * @size:       TX aggregation align size, unit is byte
1462  *
1463  * Get TX aggregation align size(byte) from HALMAC.
1464  *
1465  * Rteurn 0 for OK, otherwise fail.
1466  */
1467 int rtw_halmac_get_tx_agg_align_size(struct dvobj_priv *d, u16 *size)
1468 {
1469         struct halmac_adapter *halmac;
1470         struct halmac_api *api;
1471         enum halmac_ret_status status;
1472         u16 val = 0;
1473
1474
1475         halmac = dvobj_to_halmac(d);
1476         api = HALMAC_GET_API(halmac);
1477
1478         status = api->halmac_get_hw_value(halmac, HALMAC_HW_TX_AGG_ALIGN_SIZE, &val);
1479         if (status != HALMAC_RET_SUCCESS)
1480                 return -1;
1481
1482         *size = val;
1483
1484         return 0;
1485 }
1486
1487 /**
1488  * rtw_halmac_get_rx_agg_align_size() - RX aggregation align size
1489  * @d:          struct dvobj_priv*
1490  * @size:       RX aggregation align size, unit is byte
1491  *
1492  * Get RX aggregation align size(byte) from HALMAC.
1493  *
1494  * Rteurn 0 for OK, otherwise fail.
1495  */
1496 int rtw_halmac_get_rx_agg_align_size(struct dvobj_priv *d, u8 *size)
1497 {
1498         struct halmac_adapter *halmac;
1499         struct halmac_api *api;
1500         enum halmac_ret_status status;
1501         u8 val = 0;
1502
1503
1504         halmac = dvobj_to_halmac(d);
1505         api = HALMAC_GET_API(halmac);
1506
1507         status = api->halmac_get_hw_value(halmac, HALMAC_HW_RX_AGG_ALIGN_SIZE, &val);
1508         if (status != HALMAC_RET_SUCCESS)
1509                 return -1;
1510
1511         *size = val;
1512
1513         return 0;
1514 }
1515
1516 /*
1517  * Description:
1518  *      Get RX driver info size. RX driver info is a small memory space between
1519  *      scriptor and RX payload.
1520  *
1521  *      +-------------------------+
1522  *      | RX descriptor           |
1523  *      | usually 24 bytes        |
1524  *      +-------------------------+
1525  *      | RX driver info          |
1526  *      | depends on driver cfg   |
1527  *      +-------------------------+
1528  *      | RX paylad               |
1529  *      |                         |
1530  *      +-------------------------+
1531  *
1532  * Parameter:
1533  *      d       pointer to struct dvobj_priv of driver
1534  *      sz      rx driver info size in bytes.
1535  *
1536  * Rteurn:
1537  *      0       Success
1538  *      other   Fail
1539  */
1540 int rtw_halmac_get_rx_drv_info_sz(struct dvobj_priv *d, u8 *sz)
1541 {
1542         enum halmac_ret_status status;
1543         struct halmac_adapter *halmac = dvobj_to_halmac(d);
1544         struct halmac_api *api = HALMAC_GET_API(halmac);
1545         u8 dw = 0;
1546
1547         status = api->halmac_get_hw_value(halmac, HALMAC_HW_DRV_INFO_SIZE, &dw);
1548         if (status != HALMAC_RET_SUCCESS)
1549                 return -1;
1550
1551         *sz = dw * 8;
1552         return 0;
1553 }
1554
1555 /**
1556  * rtw_halmac_get_tx_desc_size() - TX descriptor size
1557  * @d:          struct dvobj_priv*
1558  * @size:       TX descriptor size, unit is byte.
1559  *
1560  * Get TX descriptor size(byte) from HALMAC.
1561  *
1562  * Rteurn 0 for OK, otherwise fail.
1563  */
1564 int rtw_halmac_get_tx_desc_size(struct dvobj_priv *d, u32 *size)
1565 {
1566         struct halmac_adapter *halmac;
1567         struct halmac_api *api;
1568         enum halmac_ret_status status;
1569         u32 val = 0;
1570
1571
1572         halmac = dvobj_to_halmac(d);
1573         api = HALMAC_GET_API(halmac);
1574
1575         status = api->halmac_get_hw_value(halmac, HALMAC_HW_TX_DESC_SIZE, &val);
1576         if (status != HALMAC_RET_SUCCESS)
1577                 return -1;
1578
1579         *size = val;
1580
1581         return 0;
1582 }
1583
1584 /**
1585  * rtw_halmac_get_rx_desc_size() - RX descriptor size
1586  * @d:          struct dvobj_priv*
1587  * @size:       RX descriptor size, unit is byte.
1588  *
1589  * Get RX descriptor size(byte) from HALMAC.
1590  *
1591  * Rteurn 0 for OK, otherwise fail.
1592  */
1593 int rtw_halmac_get_rx_desc_size(struct dvobj_priv *d, u32 *size)
1594 {
1595         struct halmac_adapter *halmac;
1596         struct halmac_api *api;
1597         enum halmac_ret_status status;
1598         u32 val = 0;
1599
1600
1601         halmac = dvobj_to_halmac(d);
1602         api = HALMAC_GET_API(halmac);
1603
1604         status = api->halmac_get_hw_value(halmac, HALMAC_HW_RX_DESC_SIZE, &val);
1605         if (status != HALMAC_RET_SUCCESS)
1606                 return -1;
1607
1608         *size = val;
1609
1610         return 0;
1611 }
1612
1613
1614 /**
1615  * rtw_halmac_get_fw_max_size() - Firmware MAX size
1616  * @d:          struct dvobj_priv*
1617  * @size:       MAX Firmware size, unit is byte.
1618  *
1619  * Get Firmware MAX size(byte) from HALMAC.
1620  *
1621  * Rteurn 0 for OK, otherwise fail.
1622  */
1623 static int rtw_halmac_get_fw_max_size(struct dvobj_priv *d, u32 *size)
1624 {
1625         struct halmac_adapter *halmac;
1626         struct halmac_api *api;
1627         enum halmac_ret_status status;
1628         u32 val = 0;
1629
1630
1631         halmac = dvobj_to_halmac(d);
1632         api = HALMAC_GET_API(halmac);
1633
1634         status = api->halmac_get_hw_value(halmac, HALMAC_HW_FW_MAX_SIZE, &val);
1635         if (status != HALMAC_RET_SUCCESS)
1636                 return -1;
1637
1638         *size = val;
1639
1640         return 0;
1641 }
1642
1643 /**
1644  * rtw_halmac_get_ori_h2c_size() - Original H2C MAX size
1645  * @d:          struct dvobj_priv*
1646  * @size:       H2C MAX size, unit is byte.
1647  *
1648  * Get original H2C MAX size(byte) from HALMAC.
1649  *
1650  * Rteurn 0 for OK, otherwise fail.
1651  */
1652 int rtw_halmac_get_ori_h2c_size(struct dvobj_priv *d, u32 *size)
1653 {
1654         struct halmac_adapter *halmac;
1655         struct halmac_api *api;
1656         enum halmac_ret_status status;
1657         u32 val = 0;
1658
1659
1660         halmac = dvobj_to_halmac(d);
1661         api = HALMAC_GET_API(halmac);
1662
1663         status = api->halmac_get_hw_value(halmac, HALMAC_HW_ORI_H2C_SIZE, &val);
1664         if (status != HALMAC_RET_SUCCESS)
1665                 return -1;
1666
1667         *size = val;
1668
1669         return 0;
1670 }
1671
1672 int rtw_halmac_get_oqt_size(struct dvobj_priv *d, u8 *size)
1673 {
1674         enum halmac_ret_status status;
1675         struct halmac_adapter *halmac;
1676         struct halmac_api *api;
1677         u8 val;
1678
1679
1680         if (!size)
1681                 return -1;
1682
1683         halmac = dvobj_to_halmac(d);
1684         api = HALMAC_GET_API(halmac);
1685
1686         status = api->halmac_get_hw_value(halmac, HALMAC_HW_AC_OQT_SIZE, &val);
1687         if (status != HALMAC_RET_SUCCESS)
1688                 return -1;
1689
1690         *size = val;
1691         return 0;
1692 }
1693
1694 int rtw_halmac_get_ac_queue_number(struct dvobj_priv *d, u8 *num)
1695 {
1696         enum halmac_ret_status status;
1697         struct halmac_adapter *halmac;
1698         struct halmac_api *api;
1699         u8 val;
1700
1701
1702         if (!num)
1703                 return -1;
1704
1705         halmac = dvobj_to_halmac(d);
1706         api = HALMAC_GET_API(halmac);
1707
1708         status = api->halmac_get_hw_value(halmac, HALMAC_HW_AC_QUEUE_NUM, &val);
1709         if (status != HALMAC_RET_SUCCESS)
1710                 return -1;
1711
1712         *num = val;
1713         return 0;
1714 }
1715
1716 /**
1717  * rtw_halmac_get_mac_address() - Get MAC address of specific port
1718  * @d:          struct dvobj_priv*
1719  * @hwport:     port
1720  * @addr:       buffer for storing MAC address
1721  *
1722  * Get MAC address of specific port from HALMAC.
1723  *
1724  * Rteurn 0 for OK, otherwise fail.
1725  */
1726 int rtw_halmac_get_mac_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
1727 {
1728         struct halmac_adapter *halmac;
1729         struct halmac_api *api;
1730         enum halmac_portid port;
1731         union halmac_wlan_addr hwa;
1732         enum halmac_ret_status status;
1733         int err = -1;
1734
1735
1736         if (!addr)
1737                 goto out;
1738
1739         halmac = dvobj_to_halmac(d);
1740         api = HALMAC_GET_API(halmac);
1741         port = _hw_port_drv2halmac(hwport);
1742         _rtw_memset(&hwa, 0, sizeof(hwa));
1743
1744         status = api->halmac_get_mac_addr(halmac, port, &hwa);
1745         if (status != HALMAC_RET_SUCCESS)
1746                 goto out;
1747
1748         _rtw_memcpy(addr, hwa.addr, 6);
1749
1750         err = 0;
1751 out:
1752         return err;
1753 }
1754
1755 /**
1756  * rtw_halmac_get_network_type() - Get network type of specific port
1757  * @d:          struct dvobj_priv*
1758  * @hwport:     port
1759  * @type:       buffer to put network type (_HW_STATE_*)
1760  *
1761  * Get network type of specific port from HALMAC.
1762  *
1763  * Rteurn 0 for OK, otherwise fail.
1764  */
1765 int rtw_halmac_get_network_type(struct dvobj_priv *d, enum _hw_port hwport, u8 *type)
1766 {
1767 #if 0
1768         struct halmac_adapter *halmac;
1769         struct halmac_api *api;
1770         enum halmac_portid port;
1771         enum halmac_network_type_select network;
1772         enum halmac_ret_status status;
1773         int err = -1;
1774
1775
1776         halmac = dvobj_to_halmac(d);
1777         api = HALMAC_GET_API(halmac);
1778         port = _hw_port_drv2halmac(hwport);
1779         network = HALMAC_NETWORK_UNDEFINE;
1780
1781         status = api->halmac_get_net_type(halmac, port, &network);
1782         if (status != HALMAC_RET_SUCCESS)
1783                 goto out;
1784
1785         *type = _network_type_halmac2drv(network);
1786
1787         err = 0;
1788 out:
1789         return err;
1790 #else
1791         struct _ADAPTER *a;
1792         enum halmac_portid port;
1793         enum halmac_network_type_select network;
1794         u32 val;
1795         int err = -1;
1796
1797
1798         a = dvobj_get_primary_adapter(d);
1799         port = _hw_port_drv2halmac(hwport);
1800         network = HALMAC_NETWORK_UNDEFINE;
1801
1802         switch (port) {
1803         case HALMAC_PORTID0:
1804                 val = rtw_read32(a, REG_CR);
1805                 network = BIT_GET_NETYPE0(val);
1806                 break;
1807
1808         case HALMAC_PORTID1:
1809                 val = rtw_read32(a, REG_CR);
1810                 network = BIT_GET_NETYPE1(val);
1811                 break;
1812
1813         case HALMAC_PORTID2:
1814                 val = rtw_read32(a, REG_CR_EXT);
1815                 network = BIT_GET_NETYPE2(val);
1816                 break;
1817
1818         case HALMAC_PORTID3:
1819                 val = rtw_read32(a, REG_CR_EXT);
1820                 network = BIT_GET_NETYPE3(val);
1821                 break;
1822
1823         case HALMAC_PORTID4:
1824                 val = rtw_read32(a, REG_CR_EXT);
1825                 network = BIT_GET_NETYPE4(val);
1826                 break;
1827
1828         default:
1829                 goto out;
1830         }
1831
1832         *type = _network_type_halmac2drv(network);
1833
1834         err = 0;
1835 out:
1836         return err;
1837 #endif
1838 }
1839
1840 /**
1841  * rtw_halmac_get_bcn_ctrl() - Get beacon control setting of specific port
1842  * @d:          struct dvobj_priv*
1843  * @hwport:     port
1844  * @bcn_ctrl:   setting of beacon control
1845  *
1846  * Get beacon control setting of specific port from HALMAC.
1847  *
1848  * Rteurn 0 for OK, otherwise fail.
1849  */
1850 int rtw_halmac_get_bcn_ctrl(struct dvobj_priv *d, enum _hw_port hwport,
1851                         struct rtw_halmac_bcn_ctrl *bcn_ctrl)
1852 {
1853         struct halmac_adapter *halmac;
1854         struct halmac_api *api;
1855         enum halmac_portid port;
1856         struct halmac_bcn_ctrl ctrl;
1857         enum halmac_ret_status status;
1858         int err = -1;
1859
1860
1861         halmac = dvobj_to_halmac(d);
1862         api = HALMAC_GET_API(halmac);
1863         port = _hw_port_drv2halmac(hwport);
1864         _rtw_memset(&ctrl, 0, sizeof(ctrl));
1865
1866         status = api->halmac_rw_bcn_ctrl(halmac, port, 0, &ctrl);
1867         if (status != HALMAC_RET_SUCCESS)
1868                 goto out;
1869         _beacon_ctrl_halmac2drv(&ctrl, bcn_ctrl);
1870
1871         err = 0;
1872 out:
1873         return err;
1874 }
1875
1876 /*
1877  * Note:
1878  *      When this function return, the register REG_RCR may be changed.
1879  */
1880 int rtw_halmac_config_rx_info(struct dvobj_priv *d, enum halmac_drv_info info)
1881 {
1882         struct halmac_adapter *halmac;
1883         struct halmac_api *api;
1884         enum halmac_ret_status status;
1885         int err = -1;
1886
1887
1888         halmac = dvobj_to_halmac(d);
1889         api = HALMAC_GET_API(halmac);
1890
1891         status = api->halmac_cfg_drv_info(halmac, info);
1892         if (status != HALMAC_RET_SUCCESS)
1893                 goto out;
1894
1895         err = 0;
1896 out:
1897         return err;
1898 }
1899
1900 /**
1901  * rtw_halmac_set_max_dl_fw_size() - Set the MAX download firmware size
1902  * @d:          struct dvobj_priv*
1903  * @size:       the max download firmware size in one I/O
1904  *
1905  * Set the max download firmware size in one I/O.
1906  * Please also consider the max size of the callback function "SEND_RSVD_PAGE"
1907  * could accept, because download firmware would call "SEND_RSVD_PAGE" to send
1908  * firmware to IC.
1909  *
1910  * If the value of "size" is not even, it would be rounded down to nearest
1911  * even, and 0 and 1 are both invalid value.
1912  *
1913  * Return 0 for setting OK, otherwise fail.
1914  */
1915 int rtw_halmac_set_max_dl_fw_size(struct dvobj_priv *d, u32 size)
1916 {
1917         struct halmac_adapter *mac;
1918         struct halmac_api *api;
1919         enum halmac_ret_status status;
1920
1921
1922         if (!size || (size == 1))
1923                 return -1;
1924
1925         mac = dvobj_to_halmac(d);
1926         if (!mac) {
1927                 RTW_ERR("%s: HALMAC is not ready!!\n", __FUNCTION__);
1928                 return -1;
1929         }
1930         api = HALMAC_GET_API(mac);
1931
1932         size &= ~1; /* round down to even */
1933         status = api->halmac_cfg_max_dl_size(mac, size);
1934         if (status != HALMAC_RET_SUCCESS) {
1935                 RTW_WARN("%s: Fail to cfg_max_dl_size(%d), err=%d!!\n",
1936                          __FUNCTION__, size, status);
1937                 return -1;
1938         }
1939
1940         return 0;
1941 }
1942
1943 /**
1944  * rtw_halmac_set_mac_address() - Set mac address of specific port
1945  * @d:          struct dvobj_priv*
1946  * @hwport:     port
1947  * @addr:       mac address
1948  *
1949  * Set self mac address of specific port to HALMAC.
1950  *
1951  * Rteurn 0 for OK, otherwise fail.
1952  */
1953 int rtw_halmac_set_mac_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
1954 {
1955         struct halmac_adapter *halmac;
1956         struct halmac_api *api;
1957         enum halmac_portid port;
1958         union halmac_wlan_addr hwa;
1959         enum halmac_ret_status status;
1960         int err = -1;
1961
1962
1963         halmac = dvobj_to_halmac(d);
1964         api = HALMAC_GET_API(halmac);
1965
1966         port = _hw_port_drv2halmac(hwport);
1967         _rtw_memset(&hwa, 0, sizeof(hwa));
1968         _rtw_memcpy(hwa.addr, addr, 6);
1969
1970         status = api->halmac_cfg_mac_addr(halmac, port, &hwa);
1971         if (status != HALMAC_RET_SUCCESS)
1972                 goto out;
1973
1974         err = 0;
1975 out:
1976         return err;
1977 }
1978
1979 /**
1980  * rtw_halmac_set_bssid() - Set BSSID of specific port
1981  * @d:          struct dvobj_priv*
1982  * @hwport:     port
1983  * @addr:       BSSID, mac address of AP
1984  *
1985  * Set BSSID of specific port to HALMAC.
1986  *
1987  * Rteurn 0 for OK, otherwise fail.
1988  */
1989 int rtw_halmac_set_bssid(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
1990 {
1991         struct halmac_adapter *halmac;
1992         struct halmac_api *api;
1993         enum halmac_portid port;
1994         union halmac_wlan_addr hwa;
1995         enum halmac_ret_status status;
1996         int err = -1;
1997
1998
1999         halmac = dvobj_to_halmac(d);
2000         api = HALMAC_GET_API(halmac);
2001         port = _hw_port_drv2halmac(hwport);
2002
2003         _rtw_memset(&hwa, 0, sizeof(hwa));
2004         _rtw_memcpy(hwa.addr, addr, 6);
2005         status = api->halmac_cfg_bssid(halmac, port, &hwa);
2006         if (status != HALMAC_RET_SUCCESS)
2007                 goto out;
2008
2009         err = 0;
2010 out:
2011         return err;
2012 }
2013
2014 /**
2015  * rtw_halmac_set_tx_address() - Set transmitter address of specific port
2016  * @d:          struct dvobj_priv*
2017  * @hwport:     port
2018  * @addr:       transmitter address
2019  *
2020  * Set transmitter address of specific port to HALMAC.
2021  *
2022  * Rteurn 0 for OK, otherwise fail.
2023  */
2024 int rtw_halmac_set_tx_address(struct dvobj_priv *d, enum _hw_port hwport, u8 *addr)
2025 {
2026         struct halmac_adapter *halmac;
2027         struct halmac_api *api;
2028         enum halmac_portid port;
2029         union halmac_wlan_addr hwa;
2030         enum halmac_ret_status status;
2031         int err = -1;
2032
2033
2034         halmac = dvobj_to_halmac(d);
2035         api = HALMAC_GET_API(halmac);
2036         port = _hw_port_drv2halmac(hwport);
2037         _rtw_memset(&hwa, 0, sizeof(hwa));
2038         _rtw_memcpy(hwa.addr, addr, 6);
2039
2040         status = api->halmac_cfg_transmitter_addr(halmac, port, &hwa);
2041         if (status != HALMAC_RET_SUCCESS)
2042                 goto out;
2043
2044         err = 0;
2045 out:
2046         return err;
2047 }
2048
2049 /**
2050  * rtw_halmac_set_network_type() - Set network type of specific port
2051  * @d:          struct dvobj_priv*
2052  * @hwport:     port
2053  * @type:       network type (_HW_STATE_*)
2054  *
2055  * Set network type of specific port to HALMAC.
2056  *
2057  * Rteurn 0 for OK, otherwise fail.
2058  */
2059 int rtw_halmac_set_network_type(struct dvobj_priv *d, enum _hw_port hwport, u8 type)
2060 {
2061         struct halmac_adapter *halmac;
2062         struct halmac_api *api;
2063         enum halmac_portid port;
2064         enum halmac_network_type_select network;
2065         enum halmac_ret_status status;
2066         int err = -1;
2067
2068
2069         halmac = dvobj_to_halmac(d);
2070         api = HALMAC_GET_API(halmac);
2071         port = _hw_port_drv2halmac(hwport);
2072         network = _network_type_drv2halmac(type);
2073
2074         status = api->halmac_cfg_net_type(halmac, port, network);
2075         if (status != HALMAC_RET_SUCCESS)
2076                 goto out;
2077
2078         err = 0;
2079 out:
2080         return err;
2081 }
2082
2083 /**
2084  * rtw_halmac_reset_tsf() - Reset TSF timer of specific port
2085  * @d:          struct dvobj_priv*
2086  * @hwport:     port
2087  *
2088  * Notice HALMAC to reset timing synchronization function(TSF) timer of
2089  * specific port.
2090  *
2091  * Rteurn 0 for OK, otherwise fail.
2092  */
2093 int rtw_halmac_reset_tsf(struct dvobj_priv *d, enum _hw_port hwport)
2094 {
2095         struct halmac_adapter *halmac;
2096         struct halmac_api *api;
2097         enum halmac_portid port;
2098         enum halmac_ret_status status;
2099         int err = -1;
2100
2101
2102         halmac = dvobj_to_halmac(d);
2103         api = HALMAC_GET_API(halmac);
2104         port = _hw_port_drv2halmac(hwport);
2105
2106         status = api->halmac_cfg_tsf_rst(halmac, port);
2107         if (status != HALMAC_RET_SUCCESS)
2108                 goto out;
2109
2110         err = 0;
2111 out:
2112         return err;
2113 }
2114
2115 /**
2116  * rtw_halmac_set_bcn_interval() - Set beacon interval of each port
2117  * @d:          struct dvobj_priv*
2118  * @hwport:     port
2119  * @space:      beacon interval, unit is ms
2120  *
2121  * Set beacon interval of specific port to HALMAC.
2122  *
2123  * Rteurn 0 for OK, otherwise fail.
2124  */
2125 int rtw_halmac_set_bcn_interval(struct dvobj_priv *d, enum _hw_port hwport,
2126                                 u32 interval)
2127 {
2128         struct halmac_adapter *halmac;
2129         struct halmac_api *api;
2130         enum halmac_portid port;
2131         enum halmac_ret_status status;
2132         int err = -1;
2133
2134
2135         halmac = dvobj_to_halmac(d);
2136         api = HALMAC_GET_API(halmac);
2137         port = _hw_port_drv2halmac(hwport);
2138
2139         status = api->halmac_cfg_bcn_space(halmac, port, interval);
2140         if (status != HALMAC_RET_SUCCESS)
2141                 goto out;
2142
2143         err = 0;
2144 out:
2145         return err;
2146 }
2147
2148 /**
2149  * rtw_halmac_set_bcn_ctrl() - Set beacon control setting of each port
2150  * @d:          struct dvobj_priv*
2151  * @hwport:     port
2152  * @bcn_ctrl:   setting of beacon control
2153  *
2154  * Set beacon control setting of specific port to HALMAC.
2155  *
2156  * Rteurn 0 for OK, otherwise fail.
2157  */
2158 int rtw_halmac_set_bcn_ctrl(struct dvobj_priv *d, enum _hw_port hwport,
2159                         struct rtw_halmac_bcn_ctrl *bcn_ctrl)
2160 {
2161         struct halmac_adapter *halmac;
2162         struct halmac_api *api;
2163         enum halmac_portid port;
2164         struct halmac_bcn_ctrl ctrl;
2165         enum halmac_ret_status status;
2166         int err = -1;
2167
2168
2169         halmac = dvobj_to_halmac(d);
2170         api = HALMAC_GET_API(halmac);
2171         port = _hw_port_drv2halmac(hwport);
2172         _rtw_memset(&ctrl, 0, sizeof(ctrl));
2173         _beacon_ctrl_drv2halmac(bcn_ctrl, &ctrl);
2174
2175         status = api->halmac_rw_bcn_ctrl(halmac, port, 1, &ctrl);
2176         if (status != HALMAC_RET_SUCCESS)
2177                 goto out;
2178
2179         err = 0;
2180 out:
2181         return err;
2182 }
2183
2184 /**
2185  * rtw_halmac_set_aid() - Set association identifier(AID) of specific port
2186  * @d:          struct dvobj_priv*
2187  * @hwport:     port
2188  * @aid:        Association identifier
2189  *
2190  * Set association identifier(AID) of specific port to HALMAC.
2191  *
2192  * Rteurn 0 for OK, otherwise fail.
2193  */
2194 int rtw_halmac_set_aid(struct dvobj_priv *d, enum _hw_port hwport, u16 aid)
2195 {
2196         struct halmac_adapter *halmac;
2197         struct halmac_api *api;
2198         enum halmac_portid port;
2199         enum halmac_ret_status status;
2200         int err = -1;
2201
2202
2203         halmac = dvobj_to_halmac(d);
2204         api = HALMAC_GET_API(halmac);
2205         port = _hw_port_drv2halmac(hwport);
2206
2207 #if 0
2208         status = api->halmac_cfg_aid(halmac, port, aid);
2209         if (status != HALMAC_RET_SUCCESS)
2210                 goto out;
2211 #else
2212 {
2213         struct _ADAPTER *a;
2214         u32 addr;
2215         u16 val;
2216
2217         a = dvobj_get_primary_adapter(d);
2218
2219         switch (port) {
2220         case 0:
2221                 addr = REG_BCN_PSR_RPT;
2222                 val = rtw_read16(a, addr);
2223                 val = BIT_SET_PS_AID_0(val, aid);
2224                 rtw_write16(a, addr, val);
2225                 break;
2226
2227         case 1:
2228                 addr = REG_BCN_PSR_RPT1;
2229                 val = rtw_read16(a, addr);
2230                 val = BIT_SET_PS_AID_1(val, aid);
2231                 rtw_write16(a, addr, val);
2232                 break;
2233
2234         case 2:
2235                 addr = REG_BCN_PSR_RPT2;
2236                 val = rtw_read16(a, addr);
2237                 val = BIT_SET_PS_AID_2(val, aid);
2238                 rtw_write16(a, addr, val);
2239                 break;
2240
2241         case 3:
2242                 addr = REG_BCN_PSR_RPT3;
2243                 val = rtw_read16(a, addr);
2244                 val = BIT_SET_PS_AID_3(val, aid);
2245                 rtw_write16(a, addr, val);
2246                 break;
2247
2248         case 4:
2249                 addr = REG_BCN_PSR_RPT4;
2250                 val = rtw_read16(a, addr);
2251                 val = BIT_SET_PS_AID_4(val, aid);
2252                 rtw_write16(a, addr, val);
2253                 break;
2254
2255         default:
2256                 goto out;
2257         }
2258 }
2259 #endif
2260
2261         err = 0;
2262 out:
2263         return err;
2264 }
2265
2266 int rtw_halmac_set_bandwidth(struct dvobj_priv *d, u8 channel, u8 pri_ch_idx, u8 bw)
2267 {
2268         struct halmac_adapter *mac;
2269         struct halmac_api *api;
2270         enum halmac_ret_status status;
2271
2272
2273         mac = dvobj_to_halmac(d);
2274         api = HALMAC_GET_API(mac);
2275
2276         status = api->halmac_cfg_ch_bw(mac, channel, pri_ch_idx, bw);
2277         if (HALMAC_RET_SUCCESS != status)
2278                 return -1;
2279
2280         return 0;
2281 }
2282
2283 /**
2284  * rtw_halmac_set_edca() - config edca parameter
2285  * @d:          struct dvobj_priv*
2286  * @queue:      XMIT_[VO/VI/BE/BK]_QUEUE
2287  * @aifs:       Arbitration inter-frame space(AIFS)
2288  * @cw:         Contention window(CW)
2289  * @txop:       MAX Transmit Opportunity(TXOP)
2290  *
2291  * Return: 0 if process OK, otherwise -1.
2292  */
2293 int rtw_halmac_set_edca(struct dvobj_priv *d, u8 queue, u8 aifs, u8 cw, u16 txop)
2294 {
2295         struct halmac_adapter *mac;
2296         struct halmac_api *api;
2297         enum halmac_acq_id ac;
2298         struct halmac_edca_para edca;
2299         enum halmac_ret_status status;
2300
2301
2302         mac = dvobj_to_halmac(d);
2303         api = HALMAC_GET_API(mac);
2304
2305         switch (queue) {
2306         case XMIT_VO_QUEUE:
2307                 ac = HALMAC_ACQ_ID_VO;
2308                 break;
2309         case XMIT_VI_QUEUE:
2310                 ac = HALMAC_ACQ_ID_VI;
2311                 break;
2312         case XMIT_BE_QUEUE:
2313                 ac = HALMAC_ACQ_ID_BE;
2314                 break;
2315         case XMIT_BK_QUEUE:
2316                 ac = HALMAC_ACQ_ID_BK;
2317                 break;
2318         default:
2319                 return -1;
2320         }
2321
2322         edca.aifs = aifs;
2323         edca.cw = cw;
2324         edca.txop_limit = txop;
2325
2326         status = api->halmac_cfg_edca_para(mac, ac, &edca);
2327         if (status != HALMAC_RET_SUCCESS)
2328                 return -1;
2329
2330         return 0;
2331 }
2332
2333 /**
2334  * rtw_halmac_set_rts_full_bw() - Send RTS to all covered channels
2335  * @d:          struct dvobj_priv*
2336  * @enable:     _TRUE(enable), _FALSE(disable)
2337  *
2338  * Hradware will duplicate RTS packet to all channels which are covered in used
2339  * bandwidth.
2340  *
2341  * Return 0 if process OK, otherwise -1.
2342  */
2343 int rtw_halmac_set_rts_full_bw(struct dvobj_priv *d, u8 enable)
2344 {
2345         struct halmac_adapter *mac;
2346         struct halmac_api *api;
2347         enum halmac_ret_status status;
2348         u8 full;
2349
2350
2351         mac = dvobj_to_halmac(d);
2352         api = HALMAC_GET_API(mac);
2353         full = (enable == _TRUE) ? 1 : 0;
2354
2355         status = api->halmac_set_hw_value(mac, HALMAC_HW_RTS_FULL_BW, &full);
2356         if (HALMAC_RET_SUCCESS != status)
2357                 return -1;
2358
2359         return 0;
2360 }
2361
2362 #ifdef RTW_HALMAC_DBG_POWER_SWITCH
2363 static void _dump_mac_reg(struct dvobj_priv *d, u32 start, u32 end)
2364 {
2365         struct _ADAPTER *adapter;
2366         int i, j = 1;
2367
2368
2369         adapter = dvobj_get_primary_adapter(d);
2370         for (i = start; i < end; i += 4) {
2371                 if (j % 4 == 1)
2372                         RTW_PRINT("0x%04x", i);
2373                 _RTW_PRINT(" 0x%08x ", rtw_read32(adapter, i));
2374                 if ((j++) % 4 == 0)
2375                         _RTW_PRINT("\n");
2376         }
2377 }
2378
2379 void dump_dbg_val(struct _ADAPTER *a, u32 reg)
2380 {
2381         u32 v32;
2382
2383
2384         rtw_write8(a, 0x3A, reg);
2385         v32 = rtw_read32(a, 0xC0);
2386         RTW_PRINT("0x3A = %02x, 0xC0 = 0x%08x\n",reg, v32);
2387 }
2388
2389 #ifdef CONFIG_PCI_HCI
2390 static void _dump_pcie_cfg_space(struct dvobj_priv *d)
2391 {
2392         struct _ADAPTER *padapter = dvobj_get_primary_adapter(d);
2393         struct dvobj_priv       *pdvobjpriv = adapter_to_dvobj(padapter);
2394         struct pci_dev  *pdev = pdvobjpriv->ppcidev;
2395         struct pci_dev  *bridge_pdev = pdev->bus->self;
2396
2397         u32 tmp[4] = { 0 };
2398         u32 i, j;
2399
2400         RTW_PRINT("\n*****  PCI Device Configuration Space *****\n\n");
2401
2402         for(i = 0; i < 0x100; i += 0x10)
2403         {
2404                 for (j = 0 ; j < 4 ; j++)
2405                         pci_read_config_dword(pdev, i + j * 4, tmp+j);
2406
2407                 RTW_PRINT("%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2408                         i, tmp[0] & 0xFF, (tmp[0] >> 8) & 0xFF, (tmp[0] >> 16) & 0xFF, (tmp[0] >> 24) & 0xFF,
2409                         tmp[1] & 0xFF, (tmp[1] >> 8) & 0xFF, (tmp[1] >> 16) & 0xFF, (tmp[1] >> 24) & 0xFF,
2410                         tmp[2] & 0xFF, (tmp[2] >> 8) & 0xFF, (tmp[2] >> 16) & 0xFF, (tmp[2] >> 24) & 0xFF,
2411                         tmp[3] & 0xFF, (tmp[3] >> 8) & 0xFF, (tmp[3] >> 16) & 0xFF, (tmp[3] >> 24) & 0xFF);
2412         }
2413
2414         RTW_PRINT("\n*****  PCI Host Device Configuration Space*****\n\n");
2415
2416         for(i = 0; i < 0x100; i += 0x10)
2417         {
2418                 for (j = 0 ; j < 4 ; j++)
2419                         pci_read_config_dword(bridge_pdev, i + j * 4, tmp+j);
2420
2421                 RTW_PRINT("%03x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
2422                         i, tmp[0] & 0xFF, (tmp[0] >> 8) & 0xFF, (tmp[0] >> 16) & 0xFF, (tmp[0] >> 24) & 0xFF,
2423                         tmp[1] & 0xFF, (tmp[1] >> 8) & 0xFF, (tmp[1] >> 16) & 0xFF, (tmp[1] >> 24) & 0xFF,
2424                         tmp[2] & 0xFF, (tmp[2] >> 8) & 0xFF, (tmp[2] >> 16) & 0xFF, (tmp[2] >> 24) & 0xFF,
2425                         tmp[3] & 0xFF, (tmp[3] >> 8) & 0xFF, (tmp[3] >> 16) & 0xFF, (tmp[3] >> 24) & 0xFF);
2426         }
2427 }
2428 #endif
2429
2430 static void _dump_mac_reg_for_power_switch(struct dvobj_priv *d,
2431                                            const char* caller, char* desc)
2432 {
2433         struct _ADAPTER *a;
2434         u8 v8;
2435
2436
2437         RTW_PRINT("%s: %s\n", caller, desc);
2438         RTW_PRINT("======= MAC REG =======\n");
2439         /* page 0/1 */
2440         _dump_mac_reg(d, 0x0, 0x200);
2441         _dump_mac_reg(d, 0x300, 0x400); /* also dump page 3 */
2442
2443         /* dump debug register */
2444         a = dvobj_get_primary_adapter(d);
2445
2446 #ifdef CONFIG_PCI_HCI
2447         _dump_pcie_cfg_space(d);
2448
2449         v8 = rtw_read8(a, 0xF6) | 0x01;
2450         rtw_write8(a, 0xF6, v8);
2451         RTW_PRINT("0xF6 = %02x\n", v8);
2452
2453         dump_dbg_val(a, 0x63);
2454         dump_dbg_val(a, 0x64);
2455         dump_dbg_val(a, 0x68);
2456         dump_dbg_val(a, 0x69);
2457         dump_dbg_val(a, 0x6a);
2458         dump_dbg_val(a, 0x6b);
2459         dump_dbg_val(a, 0x71);
2460         dump_dbg_val(a, 0x72);
2461 #endif
2462 }
2463
2464 static enum halmac_ret_status _power_switch(struct halmac_adapter *halmac,
2465                                             struct halmac_api *api,
2466                                             enum halmac_mac_power pwr)
2467 {
2468         enum halmac_ret_status status;
2469         char desc[80] = {0};
2470
2471
2472         rtw_sprintf(desc, 80, "before calling power %s",
2473                                 (pwr==HALMAC_MAC_POWER_ON)?"on":"off");
2474         _dump_mac_reg_for_power_switch((struct dvobj_priv *)halmac->drv_adapter,
2475                         __FUNCTION__, desc);
2476
2477         status = api->halmac_mac_power_switch(halmac, pwr);
2478         RTW_PRINT("%s: status=%d\n", __FUNCTION__, status);
2479
2480         rtw_sprintf(desc, 80, "after calling power %s",
2481                                 (pwr==HALMAC_MAC_POWER_ON)?"on":"off");
2482         _dump_mac_reg_for_power_switch((struct dvobj_priv *)halmac->drv_adapter,
2483                         __FUNCTION__, desc);
2484
2485         return status;
2486 }
2487 #else /* !RTW_HALMAC_DBG_POWER_SWITCH */
2488 #define _power_switch(mac, api, pwr)    (api)->halmac_mac_power_switch(mac, pwr)
2489 #endif /* !RTW_HALMAC_DBG_POWER_SWITCH */
2490
2491 /*
2492  * Description:
2493  *      Power on device hardware.
2494  *      [Notice!] If device's power state is on before,
2495  *      it would be power off first and turn on power again.
2496  *
2497  * Return:
2498  *      0       power on success
2499  *      -1      power on fail
2500  *      -2      power state unchange
2501  */
2502 int rtw_halmac_poweron(struct dvobj_priv *d)
2503 {
2504         struct halmac_adapter *halmac;
2505         struct halmac_api *api;
2506         enum halmac_ret_status status;
2507         int err = -1;
2508 #if defined(CONFIG_PCI_HCI) && defined(CONFIG_RTL8822B)
2509         struct _ADAPTER *a;
2510         u8 v8;
2511         u32 addr;
2512
2513         a = dvobj_get_primary_adapter(d);
2514 #endif
2515
2516         halmac = dvobj_to_halmac(d);
2517         if (!halmac)
2518                 goto out;
2519
2520         api = HALMAC_GET_API(halmac);
2521
2522         status = api->halmac_pre_init_system_cfg(halmac);
2523         if (status != HALMAC_RET_SUCCESS)
2524                 goto out;
2525
2526 #ifdef CONFIG_SDIO_HCI
2527         status = api->halmac_sdio_cmd53_4byte(halmac, HALMAC_SDIO_CMD53_4BYTE_MODE_RW);
2528         if (status != HALMAC_RET_SUCCESS)
2529                 goto out;
2530 #endif /* CONFIG_SDIO_HCI */
2531
2532 #if defined(CONFIG_PCI_HCI) && defined(CONFIG_RTL8822B)
2533         addr = 0x3F3;
2534         v8 = rtw_read8(a, addr);
2535         RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2536         /* are we in pcie debug mode? */
2537         if (!(v8 & BIT(2))) {
2538                 RTW_PRINT("%s: Enable pcie debug mode\n", __FUNCTION__);
2539                 v8 |= BIT(2);
2540                 v8 = rtw_write8(a, addr, v8);
2541         }
2542 #endif
2543
2544         status = _power_switch(halmac, api, HALMAC_MAC_POWER_ON);
2545         if (HALMAC_RET_PWR_UNCHANGE == status) {
2546
2547 #if defined(CONFIG_PCI_HCI) && defined(CONFIG_RTL8822B)
2548                 addr = 0x3F3;
2549                 v8 = rtw_read8(a, addr);
2550                 RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2551
2552                 /* are we in pcie debug mode? */
2553                 if (!(v8 & BIT(2))) {
2554                         RTW_PRINT("%s: Enable pcie debug mode\n", __FUNCTION__);
2555                         v8 |= BIT(2);
2556                         v8 = rtw_write8(a, addr, v8);
2557                 } else if (v8 & BIT(0)) {
2558                         /* DMA stuck */
2559                         addr = 0x1350;
2560                         v8 = rtw_read8(a, addr);
2561                         RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2562                         RTW_PRINT("%s: recover DMA stuck\n", __FUNCTION__);
2563                         v8 |= BIT(6);
2564                         v8 = rtw_write8(a, addr, v8);
2565                         RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v8);
2566                 }
2567 #endif
2568                 /*
2569                  * Work around for warm reboot but device not power off,
2570                  * but it would also fall into this case when auto power on is enabled.
2571                  */
2572                 _power_switch(halmac, api, HALMAC_MAC_POWER_OFF);
2573                 status = _power_switch(halmac, api, HALMAC_MAC_POWER_ON);
2574                 RTW_WARN("%s: Power state abnormal, try to recover...%s\n",
2575                          __FUNCTION__, (HALMAC_RET_SUCCESS == status)?"OK":"FAIL!");
2576         }
2577         if (HALMAC_RET_SUCCESS != status) {
2578                 if (HALMAC_RET_PWR_UNCHANGE == status)
2579                         err = -2;
2580                 goto out;
2581         }
2582
2583         status = api->halmac_init_system_cfg(halmac);
2584         if (status != HALMAC_RET_SUCCESS)
2585                 goto out;
2586
2587         err = 0;
2588 out:
2589         return err;
2590 }
2591
2592 /*
2593  * Description:
2594  *      Power off device hardware.
2595  *
2596  * Return:
2597  *      0       Power off success
2598  *      -1      Power off fail
2599  */
2600 int rtw_halmac_poweroff(struct dvobj_priv *d)
2601 {
2602         struct halmac_adapter *halmac;
2603         struct halmac_api *api;
2604         enum halmac_ret_status status;
2605         int err = -1;
2606
2607
2608         halmac = dvobj_to_halmac(d);
2609         if (!halmac)
2610                 goto out;
2611
2612         api = HALMAC_GET_API(halmac);
2613
2614         status = _power_switch(halmac, api, HALMAC_MAC_POWER_OFF);
2615         if ((HALMAC_RET_SUCCESS != status)
2616             && (HALMAC_RET_PWR_UNCHANGE != status))
2617                 goto out;
2618
2619         err = 0;
2620 out:
2621         return err;
2622 }
2623
2624 #ifdef CONFIG_SUPPORT_TRX_SHARED
2625 static inline enum halmac_rx_fifo_expanding_mode _trx_share_mode_drv2halmac(u8 trx_share_mode)
2626 {
2627         if (0 == trx_share_mode)
2628                 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
2629         else if (1 == trx_share_mode)
2630                 return HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK;
2631         else if (2 == trx_share_mode)
2632                 return HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK;
2633         else if (3 == trx_share_mode)
2634                 return HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK;
2635         else
2636                 return HALMAC_RX_FIFO_EXPANDING_MODE_DISABLE;
2637 }
2638
2639 static enum halmac_rx_fifo_expanding_mode _rtw_get_trx_share_mode(struct _ADAPTER *adapter)
2640 {
2641         struct registry_priv *registry_par = &adapter->registrypriv;
2642
2643         return _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
2644 }
2645
2646 void dump_trx_share_mode(void *sel, struct _ADAPTER *adapter)
2647 {
2648         struct registry_priv  *registry_par = &adapter->registrypriv;
2649         u8 mode = _trx_share_mode_drv2halmac(registry_par->trx_share_mode);
2650
2651         if (HALMAC_RX_FIFO_EXPANDING_MODE_1_BLOCK == mode)
2652                 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_1");
2653         else if (HALMAC_RX_FIFO_EXPANDING_MODE_2_BLOCK == mode)
2654                 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_2");
2655         else if (HALMAC_RX_FIFO_EXPANDING_MODE_3_BLOCK == mode)
2656                 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "RX_FIFO_EXPANDING_MODE_3");
2657         else
2658                 RTW_PRINT_SEL(sel, "TRx share mode : %s\n", "DISABLE");
2659 }
2660 #endif
2661
2662 static enum halmac_drv_rsvd_pg_num _rsvd_page_num_drv2halmac(u8 num)
2663 {
2664         if (num <= 8)
2665                 return HALMAC_RSVD_PG_NUM8;
2666         if (num <= 16)
2667                 return HALMAC_RSVD_PG_NUM16;
2668         if (num <= 24)
2669                 return HALMAC_RSVD_PG_NUM24;
2670         if (num <= 32)
2671                 return HALMAC_RSVD_PG_NUM32;
2672         if (num <= 64)
2673                 return HALMAC_RSVD_PG_NUM64;
2674
2675         if (num > 128)
2676                 RTW_WARN("%s: Fail to allocate RSVD page(%d)!!"
2677                          " The MAX RSVD page number is 128...\n",
2678                          __FUNCTION__, num);
2679
2680         return HALMAC_RSVD_PG_NUM128;
2681 }
2682
2683 static u8 _rsvd_page_num_halmac2drv(enum halmac_drv_rsvd_pg_num rsvd_page_number)
2684 {
2685         u8 num = 0;
2686
2687
2688         switch (rsvd_page_number) {
2689         case HALMAC_RSVD_PG_NUM8:
2690                 num = 8;
2691                 break;
2692
2693         case HALMAC_RSVD_PG_NUM16:
2694                 num = 16;
2695                 break;
2696
2697         case HALMAC_RSVD_PG_NUM24:
2698                 num = 24;
2699                 break;
2700
2701         case HALMAC_RSVD_PG_NUM32:
2702                 num = 32;
2703                 break;
2704
2705         case HALMAC_RSVD_PG_NUM64:
2706                 num = 64;
2707                 break;
2708
2709         case HALMAC_RSVD_PG_NUM128:
2710                 num = 128;
2711                 break;
2712         }
2713
2714         return num;
2715 }
2716
2717 static enum halmac_trx_mode _choose_trx_mode(struct dvobj_priv *d)
2718 {
2719         PADAPTER p;
2720
2721
2722         p = dvobj_get_primary_adapter(d);
2723
2724         if (p->registrypriv.wifi_spec)
2725                 return HALMAC_TRX_MODE_WMM;
2726
2727 #ifdef CONFIG_SUPPORT_TRX_SHARED
2728         if (_rtw_get_trx_share_mode(p))
2729                 return HALMAC_TRX_MODE_TRXSHARE;
2730 #endif
2731
2732         return HALMAC_TRX_MODE_NORMAL;
2733 }
2734
2735 static inline enum halmac_rf_type _rf_type_drv2halmac(enum rf_type rf_drv)
2736 {
2737         enum halmac_rf_type rf_mac;
2738
2739
2740         switch (rf_drv) {
2741         case RF_1T1R:
2742                 rf_mac = HALMAC_RF_1T1R;
2743                 break;
2744         case RF_1T2R:
2745                 rf_mac = HALMAC_RF_1T2R;
2746                 break;
2747         case RF_2T2R:
2748                 rf_mac = HALMAC_RF_2T2R;
2749                 break;
2750         case RF_2T3R:
2751                 rf_mac = HALMAC_RF_2T3R;
2752                 break;
2753         case RF_2T4R:
2754                 rf_mac = HALMAC_RF_2T4R;
2755                 break;
2756         case RF_3T3R:
2757                 rf_mac = HALMAC_RF_3T3R;
2758                 break;
2759         case RF_3T4R:
2760                 rf_mac = HALMAC_RF_3T4R;
2761                 break;
2762         case RF_4T4R:
2763                 rf_mac = HALMAC_RF_4T4R;
2764                 break;
2765         default:
2766                 rf_mac = HALMAC_RF_MAX_TYPE;
2767                 RTW_ERR("%s: Invalid RF type(0x%x)!\n", __FUNCTION__, rf_drv);
2768                 break;
2769         }
2770
2771         return rf_mac;
2772 }
2773
2774 static inline enum rf_type _rf_type_halmac2drv(enum halmac_rf_type rf_mac)
2775 {
2776         enum rf_type rf_drv;
2777
2778
2779         switch (rf_mac) {
2780         case HALMAC_RF_1T2R:
2781                 rf_drv = RF_1T2R;
2782                 break;
2783         case HALMAC_RF_2T4R:
2784                 rf_drv = RF_2T4R;
2785                 break;
2786         case HALMAC_RF_2T2R:
2787         case HALMAC_RF_2T2R_GREEN:
2788                 rf_drv = RF_2T2R;
2789                 break;
2790         case HALMAC_RF_2T3R:
2791                 rf_drv = RF_2T3R;
2792                 break;
2793         case HALMAC_RF_1T1R:
2794                 rf_drv = RF_1T1R;
2795                 break;
2796         case HALMAC_RF_3T3R:
2797                 rf_drv = RF_3T3R;
2798                 break;
2799         case HALMAC_RF_3T4R:
2800                 rf_drv = RF_3T4R;
2801                 break;
2802         case HALMAC_RF_4T4R:
2803                 rf_drv = RF_4T4R;
2804                 break;
2805         default:
2806                 rf_drv = RF_TYPE_MAX;
2807                 RTW_ERR("%s: Invalid RF type(0x%x)!\n", __FUNCTION__, rf_mac);
2808                 break;
2809         }
2810
2811         return rf_drv;
2812 }
2813
2814 static enum odm_cut_version _cut_version_drv2phydm(
2815                                 enum tag_HAL_Cut_Version_Definition cut_drv)
2816 {
2817         enum odm_cut_version cut_phydm = ODM_CUT_A;
2818         u32 diff;
2819
2820
2821         if (cut_drv > K_CUT_VERSION)
2822                 RTW_WARN("%s: unknown cut_ver=%d !!\n", __FUNCTION__, cut_drv);
2823
2824         diff = cut_drv - A_CUT_VERSION;
2825         cut_phydm += diff;
2826
2827         return cut_phydm;
2828 }
2829
2830 static int _send_general_info_by_reg(struct dvobj_priv *d,
2831                                      struct halmac_general_info *info)
2832 {
2833         struct _ADAPTER *a;
2834         struct hal_com_data *hal;
2835         enum tag_HAL_Cut_Version_Definition cut_drv;
2836         enum rf_type rftype;
2837         enum odm_cut_version cut_phydm;
2838         u8 h2c[RTW_HALMAC_H2C_MAX_SIZE] = {0};
2839
2840
2841         a = dvobj_get_primary_adapter(d);
2842         hal = GET_HAL_DATA(a);
2843         rftype = _rf_type_halmac2drv(info->rf_type);
2844         cut_drv = GET_CVID_CUT_VERSION(hal->version_id);
2845         cut_phydm = _cut_version_drv2phydm(cut_drv);
2846
2847 #define CLASS_GENERAL_INFO_REG                          0x02
2848 #define CMD_ID_GENERAL_INFO_REG                         0x0C
2849 #define GENERAL_INFO_REG_SET_CMD_ID(buf, v)             SET_BITS_TO_LE_4BYTE(buf, 0, 5, v)
2850 #define GENERAL_INFO_REG_SET_CLASS(buf, v)              SET_BITS_TO_LE_4BYTE(buf, 5, 3, v)
2851 #define GENERAL_INFO_REG_SET_RFE_TYPE(buf, v)           SET_BITS_TO_LE_4BYTE(buf, 8, 8, v)
2852 #define GENERAL_INFO_REG_SET_RF_TYPE(buf, v)            SET_BITS_TO_LE_4BYTE(buf, 16, 8, v)
2853 #define GENERAL_INFO_REG_SET_CUT_VERSION(buf, v)        SET_BITS_TO_LE_4BYTE(buf, 24, 8, v)
2854 #define GENERAL_INFO_REG_SET_RX_ANT_STATUS(buf, v)      SET_BITS_TO_LE_1BYTE(buf+4, 0, 4, v)
2855 #define GENERAL_INFO_REG_SET_TX_ANT_STATUS(buf, v)      SET_BITS_TO_LE_1BYTE(buf+4, 4, 4, v)
2856
2857         GENERAL_INFO_REG_SET_CMD_ID(h2c, CMD_ID_GENERAL_INFO_REG);
2858         GENERAL_INFO_REG_SET_CLASS(h2c, CLASS_GENERAL_INFO_REG);
2859         GENERAL_INFO_REG_SET_RFE_TYPE(h2c, info->rfe_type);
2860         GENERAL_INFO_REG_SET_RF_TYPE(h2c, rftype);
2861         GENERAL_INFO_REG_SET_CUT_VERSION(h2c, cut_phydm);
2862         GENERAL_INFO_REG_SET_RX_ANT_STATUS(h2c, info->rx_ant_status);
2863         GENERAL_INFO_REG_SET_TX_ANT_STATUS(h2c, info->tx_ant_status);
2864
2865         return rtw_halmac_send_h2c(d, h2c);
2866 }
2867
2868 static int _send_general_info(struct dvobj_priv *d)
2869 {
2870         struct _ADAPTER *adapter;
2871         struct hal_com_data *hal;
2872         struct halmac_adapter *halmac;
2873         struct halmac_api *api;
2874         struct halmac_general_info info;
2875         enum halmac_ret_status status;
2876         enum rf_type rf = RF_1T1R;
2877         enum bb_path txpath = BB_PATH_A;
2878         enum bb_path rxpath = BB_PATH_A;
2879         int err;
2880
2881
2882         adapter = dvobj_get_primary_adapter(d);
2883         hal = GET_HAL_DATA(adapter);
2884         halmac = dvobj_to_halmac(d);
2885         if (!halmac)
2886                 return -1;
2887         api = HALMAC_GET_API(halmac);
2888
2889         _rtw_memset(&info, 0, sizeof(info));
2890         info.rfe_type = (u8)hal->rfe_type;
2891         rtw_hal_get_rf_path(d, &rf, &txpath, &rxpath);
2892         info.rf_type = _rf_type_drv2halmac(rf);
2893         info.tx_ant_status = (u8)txpath;
2894         info.rx_ant_status = (u8)rxpath;
2895
2896         status = api->halmac_send_general_info(halmac, &info);
2897         switch (status) {
2898         case HALMAC_RET_SUCCESS:
2899                 break;
2900         case HALMAC_RET_NO_DLFW:
2901                 RTW_WARN("%s: halmac_send_general_info() fail because fw not dl!\n",
2902                          __FUNCTION__);
2903                 __attribute__((__fallthrough__));
2904         default:
2905                 return -1;
2906         }
2907
2908         err = _send_general_info_by_reg(d, &info);
2909         if (err) {
2910                 RTW_ERR("%s: Fail to send general info by register!\n",
2911                          __FUNCTION__);
2912                 return -1;
2913         }
2914
2915         return 0;
2916 }
2917
2918 static int _cfg_drv_rsvd_pg_num(struct dvobj_priv *d)
2919 {
2920         struct _ADAPTER *a;
2921         struct hal_com_data *hal;
2922         struct halmac_adapter *halmac;
2923         struct halmac_api *api;
2924         enum halmac_drv_rsvd_pg_num rsvd_page_number;
2925         enum halmac_ret_status status;
2926         u8 drv_rsvd_num;
2927
2928
2929         a = dvobj_get_primary_adapter(d);
2930         hal = GET_HAL_DATA(a);
2931         halmac = dvobj_to_halmac(d);
2932         api = HALMAC_GET_API(halmac);
2933
2934         drv_rsvd_num = rtw_hal_get_rsvd_page_num(a);
2935         rsvd_page_number = _rsvd_page_num_drv2halmac(drv_rsvd_num);
2936         status = api->halmac_cfg_drv_rsvd_pg_num(halmac, rsvd_page_number);
2937         if (status != HALMAC_RET_SUCCESS)
2938                 return -1;
2939         hal->drv_rsvd_page_number = _rsvd_page_num_halmac2drv(rsvd_page_number);
2940
2941         if (drv_rsvd_num != hal->drv_rsvd_page_number)
2942                 RTW_INFO("%s: request %d pages, but allocate %d pages\n",
2943                          __FUNCTION__, drv_rsvd_num, hal->drv_rsvd_page_number);
2944
2945         return 0;
2946 }
2947
2948 static void _debug_dlfw_fail(struct dvobj_priv *d)
2949 {
2950         struct _ADAPTER *a;
2951         u32 addr;
2952         u32 v32, i, n;
2953         u8 data[0x100] = {0};
2954
2955
2956         a = dvobj_get_primary_adapter(d);
2957
2958         /* read 0x80[15:0], 0x10F8[31:0] once */
2959         addr = 0x80;
2960         v32 = rtw_read16(a, addr);
2961         RTW_PRINT("%s: 0x%X = 0x%04x\n", __FUNCTION__, addr, v32);
2962
2963         addr = 0x10F8;
2964         v32 = rtw_read32(a, addr);
2965         RTW_PRINT("%s: 0x%X = 0x%08x\n", __FUNCTION__, addr, v32);
2966
2967         /* read 0x10FC[31:0], 5 times */
2968         addr = 0x10FC;
2969         n = 5;
2970         for (i = 0; i < n; i++) {
2971                 v32 = rtw_read32(a, addr);
2972                 RTW_PRINT("%s: 0x%X = 0x%08x (%u/%u)\n",
2973                           __FUNCTION__, addr, v32, i, n);
2974         }
2975
2976         /*
2977          * write 0x3A[7:0]=0x28 and 0xF6[7:0]=0x01
2978          * and then read 0xC0[31:0] 5 times
2979          */
2980         addr = 0x3A;
2981         v32 = 0x28;
2982         rtw_write8(a, addr, (u8)v32);
2983         v32 = rtw_read8(a, addr);
2984         RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v32);
2985
2986         addr = 0xF6;
2987         v32 = 0x1;
2988         rtw_write8(a, addr, (u8)v32);
2989         v32 = rtw_read8(a, addr);
2990         RTW_PRINT("%s: 0x%X = 0x%02x\n", __FUNCTION__, addr, v32);
2991
2992         addr = 0xC0;
2993         n = 5;
2994         for (i = 0; i < n; i++) {
2995                 v32 = rtw_read32(a, addr);
2996                 RTW_PRINT("%s: 0x%X = 0x%08x (%u/%u)\n",
2997                           __FUNCTION__, addr, v32, i, n);
2998         }
2999
3000         /* 0x00~0xFF, 0x1000~0x10FF */
3001         addr = 0;
3002         n = 0x100;
3003         for (i = 0; i < n; i+=4)
3004                 *(u32*)&data[i] = cpu_to_le32(rtw_read32(a, addr+i));
3005         for (i = 0; i < n; i++) {
3006                 if (i % 16 == 0)
3007                         RTW_PRINT("0x%04x\t", addr+i);
3008                 _RTW_PRINT("0x%02x", data[i]);
3009                 if (i % 16 == 15)
3010                         _RTW_PRINT("\n");
3011                 else
3012                         _RTW_PRINT(" ");
3013         }
3014
3015         addr = 0x1000;
3016         n = 0x100;
3017         for (i = 0; i < n; i+=4)
3018                 *(u32*)&data[i] = cpu_to_le32(rtw_read32(a, addr+i));
3019         for (i = 0; i < n; i++) {
3020                 if (i % 16 == 0)
3021                         RTW_PRINT("0x%04x\t", addr+i);
3022                 _RTW_PRINT("0x%02x", data[i]);
3023                 if (i % 16 == 15)
3024                         _RTW_PRINT("\n");
3025                 else
3026                         _RTW_PRINT(" ");
3027         }
3028
3029         /* read 0x80 after 10 secs */
3030         rtw_msleep_os(10000);
3031         addr = 0x80;
3032         v32 = rtw_read16(a, addr);
3033         RTW_PRINT("%s: 0x%X = 0x%04x (after 10 secs)\n",
3034                   __FUNCTION__, addr, v32);
3035 }
3036
3037 static enum halmac_ret_status _enter_cpu_sleep_mode(struct dvobj_priv *d)
3038 {
3039         struct hal_com_data *hal;
3040         struct halmac_adapter *mac;
3041         struct halmac_api *api;
3042
3043
3044         hal = GET_HAL_DATA(dvobj_get_primary_adapter(d));
3045         mac = dvobj_to_halmac(d);
3046         api = HALMAC_GET_API(mac);
3047
3048 #ifdef CONFIG_RTL8822B
3049         /* Support after firmware version 21 */
3050         if (hal->firmware_version < 21)
3051                 return HALMAC_RET_NOT_SUPPORT;
3052 #elif defined(CONFIG_RTL8821C)
3053         /* Support after firmware version 13.6 or 16 */
3054         if (hal->firmware_version == 13) {
3055                 if (hal->firmware_sub_version < 6)
3056                         return HALMAC_RET_NOT_SUPPORT;
3057         } else if (hal->firmware_version < 16) {
3058                 return HALMAC_RET_NOT_SUPPORT;
3059         }
3060 #endif
3061
3062         return api->halmac_enter_cpu_sleep_mode(mac);
3063 }
3064
3065 /*
3066  * _cpu_sleep() - Let IC CPU enter sleep mode
3067  * @d:          struct dvobj_priv*
3068  * @timeout:    time limit of wait, unit is ms
3069  *              0 for no limit
3070  *
3071  * Rteurn 0 for CPU in sleep mode, otherwise fail to enter sleep mode.
3072  * Error codes definition are as follow:
3073  *      -1      HALMAC enter sleep return fail
3074  *      -2      HALMAC get CPU mode return fail
3075  *      -110    timeout
3076  */
3077 static int _cpu_sleep(struct dvobj_priv *d, u32 timeout)
3078 {
3079         struct halmac_adapter *mac;
3080         struct halmac_api *api;
3081         enum halmac_ret_status status;
3082         enum halmac_wlcpu_mode mode = HALMAC_WLCPU_UNDEFINE;
3083         systime start_t;
3084         s32 period = 0;
3085         u32 cnt = 0;
3086         int err = 0;
3087
3088
3089         mac = dvobj_to_halmac(d);
3090         api = HALMAC_GET_API(mac);
3091
3092         start_t = rtw_get_current_time();
3093
3094         status = _enter_cpu_sleep_mode(d);
3095         if (status != HALMAC_RET_SUCCESS) {
3096                 if (status != HALMAC_RET_NOT_SUPPORT)
3097                         err = -1;
3098                 goto exit;
3099         }
3100
3101         do {
3102                 cnt++;
3103
3104                 mode = HALMAC_WLCPU_UNDEFINE;
3105                 status = api->halmac_get_cpu_mode(mac, &mode);
3106
3107                 period = rtw_get_passing_time_ms(start_t);
3108
3109                 if (status != HALMAC_RET_SUCCESS) {
3110                         err = -2;
3111                         break;
3112                 }
3113                 if (mode == HALMAC_WLCPU_SLEEP)
3114                         break;
3115                 if (period > timeout) {
3116                         err = -110;
3117                         break;
3118                 }
3119
3120                 rtw_msleep_os(1);
3121         } while (1);
3122
3123 exit:
3124         if (err)
3125                 RTW_ERR("%s: Fail to enter sleep mode! (%d, %d)\n",
3126                         __FUNCTION__, status, mode);
3127
3128         RTW_INFO("%s: Cost %dms to polling %u times. (err=%d)\n",
3129                 __FUNCTION__, period, cnt, err);
3130
3131         return err;
3132 }
3133
3134 static void _init_trx_cfg_drv(struct dvobj_priv *d)
3135 {
3136 #ifdef CONFIG_PCI_HCI
3137         rtw_hal_irp_reset(dvobj_get_primary_adapter(d));
3138 #endif
3139 }
3140
3141 /*
3142  * Description:
3143  *      Downlaod Firmware Flow
3144  *
3145  * Parameters:
3146  *      d       pointer of struct dvobj_priv
3147  *      fw      firmware array
3148  *      fwsize  firmware size
3149  *      re_dl   re-download firmware or not
3150  *              0: run in init hal flow, not re-download
3151  *              1: it is a stand alone operation, not in init hal flow
3152  *
3153  * Return:
3154  *      0       Success
3155  *      others  Fail
3156  */
3157 static int download_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize, u8 re_dl)
3158 {
3159         PHAL_DATA_TYPE hal;
3160         struct halmac_adapter *mac;
3161         struct halmac_api *api;
3162         struct halmac_fw_version fw_vesion;
3163         enum halmac_ret_status status;
3164         int err = 0;
3165
3166
3167         hal = GET_HAL_DATA(dvobj_get_primary_adapter(d));
3168         mac = dvobj_to_halmac(d);
3169         api = HALMAC_GET_API(mac);
3170
3171         if ((!fw) || (!fwsize))
3172                 return -1;
3173
3174         /* 1. Driver Stop Tx */
3175         /* ToDo */
3176
3177         /* 2. Driver Check Tx FIFO is empty */
3178         err = rtw_halmac_txfifo_wait_empty(d, 2000); /* wait 2s */
3179         if (err) {
3180                 err = -1;
3181                 goto resume_tx;
3182         }
3183
3184         /* 3. Config MAX download size */
3185         /*
3186          * Already done in rtw_halmac_init_adapter() or
3187          * somewhere calling rtw_halmac_set_max_dl_fw_size().
3188          */
3189
3190         if (re_dl) {
3191                 /* 4. Enter IC CPU sleep mode */
3192                 err = _cpu_sleep(d, 2000);
3193                 if (err) {
3194                         RTW_ERR("%s: IC CPU fail to enter sleep mode!(%d)\n",
3195                                 __FUNCTION__, err);
3196                         /* skip this error */
3197                         err = 0;
3198                 }
3199         }
3200
3201         /* 5. Download Firmware */
3202         status = api->halmac_download_firmware(mac, fw, fwsize);
3203         if (status != HALMAC_RET_SUCCESS) {
3204                 RTW_ERR("%s: download firmware FAIL! status=0x%02x\n",
3205                         __FUNCTION__, status);
3206                 _debug_dlfw_fail(d);
3207                 err = -1;
3208                 goto resume_tx;
3209         }
3210
3211         /* 5.1. (Driver) Reset driver variables if needed */
3212         hal->LastHMEBoxNum = 0;
3213
3214         /* 5.2. (Driver) Get FW version */
3215         status = api->halmac_get_fw_version(mac, &fw_vesion);
3216         if (status == HALMAC_RET_SUCCESS) {
3217                 hal->firmware_version = fw_vesion.version;
3218                 hal->firmware_sub_version = fw_vesion.sub_version;
3219                 hal->firmware_size = fwsize;
3220         }
3221
3222 resume_tx:
3223         /* 6. Driver resume TX if needed */
3224         /* ToDo */
3225
3226         if (err)
3227                 goto exit;
3228
3229         if (re_dl) {
3230                 enum halmac_trx_mode mode;
3231
3232                 /* 7. Change reserved page size */
3233                 err = _cfg_drv_rsvd_pg_num(d);
3234                 if (err)
3235                         return -1;
3236
3237                 /* 8. Init TRX Configuration */
3238                 mode = _choose_trx_mode(d);
3239                 status = api->halmac_init_trx_cfg(mac, mode);
3240                 if (HALMAC_RET_SUCCESS != status)
3241                         return -1;
3242                 _init_trx_cfg_drv(d);
3243
3244                 /* 9. Config RX Aggregation */
3245                 err = rtw_halmac_rx_agg_switch(d, _TRUE);
3246                 if (err)
3247                         return -1;
3248
3249                 /* 10. Send General Info */
3250                 err = _send_general_info(d);
3251                 if (err)
3252                         return -1;
3253         }
3254
3255 exit:
3256         return err;
3257 }
3258
3259 static int init_mac_flow(struct dvobj_priv *d)
3260 {
3261         PADAPTER p;
3262         struct hal_com_data *hal;
3263         struct halmac_adapter *halmac;
3264         struct halmac_api *api;
3265         enum halmac_drv_rsvd_pg_num rsvd_page_number;
3266         union halmac_wlan_addr hwa;
3267         enum halmac_trx_mode trx_mode;
3268         enum halmac_ret_status status;
3269         u8 drv_rsvd_num;
3270         u8 nettype;
3271         int err, err_ret = -1;
3272
3273
3274         p = dvobj_get_primary_adapter(d);
3275         hal = GET_HAL_DATA(p);
3276         halmac = dvobj_to_halmac(d);
3277         api = HALMAC_GET_API(halmac);
3278
3279 #ifdef CONFIG_SUPPORT_TRX_SHARED
3280         status = api->halmac_cfg_rxff_expand_mode(halmac,
3281                                                   _rtw_get_trx_share_mode(p));
3282         if (status != HALMAC_RET_SUCCESS)
3283                 goto out;
3284 #endif
3285
3286 #if 0 /* It is not necessary to call this in normal driver */
3287         status = api->halmac_cfg_la_mode(halmac, HALMAC_LA_MODE_DISABLE);
3288         if (status != HALMAC_RET_SUCCESS)
3289                 goto out;
3290 #endif
3291
3292         err = _cfg_drv_rsvd_pg_num(d);
3293         if (err)
3294                 goto out;
3295
3296 #ifdef CONFIG_USB_HCI
3297         status = api->halmac_set_bulkout_num(halmac, d->RtNumOutPipes);
3298         if (status != HALMAC_RET_SUCCESS)
3299                 goto out;
3300 #endif /* CONFIG_USB_HCI */
3301
3302         trx_mode = _choose_trx_mode(d);
3303         status = api->halmac_init_mac_cfg(halmac, trx_mode);
3304         if (status != HALMAC_RET_SUCCESS)
3305                 goto out;
3306         _init_trx_cfg_drv(d);
3307
3308         err = rtw_halmac_rx_agg_switch(d, _TRUE);
3309         if (err)
3310                 goto out;
3311
3312         nettype = dvobj_to_regsty(d)->wireless_mode;
3313         if (is_supported_vht(nettype) == _TRUE)
3314                 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_AC);
3315         else if (is_supported_ht(nettype) == _TRUE)
3316                 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_N);
3317         else if (IsSupportedTxOFDM(nettype) == _TRUE)
3318                 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_G);
3319         else
3320                 status = api->halmac_cfg_operation_mode(halmac, HALMAC_WIRELESS_MODE_B);
3321         if (status != HALMAC_RET_SUCCESS)
3322                 goto out;
3323
3324         err_ret = 0;
3325 out:
3326         return err_ret;
3327 }
3328
3329 static int _drv_enable_trx(struct dvobj_priv *d)
3330 {
3331         struct _ADAPTER *adapter;
3332         u32 status;
3333
3334
3335         adapter = dvobj_get_primary_adapter(d);
3336         if (adapter->bup == _FALSE) {
3337 #ifdef CONFIG_NEW_NETDEV_HDL
3338                 status = rtw_mi_start_drv_threads(adapter);
3339 #else
3340                 status = rtw_start_drv_threads(adapter);
3341 #endif
3342                 if (status == _FAIL) {
3343                         RTW_ERR("%s: Start threads Failed!\n", __FUNCTION__);
3344                         return -1;
3345                 }
3346         }
3347
3348         rtw_intf_start(adapter);
3349
3350         return 0;
3351 }
3352
3353 /*
3354  * Notices:
3355  *      Make sure
3356  *      1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
3357  *      2. HAL_DATA_TYPE.rfe_type
3358  *      already ready for use before calling this function.
3359  */
3360 static int _halmac_init_hal(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3361 {
3362         PADAPTER adapter;
3363         struct halmac_adapter *halmac;
3364         struct halmac_api *api;
3365         enum halmac_ret_status status;
3366         u32 ok;
3367         u8 fw_ok = _FALSE;
3368         int err, err_ret = -1;
3369
3370
3371         adapter = dvobj_get_primary_adapter(d);
3372         halmac = dvobj_to_halmac(d);
3373         if (!halmac)
3374                 goto out;
3375         api = HALMAC_GET_API(halmac);
3376
3377         /* StatePowerOff */
3378
3379         /* SKIP: halmac_init_adapter (Already done before) */
3380
3381         /* halmac_pre_Init_system_cfg */
3382         /* halmac_mac_power_switch(on) */
3383         /* halmac_Init_system_cfg */
3384         ok = rtw_hal_power_on(adapter);
3385         if (_FAIL == ok)
3386                 goto out;
3387
3388         /* StatePowerOn */
3389
3390         /* DownloadFW */
3391         if (fw && fwsize) {
3392                 err = download_fw(d, fw, fwsize, 0);
3393                 if (err)
3394                         goto out;
3395                 fw_ok = _TRUE;
3396         }
3397
3398         /* InitMACFlow */
3399         err = init_mac_flow(d);
3400         if (err)
3401                 goto out;
3402
3403         /* Driver insert flow: Enable TR/RX */
3404         err = _drv_enable_trx(d);
3405         if (err)
3406                 goto out;
3407
3408         /* halmac_send_general_info */
3409         if (_TRUE == fw_ok) {
3410                 err = _send_general_info(d);
3411                 if (err)
3412                         goto out;
3413         }
3414
3415         /* Init Phy parameter-MAC */
3416         ok = rtw_hal_init_mac_register(adapter);
3417         if (_FALSE == ok)
3418                 goto out;
3419
3420         /* StateMacInitialized */
3421
3422         /* halmac_cfg_drv_info */
3423         err = rtw_halmac_config_rx_info(d, HALMAC_DRV_INFO_PHY_STATUS);
3424         if (err)
3425                 goto out;
3426
3427         /* halmac_set_hw_value(HALMAC_HW_EN_BB_RF) */
3428         /* Init BB, RF */
3429         ok = rtw_hal_init_phy(adapter);
3430         if (_FALSE == ok)
3431                 goto out;
3432
3433         status = api->halmac_init_interface_cfg(halmac);
3434         if (status != HALMAC_RET_SUCCESS)
3435                 goto out;
3436
3437         /* SKIP: halmac_verify_platform_api */
3438         /* SKIP: halmac_h2c_lb */
3439
3440         /* StateRxIdle */
3441
3442         err_ret = 0;
3443 out:
3444         return err_ret;
3445 }
3446
3447 int rtw_halmac_init_hal(struct dvobj_priv *d)
3448 {
3449         return _halmac_init_hal(d, NULL, 0);
3450 }
3451
3452 /*
3453  * Notices:
3454  *      Make sure
3455  *      1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
3456  *      2. HAL_DATA_TYPE.rfe_type
3457  *      already ready for use before calling this function.
3458  */
3459 int rtw_halmac_init_hal_fw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3460 {
3461         return _halmac_init_hal(d, fw, fwsize);
3462 }
3463
3464 /*
3465  * Notices:
3466  *      Make sure
3467  *      1. rtw_hal_get_hwreg(HW_VAR_RF_TYPE)
3468  *      2. HAL_DATA_TYPE.rfe_type
3469  *      already ready for use before calling this function.
3470  */
3471 int rtw_halmac_init_hal_fw_file(struct dvobj_priv *d, u8 *fwpath)
3472 {
3473         u8 *fw = NULL;
3474         u32 fwmaxsize = 0, size = 0;
3475         int err = 0;
3476
3477
3478         err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
3479         if (err) {
3480                 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
3481                 return -1;
3482         }
3483
3484         fw = rtw_zmalloc(fwmaxsize);
3485         if (!fw)
3486                 return -1;
3487
3488         size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
3489         if (!size) {
3490                 err = -1;
3491                 goto exit;
3492         }
3493
3494         err = _halmac_init_hal(d, fw, size);
3495
3496 exit:
3497         rtw_mfree(fw, fwmaxsize);
3498         /*fw = NULL;*/
3499
3500         return err;
3501 }
3502
3503 int rtw_halmac_deinit_hal(struct dvobj_priv *d)
3504 {
3505         PADAPTER adapter;
3506         struct halmac_adapter *halmac;
3507         struct halmac_api *api;
3508         enum halmac_ret_status status;
3509         int err = -1;
3510
3511
3512         adapter = dvobj_get_primary_adapter(d);
3513         halmac = dvobj_to_halmac(d);
3514         if (!halmac)
3515                 goto out;
3516         api = HALMAC_GET_API(halmac);
3517
3518         status = api->halmac_deinit_interface_cfg(halmac);
3519         if (status != HALMAC_RET_SUCCESS)
3520                 goto out;
3521
3522         rtw_hal_power_off(adapter);
3523
3524         err = 0;
3525 out:
3526         return err;
3527 }
3528
3529 int rtw_halmac_self_verify(struct dvobj_priv *d)
3530 {
3531         struct halmac_adapter *mac;
3532         struct halmac_api *api;
3533         enum halmac_ret_status status;
3534         int err = -1;
3535
3536
3537         mac = dvobj_to_halmac(d);
3538         api = HALMAC_GET_API(mac);
3539
3540         status = api->halmac_verify_platform_api(mac);
3541         if (status != HALMAC_RET_SUCCESS)
3542                 goto out;
3543
3544         status = api->halmac_h2c_lb(mac);
3545         if (status != HALMAC_RET_SUCCESS)
3546                 goto out;
3547
3548         err = 0;
3549 out:
3550         return err;
3551 }
3552
3553 static u8 rtw_halmac_txfifo_is_empty(struct dvobj_priv *d)
3554 {
3555         struct halmac_adapter *mac;
3556         struct halmac_api *api;
3557         enum halmac_ret_status status;
3558         u32 chk_num = 10;
3559         u8 rst = _FALSE;
3560
3561
3562         mac = dvobj_to_halmac(d);
3563         api = HALMAC_GET_API(mac);
3564
3565         status = api->halmac_txfifo_is_empty(mac, chk_num);
3566         if (status == HALMAC_RET_SUCCESS)
3567                 rst = _TRUE;
3568
3569         return rst;
3570 }
3571
3572 /**
3573  * rtw_halmac_txfifo_wait_empty() - Wait TX FIFO to be emtpy
3574  * @d:          struct dvobj_priv*
3575  * @timeout:    time limit of wait, unit is ms
3576  *              0 for no limit
3577  *
3578  * Wait TX FIFO to be emtpy.
3579  *
3580  * Rteurn 0 for TX FIFO is empty, otherwise not empty.
3581  */
3582 int rtw_halmac_txfifo_wait_empty(struct dvobj_priv *d, u32 timeout)
3583 {
3584         struct _ADAPTER *a;
3585         u8 empty = _FALSE;
3586         u32 cnt = 0;
3587         systime start_time = 0;
3588         u32 pass_time; /* ms */
3589
3590
3591         a = dvobj_get_primary_adapter(d);
3592         start_time = rtw_get_current_time();
3593
3594         do {
3595                 cnt++;
3596                 empty = rtw_halmac_txfifo_is_empty(d);
3597                 if (empty == _TRUE)
3598                         break;
3599
3600                 if (timeout) {
3601                         pass_time = rtw_get_passing_time_ms(start_time);
3602                         if (pass_time > timeout)
3603                                 break;
3604                 }
3605                 if (RTW_CANNOT_IO(a)) {
3606                         RTW_WARN("%s: Interrupted by I/O forbiden!\n", __FUNCTION__);
3607                         break;
3608                 }
3609
3610                 rtw_msleep_os(2);
3611         } while (1);
3612
3613         if (empty == _FALSE) {
3614 #ifdef CONFIG_RTW_DEBUG
3615                 u16 dbg_reg[] = {0x210, 0x230, 0x234, 0x238, 0x23C, 0x240,
3616                                  0x41A, 0x10FC, 0x10F8, 0x11F4, 0x11F8};
3617                 u8 i;
3618                 u32 val;
3619
3620                 if (!RTW_CANNOT_IO(a)) {
3621                         for (i = 0; i < ARRAY_SIZE(dbg_reg); i++) {
3622                                 val = rtw_read32(a, dbg_reg[i]);
3623                                 RTW_ERR("REG_%X:0x%08x\n", dbg_reg[i], val);
3624                         }
3625                 }
3626 #endif /* CONFIG_RTW_DEBUG */
3627
3628                 RTW_ERR("%s: Fail to wait txfifo empty!(cnt=%d)\n",
3629                         __FUNCTION__, cnt);
3630                 return -1;
3631         }
3632
3633         return 0;
3634 }
3635
3636 static enum halmac_dlfw_mem _fw_mem_drv2halmac(enum fw_mem mem, u8 tx_stop)
3637 {
3638         enum halmac_dlfw_mem mem_halmac = HALMAC_DLFW_MEM_UNDEFINE;
3639
3640
3641         switch (mem) {
3642         case FW_EMEM:
3643                 if (tx_stop == _FALSE)
3644                         mem_halmac = HALMAC_DLFW_MEM_EMEM_RSVD_PG;
3645                 else
3646                         mem_halmac = HALMAC_DLFW_MEM_EMEM;
3647                 break;
3648
3649         case FW_IMEM:
3650         case FW_DMEM:
3651                 mem_halmac = HALMAC_DLFW_MEM_UNDEFINE;
3652                 break;
3653         }
3654
3655         return mem_halmac;
3656 }
3657
3658 int rtw_halmac_dlfw_mem(struct dvobj_priv *d, u8 *fw, u32 fwsize, enum fw_mem mem)
3659 {
3660         struct halmac_adapter *mac;
3661         struct halmac_api *api;
3662         enum halmac_ret_status status;
3663         enum halmac_dlfw_mem dlfw_mem;
3664         u8 tx_stop = _FALSE;
3665         u32 chk_timeout = 2000; /* unit: ms */
3666         int err = 0;
3667
3668
3669         mac = dvobj_to_halmac(d);
3670         api = HALMAC_GET_API(mac);
3671
3672         if ((!fw) || (!fwsize))
3673                 return -1;
3674
3675 #ifndef RTW_HALMAC_DLFW_MEM_NO_STOP_TX
3676         /* 1. Driver Stop Tx */
3677         /* ToDo */
3678
3679         /* 2. Driver Check Tx FIFO is empty */
3680         err = rtw_halmac_txfifo_wait_empty(d, chk_timeout);
3681         if (err)
3682                 tx_stop = _FALSE;
3683         else
3684                 tx_stop = _TRUE;
3685 #endif /* !RTW_HALMAC_DLFW_MEM_NO_STOP_TX */
3686
3687         /* 3. Download Firmware MEM */
3688         dlfw_mem = _fw_mem_drv2halmac(mem, tx_stop);
3689         if (dlfw_mem == HALMAC_DLFW_MEM_UNDEFINE) {
3690                 err = -1;
3691                 goto resume_tx;
3692         }
3693         status = api->halmac_free_download_firmware(mac, dlfw_mem, fw, fwsize);
3694         if (status != HALMAC_RET_SUCCESS) {
3695                 RTW_ERR("%s: halmac_free_download_firmware fail(err=0x%x)\n",
3696                         __FUNCTION__, status);
3697                 err = -1;
3698                 goto resume_tx;
3699         }
3700
3701 resume_tx:
3702 #ifndef RTW_HALMAC_DLFW_MEM_NO_STOP_TX
3703         /* 4. Driver resume TX if needed */
3704         /* ToDo */
3705 #endif /* !RTW_HALMAC_DLFW_MEM_NO_STOP_TX */
3706
3707         return err;
3708 }
3709
3710 int rtw_halmac_dlfw_mem_from_file(struct dvobj_priv *d, u8 *fwpath, enum fw_mem mem)
3711 {
3712         u8 *fw = NULL;
3713         u32 fwmaxsize = 0, size = 0;
3714         int err = 0;
3715
3716
3717         err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
3718         if (err) {
3719                 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
3720                 return -1;
3721         }
3722
3723         fw = rtw_zmalloc(fwmaxsize);
3724         if (!fw)
3725                 return -1;
3726
3727         size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
3728         if (size)
3729                 err = rtw_halmac_dlfw_mem(d, fw, size, mem);
3730         else
3731                 err = -1;
3732
3733         rtw_mfree(fw, fwmaxsize);
3734         /*fw = NULL;*/
3735
3736         return err;
3737 }
3738
3739 /*
3740  * Return:
3741  *      0       Success
3742  *      -22     Invalid arguemnt
3743  */
3744 int rtw_halmac_dlfw(struct dvobj_priv *d, u8 *fw, u32 fwsize)
3745 {
3746         PADAPTER adapter;
3747         enum halmac_ret_status status;
3748         u32 ok;
3749         int err, err_ret = -1;
3750
3751
3752         if (!fw || !fwsize)
3753                 return -22;
3754
3755         adapter = dvobj_get_primary_adapter(d);
3756
3757         /* re-download firmware */
3758         if (rtw_is_hw_init_completed(adapter))
3759                 return download_fw(d, fw, fwsize, 1);
3760
3761         /* Download firmware before hal init */
3762         /* Power on, download firmware and init mac */
3763         ok = rtw_hal_power_on(adapter);
3764         if (_FAIL == ok)
3765                 goto out;
3766
3767         err = download_fw(d, fw, fwsize, 0);
3768         if (err) {
3769                 err_ret = err;
3770                 goto out;
3771         }
3772
3773         err = init_mac_flow(d);
3774         if (err)
3775                 goto out;
3776
3777         err = _send_general_info(d);
3778         if (err)
3779                 goto out;
3780
3781         err_ret = 0;
3782
3783 out:
3784         return err_ret;
3785 }
3786
3787 int rtw_halmac_dlfw_from_file(struct dvobj_priv *d, u8 *fwpath)
3788 {
3789         u8 *fw = NULL;
3790         u32 fwmaxsize = 0, size = 0;
3791         int err = 0;
3792
3793
3794         err = rtw_halmac_get_fw_max_size(d, &fwmaxsize);
3795         if (err) {
3796                 RTW_ERR("%s: Fail to get Firmware MAX size(err=%d)\n", __FUNCTION__, err);
3797                 return -1;
3798         }
3799
3800         fw = rtw_zmalloc(fwmaxsize);
3801         if (!fw)
3802                 return -1;
3803
3804         size = rtw_retrieve_from_file(fwpath, fw, fwmaxsize);
3805         if (size)
3806                 err = rtw_halmac_dlfw(d, fw, size);
3807         else
3808                 err = -1;
3809
3810         rtw_mfree(fw, fwmaxsize);
3811         /*fw = NULL;*/
3812
3813         return err;
3814 }
3815
3816 /*
3817  * Description:
3818  *      Power on/off BB/RF domain.
3819  *
3820  * Parameters:
3821  *      enable  _TRUE/_FALSE for power on/off
3822  *
3823  * Return:
3824  *      0       Success
3825  *      others  Fail
3826  */
3827 int rtw_halmac_phy_power_switch(struct dvobj_priv *d, u8 enable)
3828 {
3829         PADAPTER adapter;
3830         struct halmac_adapter *halmac;
3831         struct halmac_api *api;
3832         enum halmac_ret_status status;
3833         u8 on;
3834
3835
3836         adapter = dvobj_get_primary_adapter(d);
3837         halmac = dvobj_to_halmac(d);
3838         if (!halmac)
3839                 return -1;
3840         api = HALMAC_GET_API(halmac);
3841         on = (enable == _TRUE) ? 1 : 0;
3842
3843         status = api->halmac_set_hw_value(halmac, HALMAC_HW_EN_BB_RF, &on);
3844         if (status != HALMAC_RET_SUCCESS)
3845                 return -1;
3846
3847         return 0;
3848 }
3849
3850 static u8 _is_fw_read_cmd_down(PADAPTER adapter, u8 msgbox_num)
3851 {
3852         u8 read_down = _FALSE;
3853         int retry_cnts = 100;
3854         u8 valid;
3855
3856         do {
3857                 valid = rtw_read8(adapter, REG_HMETFR) & BIT(msgbox_num);
3858                 if (0 == valid)
3859                         read_down = _TRUE;
3860                 else
3861                         rtw_msleep_os(1);
3862         } while ((!read_down) && (retry_cnts--));
3863
3864         if (_FALSE == read_down)
3865                 RTW_WARN("%s, reg_1cc(%x), msg_box(%d)...\n", __func__, rtw_read8(adapter, REG_HMETFR), msgbox_num);
3866
3867         return read_down;
3868 }
3869
3870 /**
3871  * rtw_halmac_send_h2c() - Send H2C to firmware
3872  * @d:          struct dvobj_priv*
3873  * @h2c:        H2C data buffer, suppose to be 8 bytes
3874  *
3875  * Send H2C to firmware by message box register(0x1D0~0x1D3 & 0x1F0~0x1F3).
3876  *
3877  * Assume firmware be ready to accept H2C here, please check
3878  * (hal->bFWReady == _TRUE) before call this function or make sure firmware is
3879  * ready.
3880  *
3881  * Return: 0 if process OK, otherwise fail to send this H2C.
3882  */
3883 int rtw_halmac_send_h2c(struct dvobj_priv *d, u8 *h2c)
3884 {
3885         PADAPTER adapter = dvobj_get_primary_adapter(d);
3886         PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
3887         u8 h2c_box_num = 0;
3888         u32 msgbox_addr = 0;
3889         u32 msgbox_ex_addr = 0;
3890         u32 h2c_cmd = 0;
3891         u32 h2c_cmd_ex = 0;
3892         int err = -1;
3893
3894
3895         if (!h2c) {
3896                 RTW_WARN("%s: pbuf is NULL\n", __FUNCTION__);
3897                 return err;
3898         }
3899
3900         if (rtw_is_surprise_removed(adapter)) {
3901                 RTW_WARN("%s: surprise removed\n", __FUNCTION__);
3902                 return err;
3903         }
3904
3905         _enter_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
3906
3907         /* pay attention to if race condition happened in H2C cmd setting */
3908         h2c_box_num = hal->LastHMEBoxNum;
3909
3910         if (!_is_fw_read_cmd_down(adapter, h2c_box_num)) {
3911                 RTW_WARN(" fw read cmd failed...\n");
3912 #ifdef DBG_CONFIG_ERROR_DETECT
3913                 hal->srestpriv.self_dect_fw = _TRUE;
3914                 hal->srestpriv.self_dect_fw_cnt++;
3915 #endif /* DBG_CONFIG_ERROR_DETECT */
3916                 goto exit;
3917         }
3918
3919         /* Write Ext command (byte 4~7) */
3920         msgbox_ex_addr = REG_HMEBOX_E0 + (h2c_box_num * EX_MESSAGE_BOX_SIZE);
3921         _rtw_memcpy((u8 *)(&h2c_cmd_ex), h2c + 4, EX_MESSAGE_BOX_SIZE);
3922         h2c_cmd_ex = le32_to_cpu(h2c_cmd_ex);
3923         rtw_write32(adapter, msgbox_ex_addr, h2c_cmd_ex);
3924
3925         /* Write command (byte 0~3) */
3926         msgbox_addr = REG_HMEBOX0 + (h2c_box_num * MESSAGE_BOX_SIZE);
3927         _rtw_memcpy((u8 *)(&h2c_cmd), h2c, 4);
3928         h2c_cmd = le32_to_cpu(h2c_cmd);
3929         rtw_write32(adapter, msgbox_addr, h2c_cmd);
3930
3931         /* update last msg box number */
3932         hal->LastHMEBoxNum = (h2c_box_num + 1) % MAX_H2C_BOX_NUMS;
3933         err = 0;
3934
3935 #ifdef DBG_H2C_CONTENT
3936         RTW_INFO_DUMP("[H2C] - ", h2c, RTW_HALMAC_H2C_MAX_SIZE);
3937 #endif
3938 exit:
3939         _exit_critical_mutex(&d->h2c_fwcmd_mutex, NULL);
3940         return err;
3941 }
3942
3943 /**
3944  * rtw_halmac_c2h_handle() - Handle C2H for HALMAC
3945  * @d:          struct dvobj_priv*
3946  * @c2h:        Full C2H packet, including RX description and payload
3947  * @size:       Size(byte) of c2h
3948  *
3949  * Send C2H packet to HALMAC to process C2H packets, and the expected C2H ID is
3950  * 0xFF. This function won't have any I/O, so caller doesn't have to call it in
3951  * I/O safe place(ex. command thread).
3952  *
3953  * Please sure doesn't call this function in the same thread as someone is
3954  * waiting HALMAC C2H ack, otherwise there is a deadlock happen.
3955  *
3956  * Return: 0 if process OK, otherwise no action for this C2H.
3957  */
3958 int rtw_halmac_c2h_handle(struct dvobj_priv *d, u8 *c2h, u32 size)
3959 {
3960         struct halmac_adapter *mac;
3961         struct halmac_api *api;
3962         enum halmac_ret_status status;
3963
3964
3965         mac = dvobj_to_halmac(d);
3966         api = HALMAC_GET_API(mac);
3967
3968         status = api->halmac_get_c2h_info(mac, c2h, size);
3969         if (HALMAC_RET_SUCCESS != status)
3970                 return -1;
3971
3972         return 0;
3973 }
3974
3975 int rtw_halmac_get_available_efuse_size(struct dvobj_priv *d, u32 *size)
3976 {
3977         struct halmac_adapter *mac;
3978         struct halmac_api *api;
3979         enum halmac_ret_status status;
3980         u32 val;
3981
3982
3983         mac = dvobj_to_halmac(d);
3984         api = HALMAC_GET_API(mac);
3985
3986         status = api->halmac_get_efuse_available_size(mac, &val);
3987         if (HALMAC_RET_SUCCESS != status)
3988                 return -1;
3989
3990         *size = val;
3991         return 0;
3992 }
3993
3994 int rtw_halmac_get_physical_efuse_size(struct dvobj_priv *d, u32 *size)
3995 {
3996         struct halmac_adapter *mac;
3997         struct halmac_api *api;
3998         enum halmac_ret_status status;
3999         u32 val;
4000
4001
4002         mac = dvobj_to_halmac(d);
4003         api = HALMAC_GET_API(mac);
4004
4005         status = api->halmac_get_efuse_size(mac, &val);
4006         if (HALMAC_RET_SUCCESS != status)
4007                 return -1;
4008
4009         *size = val;
4010         return 0;
4011 }
4012
4013 int rtw_halmac_read_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
4014 {
4015         struct halmac_adapter *mac;
4016         struct halmac_api *api;
4017         enum halmac_ret_status status;
4018         enum halmac_feature_id id;
4019         int ret;
4020
4021
4022         mac = dvobj_to_halmac(d);
4023         api = HALMAC_GET_API(mac);
4024         id = HALMAC_FEATURE_DUMP_PHYSICAL_EFUSE;
4025
4026         ret = init_halmac_event(d, id, map, size);
4027         if (ret)
4028                 return -1;
4029
4030         status = api->halmac_dump_efuse_map(mac, HALMAC_EFUSE_R_DRV);
4031         if (HALMAC_RET_SUCCESS != status) {
4032                 free_halmac_event(d, id);
4033                 return -1;
4034         }
4035
4036         ret = wait_halmac_event(d, id);
4037         if (ret)
4038                 return -1;
4039
4040         return 0;
4041 }
4042
4043 int rtw_halmac_read_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4044 {
4045         struct halmac_adapter *mac;
4046         struct halmac_api *api;
4047         enum halmac_ret_status status;
4048         u8 v;
4049         u32 i;
4050         u8 *efuse = NULL;
4051         u32 size = 0;
4052         int err = 0;
4053
4054
4055         mac = dvobj_to_halmac(d);
4056         api = HALMAC_GET_API(mac);
4057
4058         if (api->halmac_read_efuse) {
4059                 for (i = 0; i < cnt; i++) {
4060                         status = api->halmac_read_efuse(mac, offset + i, &v);
4061                         if (HALMAC_RET_SUCCESS != status)
4062                                 return -1;
4063                         data[i] = v;
4064                 }
4065         } else {
4066                 err = rtw_halmac_get_physical_efuse_size(d, &size);
4067                 if (err)
4068                         return -1;
4069
4070                 efuse = rtw_zmalloc(size);
4071                 if (!efuse)
4072                         return -1;
4073
4074                 err = rtw_halmac_read_physical_efuse_map(d, efuse, size);
4075                 if (err)
4076                         err = -1;
4077                 else
4078                         _rtw_memcpy(data, efuse + offset, cnt);
4079
4080                 rtw_mfree(efuse, size);
4081         }
4082
4083         return err;
4084 }
4085
4086 int rtw_halmac_write_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4087 {
4088         struct halmac_adapter *mac;
4089         struct halmac_api *api;
4090         enum halmac_ret_status status;
4091         u32 i;
4092
4093
4094         mac = dvobj_to_halmac(d);
4095         api = HALMAC_GET_API(mac);
4096
4097         if (api->halmac_write_efuse == NULL)
4098                 return -1;
4099
4100         for (i = 0; i < cnt; i++) {
4101                 status = api->halmac_write_efuse(mac, offset + i, data[i]);
4102                 if (HALMAC_RET_SUCCESS != status)
4103                         return -1;
4104         }
4105
4106         return 0;
4107 }
4108
4109 int rtw_halmac_get_logical_efuse_size(struct dvobj_priv *d, u32 *size)
4110 {
4111         struct halmac_adapter *mac;
4112         struct halmac_api *api;
4113         enum halmac_ret_status status;
4114         u32 val;
4115
4116
4117         mac = dvobj_to_halmac(d);
4118         api = HALMAC_GET_API(mac);
4119
4120         status = api->halmac_get_logical_efuse_size(mac, &val);
4121         if (HALMAC_RET_SUCCESS != status)
4122                 return -1;
4123
4124         *size = val;
4125         return 0;
4126 }
4127
4128 int rtw_halmac_read_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size, u8 *maskmap, u32 masksize)
4129 {
4130         struct halmac_adapter *mac;
4131         struct halmac_api *api;
4132         enum halmac_ret_status status;
4133         enum halmac_feature_id id;
4134         int ret;
4135
4136
4137         mac = dvobj_to_halmac(d);
4138         api = HALMAC_GET_API(mac);
4139         id = HALMAC_FEATURE_DUMP_LOGICAL_EFUSE;
4140
4141         ret = init_halmac_event(d, id, map, size);
4142         if (ret)
4143                 return -1;
4144
4145         status = api->halmac_dump_logical_efuse_map(mac, HALMAC_EFUSE_R_DRV);
4146         if (HALMAC_RET_SUCCESS != status) {
4147                 free_halmac_event(d, id);
4148                 return -1;
4149         }
4150
4151         ret = wait_halmac_event(d, id);
4152         if (ret)
4153                 return -1;
4154
4155         if (maskmap && masksize) {
4156                 struct halmac_pg_efuse_info pginfo;
4157
4158                 pginfo.efuse_map = map;
4159                 pginfo.efuse_map_size = size;
4160                 pginfo.efuse_mask = maskmap;
4161                 pginfo.efuse_mask_size = masksize;
4162
4163                 status = api->halmac_mask_logical_efuse(mac, &pginfo);
4164                 if (status != HALMAC_RET_SUCCESS)
4165                         RTW_WARN("%s: mask logical efuse FAIL!\n", __FUNCTION__);
4166         }
4167
4168         return 0;
4169 }
4170
4171 int rtw_halmac_write_logical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size, u8 *maskmap, u32 masksize)
4172 {
4173         struct halmac_adapter *mac;
4174         struct halmac_api *api;
4175         struct halmac_pg_efuse_info pginfo;
4176         enum halmac_ret_status status;
4177
4178
4179         mac = dvobj_to_halmac(d);
4180         api = HALMAC_GET_API(mac);
4181
4182         pginfo.efuse_map = map;
4183         pginfo.efuse_map_size = size;
4184         pginfo.efuse_mask = maskmap;
4185         pginfo.efuse_mask_size = masksize;
4186
4187         status = api->halmac_pg_efuse_by_map(mac, &pginfo, HALMAC_EFUSE_R_AUTO);
4188         if (HALMAC_RET_SUCCESS != status)
4189                 return -1;
4190
4191         return 0;
4192 }
4193
4194 int rtw_halmac_read_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4195 {
4196         struct halmac_adapter *mac;
4197         struct halmac_api *api;
4198         enum halmac_ret_status status;
4199         u8 v;
4200         u32 i;
4201
4202
4203         mac = dvobj_to_halmac(d);
4204         api = HALMAC_GET_API(mac);
4205
4206         for (i = 0; i < cnt; i++) {
4207                 status = api->halmac_read_logical_efuse(mac, offset + i, &v);
4208                 if (HALMAC_RET_SUCCESS != status)
4209                         return -1;
4210                 data[i] = v;
4211         }
4212
4213         return 0;
4214 }
4215
4216 int rtw_halmac_write_logical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4217 {
4218         struct halmac_adapter *mac;
4219         struct halmac_api *api;
4220         enum halmac_ret_status status;
4221         u32 i;
4222
4223
4224         mac = dvobj_to_halmac(d);
4225         api = HALMAC_GET_API(mac);
4226
4227         for (i = 0; i < cnt; i++) {
4228                 status = api->halmac_write_logical_efuse(mac, offset + i, data[i]);
4229                 if (HALMAC_RET_SUCCESS != status)
4230                         return -1;
4231         }
4232
4233         return 0;
4234 }
4235
4236 int rtw_halmac_write_bt_physical_efuse(struct dvobj_priv *d, u32 offset, u32 cnt, u8 *data)
4237 {
4238         struct halmac_adapter *mac;
4239         struct halmac_api *api;
4240         enum halmac_ret_status status;
4241         u32 i;
4242         u8 bank = 1;
4243
4244
4245         mac = dvobj_to_halmac(d);
4246         api = HALMAC_GET_API(mac);
4247
4248         for (i = 0; i < cnt; i++) {
4249                 status = api->halmac_write_efuse_bt(mac, offset + i, data[i], bank);
4250                 if (HALMAC_RET_SUCCESS != status) {
4251                         printk("%s: halmac_write_efuse_bt status = %d\n", __FUNCTION__, status);
4252                         return -1;
4253                 }
4254         }
4255         printk("%s: halmac_write_efuse_bt status = HALMAC_RET_SUCCESS %d\n", __FUNCTION__, status);
4256         return 0;
4257 }
4258
4259
4260 int rtw_halmac_read_bt_physical_efuse_map(struct dvobj_priv *d, u8 *map, u32 size)
4261 {
4262         struct halmac_adapter *mac;
4263         struct halmac_api *api;
4264         enum halmac_ret_status status;
4265         int bank = 1;
4266
4267
4268         mac = dvobj_to_halmac(d);
4269         api = HALMAC_GET_API(mac);
4270
4271         status = api->halmac_dump_efuse_map_bt(mac, bank, size, map);
4272         if (HALMAC_RET_SUCCESS != status) {
4273                 printk("%s: halmac_dump_efuse_map_bt fail!\n", __FUNCTION__);
4274                 return -1;
4275         }
4276
4277         printk("%s: OK!\n", __FUNCTION__);
4278
4279         return 0;
4280 }
4281
4282 static enum hal_fifo_sel _fifo_sel_drv2halmac(u8 fifo_sel)
4283 {
4284         switch (fifo_sel) {
4285         case 0:
4286                 return HAL_FIFO_SEL_TX;
4287         case 1:
4288                 return HAL_FIFO_SEL_RX;
4289         case 2:
4290                 return HAL_FIFO_SEL_RSVD_PAGE;
4291         case 3:
4292                 return HAL_FIFO_SEL_REPORT;
4293         case 4:
4294                 return HAL_FIFO_SEL_LLT;
4295         case 5:
4296                 return HAL_FIFO_SEL_RXBUF_FW;
4297         }
4298
4299         return HAL_FIFO_SEL_RSVD_PAGE;
4300 }
4301
4302 /*#define CONFIG_HALMAC_FIFO_DUMP*/
4303 int rtw_halmac_dump_fifo(struct dvobj_priv *d, u8 fifo_sel, u32 addr, u32 size, u8 *buffer)
4304 {
4305         struct halmac_adapter *mac;
4306         struct halmac_api *api;
4307         enum hal_fifo_sel halmac_fifo_sel;
4308         enum halmac_ret_status status;
4309         u8 *pfifo_map = NULL;
4310         u32 fifo_size = 0;
4311         s8 ret = 0;/* 0:success, -1:error */
4312         u8 mem_created = _FALSE;
4313
4314
4315         mac = dvobj_to_halmac(d);
4316         api = HALMAC_GET_API(mac);
4317
4318         if ((size != 0) && (buffer == NULL))
4319                 return -1;
4320
4321         halmac_fifo_sel = _fifo_sel_drv2halmac(fifo_sel);
4322
4323         if ((size) && (buffer)) {
4324                 pfifo_map = buffer;
4325                 fifo_size = size;
4326         } else {
4327                 fifo_size = api->halmac_get_fifo_size(mac, halmac_fifo_sel);
4328
4329                 if (fifo_size)
4330                         pfifo_map = rtw_zvmalloc(fifo_size);
4331                 if (pfifo_map == NULL)
4332                         return -1;
4333                 mem_created = _TRUE;
4334         }
4335
4336         status = api->halmac_dump_fifo(mac, halmac_fifo_sel, addr, fifo_size, pfifo_map);
4337         if (HALMAC_RET_SUCCESS != status) {
4338                 ret = -1;
4339                 goto _exit;
4340         }
4341
4342 #ifdef CONFIG_HALMAC_FIFO_DUMP
4343         {
4344                 static const char * const fifo_sel_str[] = {
4345                         "TX", "RX", "RSVD_PAGE", "REPORT", "LLT", "RXBUF_FW"
4346                 };
4347
4348                 RTW_INFO("%s FIFO DUMP [start_addr:0x%04x , size:%d]\n", fifo_sel_str[halmac_fifo_sel], addr, fifo_size);
4349                 RTW_INFO_DUMP("\n", pfifo_map, fifo_size);
4350                 RTW_INFO(" ==================================================\n");
4351         }
4352 #endif /* CONFIG_HALMAC_FIFO_DUMP */
4353
4354 _exit:
4355         if ((mem_created == _TRUE) && pfifo_map)
4356                 rtw_vmfree(pfifo_map, fifo_size);
4357
4358         return ret;
4359 }
4360
4361 /*
4362  * rtw_halmac_rx_agg_switch() - Switch RX aggregation function and setting
4363  * @d           struct dvobj_priv *
4364  * @enable      _FALSE/_TRUE for disable/enable RX aggregation function
4365  *
4366  * This function could help to on/off bus RX aggregation function, and is only
4367  * useful for SDIO and USB interface. Although only "enable" flag is brough in,
4368  * some setting would be taken from other places, and they are from:
4369  * [DMA aggregation]
4370  *      struct hal_com_data.rxagg_dma_size
4371  *      struct hal_com_data.rxagg_dma_timeout
4372  * [USB aggregation] (only use for USB interface)
4373  *      struct hal_com_data.rxagg_usb_size
4374  *      struct hal_com_data.rxagg_usb_timeout
4375  * If above values of size and timeout are both 0 means driver would not
4376  * control the threshold setting and leave it to HALMAC handle.
4377  *
4378  * From HALMAC V1_04_04, driver force the size threshold be hard limit, and the
4379  * rx size can not exceed the setting.
4380  *
4381  * Return 0 for success, otherwise fail.
4382  */
4383 int rtw_halmac_rx_agg_switch(struct dvobj_priv *d, u8 enable)
4384 {
4385         struct _ADAPTER *adapter;
4386         struct hal_com_data *hal;
4387         struct halmac_adapter *halmac;
4388         struct halmac_api *api;
4389         struct halmac_rxagg_cfg rxaggcfg;
4390         enum halmac_ret_status status;
4391
4392
4393         adapter = dvobj_get_primary_adapter(d);
4394         hal = GET_HAL_DATA(adapter);
4395         halmac = dvobj_to_halmac(d);
4396         api = HALMAC_GET_API(halmac);
4397         _rtw_memset((void *)&rxaggcfg, 0, sizeof(rxaggcfg));
4398         rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
4399         /*
4400          * Always enable size limit to avoid rx size exceed
4401          * driver defined size.
4402          */
4403         rxaggcfg.threshold.size_limit_en = 1;
4404
4405 #ifdef RTW_RX_AGGREGATION
4406         if (_TRUE == enable) {
4407 #ifdef CONFIG_SDIO_HCI
4408                 rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
4409                 rxaggcfg.threshold.drv_define = 0;
4410                 if (hal->rxagg_dma_size || hal->rxagg_dma_timeout) {
4411                         rxaggcfg.threshold.drv_define = 1;
4412                         rxaggcfg.threshold.timeout = hal->rxagg_dma_timeout;
4413                         rxaggcfg.threshold.size = hal->rxagg_dma_size;
4414                         RTW_INFO("%s: RX aggregation threshold: "
4415                                  "timeout=%u size=%u\n",
4416                                  __FUNCTION__,
4417                                  hal->rxagg_dma_timeout,
4418                                  hal->rxagg_dma_size);
4419                 }
4420 #elif defined(CONFIG_USB_HCI)
4421                 switch (hal->rxagg_mode) {
4422                 case RX_AGG_DISABLE:
4423                         rxaggcfg.mode = HALMAC_RX_AGG_MODE_NONE;
4424                         break;
4425
4426                 case RX_AGG_DMA:
4427                         rxaggcfg.mode = HALMAC_RX_AGG_MODE_DMA;
4428                         if (hal->rxagg_dma_size || hal->rxagg_dma_timeout) {
4429                                 rxaggcfg.threshold.drv_define = 1;
4430                                 rxaggcfg.threshold.timeout = hal->rxagg_dma_timeout;
4431                                 rxaggcfg.threshold.size = hal->rxagg_dma_size;
4432                         }
4433                         break;
4434
4435                 case RX_AGG_USB:
4436                 case RX_AGG_MIX:
4437                         rxaggcfg.mode = HALMAC_RX_AGG_MODE_USB;
4438                         if (hal->rxagg_usb_size || hal->rxagg_usb_timeout) {
4439                                 rxaggcfg.threshold.drv_define = 1;
4440                                 rxaggcfg.threshold.timeout = hal->rxagg_usb_timeout;
4441                                 rxaggcfg.threshold.size = hal->rxagg_usb_size;
4442                         }
4443                         break;
4444                 }
4445 #endif /* CONFIG_USB_HCI */
4446         }
4447 #endif /* RTW_RX_AGGREGATION */
4448
4449         status = api->halmac_cfg_rx_aggregation(halmac, &rxaggcfg);
4450         if (status != HALMAC_RET_SUCCESS)
4451                 return -1;
4452
4453         return 0;
4454 }
4455
4456 int rtw_halmac_download_rsvd_page(struct dvobj_priv *dvobj, u8 pg_offset, u8 *pbuf, u32 size)
4457 {
4458         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4459         struct halmac_adapter *halmac = dvobj_to_halmac(dvobj);
4460         struct halmac_api *api = HALMAC_GET_API(halmac);
4461
4462         status = api->halmac_dl_drv_rsvd_page(halmac, pg_offset, pbuf, size);
4463         if (status != HALMAC_RET_SUCCESS)
4464                 return -1;
4465
4466         return 0;
4467 }
4468
4469 /*
4470  * Description
4471  *      Fill following spec info from HALMAC API:
4472  *      sec_cam_ent_num
4473  *
4474  * Return
4475  *      0       Success
4476  *      others  Fail
4477  */
4478 int rtw_halmac_fill_hal_spec(struct dvobj_priv *dvobj, struct hal_spec_t *spec)
4479 {
4480         enum halmac_ret_status status;
4481         struct halmac_adapter *halmac;
4482         struct halmac_api *api;
4483         u8 cam = 0;     /* Security Cam Entry Number */
4484
4485
4486         halmac = dvobj_to_halmac(dvobj);
4487         api = HALMAC_GET_API(halmac);
4488
4489         /* Prepare data from HALMAC */
4490         status = api->halmac_get_hw_value(halmac, HALMAC_HW_CAM_ENTRY_NUM, &cam);
4491         if (status != HALMAC_RET_SUCCESS)
4492                 return -1;
4493
4494         /* Fill data to hal_spec_t */
4495         spec->sec_cam_ent_num = cam;
4496
4497         return 0;
4498 }
4499
4500 int rtw_halmac_p2pps(struct dvobj_priv *dvobj, struct hal_p2p_ps_para *pp2p_ps_para)
4501 {
4502         enum halmac_ret_status status = HALMAC_RET_SUCCESS;
4503         struct halmac_adapter *halmac = dvobj_to_halmac(dvobj);
4504         struct halmac_api *api = HALMAC_GET_API(halmac);
4505         struct halmac_p2pps halmac_p2p_ps;
4506
4507         (&halmac_p2p_ps)->offload_en = pp2p_ps_para->offload_en;
4508         (&halmac_p2p_ps)->role = pp2p_ps_para->role;
4509         (&halmac_p2p_ps)->ctwindow_en = pp2p_ps_para->ctwindow_en;
4510         (&halmac_p2p_ps)->noa_en = pp2p_ps_para->noa_en;
4511         (&halmac_p2p_ps)->noa_sel = pp2p_ps_para->noa_sel;
4512         (&halmac_p2p_ps)->all_sta_sleep = pp2p_ps_para->all_sta_sleep;
4513         (&halmac_p2p_ps)->discovery = pp2p_ps_para->discovery;
4514         (&halmac_p2p_ps)->p2p_port_id = _hw_port_drv2halmac(pp2p_ps_para->p2p_port_id);
4515         (&halmac_p2p_ps)->p2p_group = pp2p_ps_para->p2p_group;
4516         (&halmac_p2p_ps)->p2p_macid = pp2p_ps_para->p2p_macid;
4517         (&halmac_p2p_ps)->ctwindow_length = pp2p_ps_para->ctwindow_length;
4518         (&halmac_p2p_ps)->noa_duration_para = pp2p_ps_para->noa_duration_para;
4519         (&halmac_p2p_ps)->noa_interval_para = pp2p_ps_para->noa_interval_para;
4520         (&halmac_p2p_ps)->noa_start_time_para = pp2p_ps_para->noa_start_time_para;
4521         (&halmac_p2p_ps)->noa_count_para = pp2p_ps_para->noa_count_para;
4522
4523         status = api->halmac_p2pps(halmac, (&halmac_p2p_ps));
4524         if (status != HALMAC_RET_SUCCESS)
4525                 return -1;
4526
4527         return 0;
4528
4529 }
4530
4531 /**
4532  * rtw_halmac_iqk() - Run IQ Calibration
4533  * @d:          struct dvobj_priv*
4534  * @clear:      IQK parameters
4535  * @segment:    IQK parameters
4536  *
4537  * Process IQ Calibration(IQK).
4538  *
4539  * Rteurn: 0 for OK, otherwise fail.
4540  */
4541 int rtw_halmac_iqk(struct dvobj_priv *d, u8 clear, u8 segment)
4542 {
4543         struct halmac_adapter *mac;
4544         struct halmac_api *api;
4545         enum halmac_ret_status status;
4546         enum halmac_feature_id id;
4547         struct halmac_iqk_para para;
4548         int ret;
4549         u8 retry = 3;
4550         u8 delay = 1; /* ms */
4551
4552
4553         mac = dvobj_to_halmac(d);
4554         api = HALMAC_GET_API(mac);
4555         id = HALMAC_FEATURE_IQK;
4556
4557         ret = init_halmac_event(d, id, NULL, 0);
4558         if (ret)
4559                 return -1;
4560
4561         para.clear = clear;
4562         para.segment_iqk = segment;
4563
4564         do {
4565                 status = api->halmac_start_iqk(mac, &para);
4566                 if (status != HALMAC_RET_BUSY_STATE)
4567                         break;
4568                 RTW_WARN("%s: Fail to start IQK, status is BUSY! retry=%d\n", __FUNCTION__, retry);
4569                 if (!retry)
4570                         break;
4571                 retry--;
4572                 rtw_msleep_os(delay);
4573         } while (1);
4574         if (status != HALMAC_RET_SUCCESS) {
4575                 free_halmac_event(d, id);
4576                 return -1;
4577         }
4578
4579         ret = wait_halmac_event(d, id);
4580         if (ret)
4581                 return -1;
4582
4583         return 0;
4584 }
4585
4586 static inline u32 _phy_parameter_val_drv2halmac(u32 val, u8 msk_en, u32 msk)
4587 {
4588         if (!msk_en)
4589                 return val;
4590
4591         return (val << bitshift(msk));
4592 }
4593
4594 static int _phy_parameter_drv2halmac(struct rtw_phy_parameter *para, struct halmac_phy_parameter_info *info)
4595 {
4596         if (!para || !info)
4597                 return -1;
4598
4599         _rtw_memset(info, 0, sizeof(*info));
4600
4601         switch (para->cmd) {
4602         case 0:
4603                 /* MAC register */
4604                 switch (para->data.mac.size) {
4605                 case 1:
4606                         info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W8;
4607                         break;
4608                 case 2:
4609                         info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W16;
4610                         break;
4611                 default:
4612                         info->cmd_id = HALMAC_PARAMETER_CMD_MAC_W32;
4613                         break;
4614                 }
4615                 info->content.MAC_REG_W.value = _phy_parameter_val_drv2halmac(
4616                                                         para->data.mac.value,
4617                                                         para->data.mac.msk_en,
4618                                                         para->data.mac.msk);
4619                 info->content.MAC_REG_W.msk = para->data.mac.msk;
4620                 info->content.MAC_REG_W.offset = para->data.mac.offset;
4621                 info->content.MAC_REG_W.msk_en = para->data.mac.msk_en;
4622                 break;
4623
4624         case 1:
4625                 /* BB register */
4626                 switch (para->data.bb.size) {
4627                 case 1:
4628                         info->cmd_id = HALMAC_PARAMETER_CMD_BB_W8;
4629                         break;
4630                 case 2:
4631                         info->cmd_id = HALMAC_PARAMETER_CMD_BB_W16;
4632                         break;
4633                 default:
4634                         info->cmd_id = HALMAC_PARAMETER_CMD_BB_W32;
4635                         break;
4636                 }
4637                 info->content.BB_REG_W.value = _phy_parameter_val_drv2halmac(
4638                                                         para->data.bb.value,
4639                                                         para->data.bb.msk_en,
4640                                                         para->data.bb.msk);
4641                 info->content.BB_REG_W.msk = para->data.bb.msk;
4642                 info->content.BB_REG_W.offset = para->data.bb.offset;
4643                 info->content.BB_REG_W.msk_en = para->data.bb.msk_en;
4644                 break;
4645
4646         case 2:
4647                 /* RF register */
4648                 info->cmd_id = HALMAC_PARAMETER_CMD_RF_W;
4649                 info->content.RF_REG_W.value = _phy_parameter_val_drv2halmac(
4650                                                         para->data.rf.value,
4651                                                         para->data.rf.msk_en,
4652                                                         para->data.rf.msk);
4653                 info->content.RF_REG_W.msk = para->data.rf.msk;
4654                 info->content.RF_REG_W.offset = para->data.rf.offset;
4655                 info->content.RF_REG_W.msk_en = para->data.rf.msk_en;
4656                 info->content.RF_REG_W.rf_path = para->data.rf.path;
4657                 break;
4658
4659         case 3:
4660                 /* Delay register */
4661                 if (para->data.delay.unit == 0)
4662                         info->cmd_id = HALMAC_PARAMETER_CMD_DELAY_US;
4663                 else
4664                         info->cmd_id = HALMAC_PARAMETER_CMD_DELAY_MS;
4665                 info->content.DELAY_TIME.delay_time = para->data.delay.value;
4666                 break;
4667
4668         case 0xFF:
4669                 /* Latest(End) command */
4670                 info->cmd_id = HALMAC_PARAMETER_CMD_END;
4671                 break;
4672
4673         default:
4674                 return -1;
4675         }
4676
4677         return 0;
4678 }
4679
4680 /**
4681  * rtw_halmac_cfg_phy_para() - Register(Phy parameter) configuration
4682  * @d:          struct dvobj_priv*
4683  * @para:       phy parameter
4684  *
4685  * Configure registers by firmware using H2C/C2H mechanism.
4686  * The latest command should be para->cmd==0xFF(End command) to finish all
4687  * processes.
4688  *
4689  * Return: 0 for OK, otherwise fail.
4690  */
4691 int rtw_halmac_cfg_phy_para(struct dvobj_priv *d, struct rtw_phy_parameter *para)
4692 {
4693         struct halmac_adapter *mac;
4694         struct halmac_api *api;
4695         enum halmac_ret_status status;
4696         enum halmac_feature_id id;
4697         struct halmac_phy_parameter_info info;
4698         u8 full_fifo;
4699         int err, ret;
4700
4701
4702         mac = dvobj_to_halmac(d);
4703         api = HALMAC_GET_API(mac);
4704         id = HALMAC_FEATURE_CFG_PARA;
4705         full_fifo = 1; /* ToDo: How to deciede? */
4706         ret = 0;
4707
4708         err = _phy_parameter_drv2halmac(para, &info);
4709         if (err)
4710                 return -1;
4711
4712         err = init_halmac_event(d, id, NULL, 0);
4713         if (err)
4714                 return -1;
4715
4716         status = api->halmac_cfg_parameter(mac, &info, full_fifo);
4717         if (info.cmd_id == HALMAC_PARAMETER_CMD_END) {
4718                 if (status == HALMAC_RET_SUCCESS) {
4719                         err = wait_halmac_event(d, id);
4720                         if (err)
4721                                 ret = -1;
4722                 } else {
4723                         free_halmac_event(d, id);
4724                         ret = -1;
4725                         RTW_ERR("%s: Fail to send END of cfg parameter, status is 0x%x!\n", __FUNCTION__, status);
4726                 }
4727         } else {
4728                 if (status == HALMAC_RET_PARA_SENDING) {
4729                         err = wait_halmac_event(d, id);
4730                         if (err)
4731                                 ret = -1;
4732                 } else {
4733                         free_halmac_event(d, id);
4734                         if (status != HALMAC_RET_SUCCESS) {
4735                                 ret = -1;
4736                                 RTW_ERR("%s: Fail to cfg parameter, status is 0x%x!\n", __FUNCTION__, status);
4737                         }
4738                 }
4739         }
4740
4741         return ret;
4742 }
4743
4744 static enum halmac_wlled_mode _led_mode_drv2halmac(u8 drv_mode)
4745 {
4746         enum halmac_wlled_mode halmac_mode;
4747
4748
4749         switch (drv_mode) {
4750         case 1:
4751                 halmac_mode = HALMAC_WLLED_MODE_TX;
4752                 break;
4753         case 2:
4754                 halmac_mode = HALMAC_WLLED_MODE_RX;
4755                 break;
4756         case 3:
4757                 halmac_mode = HALMAC_WLLED_MODE_SW_CTRL;
4758                 break;
4759         case 0:
4760         default:
4761                 halmac_mode = HALMAC_WLLED_MODE_TRX;
4762                 break;
4763         }
4764
4765         return halmac_mode;
4766 }
4767
4768 /**
4769  * rtw_halmac_led_cfg() - Configure Hardware LED Mode
4770  * @d:          struct dvobj_priv*
4771  * @enable:     enable or disable LED function
4772  *              0: disable
4773  *              1: enable
4774  * @mode:       WLan LED mode (valid when enable==1)
4775  *              0: Blink when TX(transmit packet) and RX(receive packet)
4776  *              1: Blink when TX only
4777  *              2: Blink when RX only
4778  *              3: Software control
4779  *
4780  * Configure hardware WLan LED mode.
4781  * If want to change LED mode after enabled, need to disable LED first and
4782  * enable again to set new mode.
4783  *
4784  * Rteurn 0 for OK, otherwise fail.
4785  */
4786 int rtw_halmac_led_cfg(struct dvobj_priv *d, u8 enable, u8 mode)
4787 {
4788         struct halmac_adapter *halmac;
4789         struct halmac_api *api;
4790         enum halmac_wlled_mode led_mode;
4791         enum halmac_ret_status status;
4792
4793
4794         halmac = dvobj_to_halmac(d);
4795         api = HALMAC_GET_API(halmac);
4796
4797         if (enable) {
4798                 status = api->halmac_pinmux_set_func(halmac,
4799                                                      HALMAC_GPIO_FUNC_WL_LED);
4800                 if (status != HALMAC_RET_SUCCESS) {
4801                         RTW_ERR("%s: pinmux set fail!(0x%x)\n",
4802                                 __FUNCTION__, status);
4803                         return -1;
4804                 }
4805
4806                 led_mode = _led_mode_drv2halmac(mode);
4807                 status = api->halmac_pinmux_wl_led_mode(halmac, led_mode);
4808                 if (status != HALMAC_RET_SUCCESS) {
4809                         RTW_ERR("%s: mode set fail!(0x%x)\n",
4810                                 __FUNCTION__, status);
4811                         return -1;
4812                 }
4813         } else {
4814                 /* Change LED to software control and turn off */
4815                 api->halmac_pinmux_wl_led_mode(halmac,
4816                                                HALMAC_WLLED_MODE_SW_CTRL);
4817                 api->halmac_pinmux_wl_led_sw_ctrl(halmac, 0);
4818
4819                 status = api->halmac_pinmux_free_func(halmac,
4820                                                       HALMAC_GPIO_FUNC_WL_LED);
4821                 if (status != HALMAC_RET_SUCCESS) {
4822                         RTW_ERR("%s: pinmux free fail!(0x%x)\n",
4823                                 __FUNCTION__, status);
4824                         return -1;
4825                 }
4826         }
4827
4828         return 0;
4829 }
4830
4831 /**
4832  * rtw_halmac_led_switch() - Turn Hardware LED on/off
4833  * @d:          struct dvobj_priv*
4834  * @on:         LED light or not
4835  *              0: Off
4836  *              1: On(Light)
4837  *
4838  * Turn Hardware WLan LED On/Off.
4839  * Before use this function, user should call rtw_halmac_led_ctrl() to switch
4840  * mode to "software control(3)" first, otherwise control would fail.
4841  * The interval between on and off must be longer than 1 ms, or the LED would
4842  * keep light or dark only.
4843  * Ex. Turn off LED at first, turn on after 0.5ms and turn off again after
4844  * 0.5ms. The LED during this flow will only keep dark, and miss the turn on
4845  * operation between two turn off operations.
4846  */
4847 void rtw_halmac_led_switch(struct dvobj_priv *d, u8 on)
4848 {
4849         struct halmac_adapter *halmac;
4850         struct halmac_api *api;
4851
4852
4853         halmac = dvobj_to_halmac(d);
4854         api = HALMAC_GET_API(halmac);
4855
4856         api->halmac_pinmux_wl_led_sw_ctrl(halmac, on);
4857 }
4858
4859 #ifdef CONFIG_SDIO_HCI
4860
4861 /*
4862  * Description:
4863  *      Update queue allocated page number to driver
4864  *
4865  * Parameter:
4866  *      d       pointer to struct dvobj_priv of driver
4867  *
4868  * Rteurn:
4869  *      0       Success, "page" is valid.
4870  *      others  Fail, "page" is invalid.
4871  */
4872 int rtw_halmac_query_tx_page_num(struct dvobj_priv *d)
4873 {
4874         PADAPTER adapter;
4875         struct halmacpriv *hmpriv;
4876         struct halmac_adapter *halmac;
4877         struct halmac_api *api;
4878         struct halmac_rqpn_map rqpn;
4879         enum halmac_dma_mapping dmaqueue;
4880         struct halmac_txff_allocation fifosize;
4881         enum halmac_ret_status status;
4882         u8 i;
4883
4884
4885         adapter = dvobj_get_primary_adapter(d);
4886         hmpriv = &d->hmpriv;
4887         halmac = dvobj_to_halmac(d);
4888         api = HALMAC_GET_API(halmac);
4889         _rtw_memset((void *)&rqpn, 0, sizeof(rqpn));
4890         _rtw_memset((void *)&fifosize, 0, sizeof(fifosize));
4891
4892         status = api->halmac_get_hw_value(halmac, HALMAC_HW_RQPN_MAPPING, &rqpn);
4893         if (status != HALMAC_RET_SUCCESS)
4894                 return -1;
4895         status = api->halmac_get_hw_value(halmac, HALMAC_HW_TXFF_ALLOCATION, &fifosize);
4896         if (status != HALMAC_RET_SUCCESS)
4897                 return -1;
4898
4899         for (i = 0; i < HW_QUEUE_ENTRY; i++) {
4900                 hmpriv->txpage[i] = 0;
4901
4902                 /* Driver index mapping to HALMAC DMA queue */
4903                 dmaqueue = HALMAC_DMA_MAPPING_UNDEFINE;
4904                 switch (i) {
4905                 case VO_QUEUE_INX:
4906                         dmaqueue = rqpn.dma_map_vo;
4907                         break;
4908                 case VI_QUEUE_INX:
4909                         dmaqueue = rqpn.dma_map_vi;
4910                         break;
4911                 case BE_QUEUE_INX:
4912                         dmaqueue = rqpn.dma_map_be;
4913                         break;
4914                 case BK_QUEUE_INX:
4915                         dmaqueue = rqpn.dma_map_bk;
4916                         break;
4917                 case MGT_QUEUE_INX:
4918                         dmaqueue = rqpn.dma_map_mg;
4919                         break;
4920                 case HIGH_QUEUE_INX:
4921                         dmaqueue = rqpn.dma_map_hi;
4922                         break;
4923                 case BCN_QUEUE_INX:
4924                 case TXCMD_QUEUE_INX:
4925                         /* Unlimited */
4926                         hmpriv->txpage[i] = 0xFFFF;
4927                         continue;
4928                 }
4929
4930                 switch (dmaqueue) {
4931                 case HALMAC_DMA_MAPPING_EXTRA:
4932                         hmpriv->txpage[i] = fifosize.extra_queue_pg_num;
4933                         break;
4934                 case HALMAC_DMA_MAPPING_LOW:
4935                         hmpriv->txpage[i] = fifosize.low_queue_pg_num;
4936                         break;
4937                 case HALMAC_DMA_MAPPING_NORMAL:
4938                         hmpriv->txpage[i] = fifosize.normal_queue_pg_num;
4939                         break;
4940                 case HALMAC_DMA_MAPPING_HIGH:
4941                         hmpriv->txpage[i] = fifosize.high_queue_pg_num;
4942                         break;
4943                 case HALMAC_DMA_MAPPING_UNDEFINE:
4944                         break;
4945                 }
4946                 hmpriv->txpage[i] += fifosize.pub_queue_pg_num;
4947         }
4948
4949         return 0;
4950 }
4951
4952 /*
4953  * Description:
4954  *      Get specific queue allocated page number
4955  *
4956  * Parameter:
4957  *      d       pointer to struct dvobj_priv of driver
4958  *      queue   target queue to query, VO/VI/BE/BK/.../TXCMD_QUEUE_INX
4959  *      page    return allocated page number
4960  *
4961  * Rteurn:
4962  *      0       Success, "page" is valid.
4963  *      others  Fail, "page" is invalid.
4964  */
4965 int rtw_halmac_get_tx_queue_page_num(struct dvobj_priv *d, u8 queue, u32 *page)
4966 {
4967         *page = 0;
4968         if (queue < HW_QUEUE_ENTRY)
4969                 *page = d->hmpriv.txpage[queue];
4970
4971         return 0;
4972 }
4973
4974 /*
4975  * Return:
4976  *      address for SDIO command
4977  */
4978 u32 rtw_halmac_sdio_get_tx_addr(struct dvobj_priv *d, u8 *desc, u32 size)
4979 {
4980         struct halmac_adapter *mac;
4981         struct halmac_api *api;
4982         enum halmac_ret_status status;
4983         u32 addr;
4984
4985
4986         mac = dvobj_to_halmac(d);
4987         api = HALMAC_GET_API(mac);
4988
4989         status = api->halmac_get_sdio_tx_addr(mac, desc, size, &addr);
4990         if (HALMAC_RET_SUCCESS != status)
4991                 return 0;
4992
4993         return addr;
4994 }
4995
4996 int rtw_halmac_sdio_tx_allowed(struct dvobj_priv *d, u8 *buf, u32 size)
4997 {
4998         struct halmac_adapter *mac;
4999         struct halmac_api *api;
5000         enum halmac_ret_status status;
5001
5002
5003         mac = dvobj_to_halmac(d);
5004         api = HALMAC_GET_API(mac);
5005
5006         status = api->halmac_tx_allowed_sdio(mac, buf, size);
5007         if (HALMAC_RET_SUCCESS != status)
5008                 return -1;
5009
5010         return 0;
5011 }
5012
5013 u32 rtw_halmac_sdio_get_rx_addr(struct dvobj_priv *d, u8 *seq)
5014 {
5015         u8 id;
5016
5017 #define RTW_SDIO_ADDR_RX_RX0FF_PRFIX    0x0E000
5018 #define RTW_SDIO_ADDR_RX_RX0FF_GEN(a)   (RTW_SDIO_ADDR_RX_RX0FF_PRFIX|(a&0x3))
5019
5020         id = *seq;
5021         (*seq)++;
5022         return RTW_SDIO_ADDR_RX_RX0FF_GEN(id);
5023 }
5024 #endif /* CONFIG_SDIO_HCI */
5025
5026 #ifdef CONFIG_USB_HCI
5027 u8 rtw_halmac_usb_get_bulkout_id(struct dvobj_priv *d, u8 *buf, u32 size)
5028 {
5029         struct halmac_adapter *mac;
5030         struct halmac_api *api;
5031         enum halmac_ret_status status;
5032         u8 bulkout_id;
5033
5034
5035         mac = dvobj_to_halmac(d);
5036         api = HALMAC_GET_API(mac);
5037
5038         status = api->halmac_get_usb_bulkout_id(mac, buf, size, &bulkout_id);
5039         if (HALMAC_RET_SUCCESS != status)
5040                 return 0;
5041
5042         return bulkout_id;
5043 }
5044
5045 /**
5046  * rtw_halmac_usb_get_txagg_desc_num() - MAX descriptor number in one bulk for TX
5047  * @d:          struct dvobj_priv*
5048  * @size:       TX FIFO size, unit is byte.
5049  *
5050  * Get MAX descriptor number in one bulk out from HALMAC.
5051  *
5052  * Rteurn 0 for OK, otherwise fail.
5053  */
5054 int rtw_halmac_usb_get_txagg_desc_num(struct dvobj_priv *d, u8 *num)
5055 {
5056         struct halmac_adapter *halmac;
5057         struct halmac_api *api;
5058         enum halmac_ret_status status;
5059         u8 val = 0;
5060
5061
5062         halmac = dvobj_to_halmac(d);
5063         api = HALMAC_GET_API(halmac);
5064
5065         status = api->halmac_get_hw_value(halmac, HALMAC_HW_USB_TXAGG_DESC_NUM, &val);
5066         if (status != HALMAC_RET_SUCCESS)
5067                 return -1;
5068
5069         *num = val;
5070
5071         return 0;
5072 }
5073
5074 static inline enum halmac_usb_mode _usb_mode_drv2halmac(enum RTW_USB_SPEED usb_mode)
5075 {
5076         enum halmac_usb_mode halmac_usb_mode = HALMAC_USB_MODE_U2;
5077
5078         switch (usb_mode) {
5079         case RTW_USB_SPEED_2:
5080                 halmac_usb_mode = HALMAC_USB_MODE_U2;
5081                 break;
5082         case RTW_USB_SPEED_3:
5083                 halmac_usb_mode = HALMAC_USB_MODE_U3;
5084                 break;
5085         default:
5086                 halmac_usb_mode = HALMAC_USB_MODE_U2;
5087                 break;
5088         }
5089
5090         return halmac_usb_mode;
5091 }
5092
5093 u8 rtw_halmac_switch_usb_mode(struct dvobj_priv *d, enum RTW_USB_SPEED usb_mode)
5094 {
5095         PADAPTER adapter;
5096         struct halmac_adapter *mac;
5097         struct halmac_api *api;
5098         enum halmac_ret_status status;
5099         enum halmac_usb_mode halmac_usb_mode;
5100
5101         adapter = dvobj_get_primary_adapter(d);
5102         mac = dvobj_to_halmac(d);
5103         api = HALMAC_GET_API(mac);
5104         halmac_usb_mode = _usb_mode_drv2halmac(usb_mode);
5105         status = api->halmac_set_hw_value(mac, HALMAC_HW_USB_MODE, (void *)&halmac_usb_mode);
5106
5107         if (HALMAC_RET_SUCCESS != status)
5108                 return _FAIL;
5109
5110         return _SUCCESS;
5111 }
5112 #endif /* CONFIG_USB_HCI */
5113
5114 #ifdef CONFIG_BEAMFORMING
5115 #ifdef RTW_BEAMFORMING_VERSION_2
5116 int rtw_halmac_bf_add_mu_bfer(struct dvobj_priv *d, u16 paid, u16 csi_para,
5117                 u16 my_aid, enum halmac_csi_seg_len sel, u8 *addr)
5118 {
5119         struct halmac_adapter *mac;
5120         struct halmac_api *api;
5121         enum halmac_ret_status status;
5122         struct halmac_mu_bfer_init_para param;
5123
5124
5125         mac = dvobj_to_halmac(d);
5126         api = HALMAC_GET_API(mac);
5127
5128         _rtw_memset(&param, 0, sizeof(param));
5129         param.paid = paid;
5130         param.csi_para = csi_para;
5131         param.my_aid = my_aid;
5132         param.csi_length_sel = sel;
5133         _rtw_memcpy(param.bfer_address.addr, addr, 6);
5134
5135         status = api->halmac_mu_bfer_entry_init(mac, &param);
5136         if (status != HALMAC_RET_SUCCESS)
5137                 return -1;
5138
5139         return 0;
5140 }
5141
5142 int rtw_halmac_bf_del_mu_bfer(struct dvobj_priv *d)
5143 {
5144         struct halmac_adapter *mac;
5145         struct halmac_api *api;
5146         enum halmac_ret_status status;
5147
5148
5149         mac = dvobj_to_halmac(d);
5150         api = HALMAC_GET_API(mac);
5151
5152         status = api->halmac_mu_bfer_entry_del(mac);
5153         if (status != HALMAC_RET_SUCCESS)
5154                 return -1;
5155
5156         return 0;
5157 }
5158
5159
5160 int rtw_halmac_bf_cfg_sounding(struct dvobj_priv *d,
5161                 enum halmac_snd_role role, enum halmac_data_rate rate)
5162 {
5163         struct halmac_adapter *mac;
5164         struct halmac_api *api;
5165         enum halmac_ret_status status;
5166
5167
5168         mac = dvobj_to_halmac(d);
5169         api = HALMAC_GET_API(mac);
5170
5171         status = api->halmac_cfg_sounding(mac, role, rate);
5172         if (status != HALMAC_RET_SUCCESS)
5173                 return -1;
5174
5175         return 0;
5176 }
5177
5178 int rtw_halmac_bf_del_sounding(struct dvobj_priv *d,
5179                 enum halmac_snd_role role)
5180 {
5181         struct halmac_adapter *mac;
5182         struct halmac_api *api;
5183         enum halmac_ret_status status;
5184
5185
5186         mac = dvobj_to_halmac(d);
5187         api = HALMAC_GET_API(mac);
5188
5189         status = api->halmac_del_sounding(mac, role);
5190         if (status != HALMAC_RET_SUCCESS)
5191                 return -1;
5192
5193         return 0;
5194 }
5195
5196 int rtw_halmac_bf_cfg_csi_rate(struct dvobj_priv *d,
5197                 u8 rssi, u8 current_rate, u8 fixrate_en,
5198                 u8 *new_rate)
5199 {
5200         struct halmac_adapter *mac;
5201         struct halmac_api *api;
5202         enum halmac_ret_status status;
5203
5204
5205         mac = dvobj_to_halmac(d);
5206         api = HALMAC_GET_API(mac);
5207
5208         status = api->halmac_cfg_csi_rate(mac,
5209                         rssi, current_rate, fixrate_en, new_rate);
5210         if (status != HALMAC_RET_SUCCESS)
5211                 return -1;
5212
5213         return 0;
5214 }
5215
5216 int rtw_halmac_bf_cfg_mu_mimo(struct dvobj_priv *d, enum halmac_snd_role role,
5217                 u8 *sounding_sts, u16 grouping_bitmap, u8 mu_tx_en,
5218                 u32 *given_gid_tab, u32 *given_user_pos)
5219 {
5220         struct halmac_adapter *mac;
5221         struct halmac_api *api;
5222         enum halmac_ret_status status;
5223         struct halmac_cfg_mumimo_para param;
5224
5225
5226         mac = dvobj_to_halmac(d);
5227         api = HALMAC_GET_API(mac);
5228
5229         _rtw_memset(&param, 0, sizeof(param));
5230
5231         param.role = role;
5232         param.grouping_bitmap = grouping_bitmap;
5233         param.mu_tx_en = mu_tx_en;
5234
5235         if (sounding_sts)
5236                 _rtw_memcpy(param.sounding_sts, sounding_sts, 6);
5237
5238         if (given_gid_tab)
5239                 _rtw_memcpy(param.given_gid_tab, given_gid_tab, 8);
5240
5241         if (given_user_pos)
5242                 _rtw_memcpy(param.given_user_pos, given_user_pos, 16);
5243
5244         status = api->halmac_cfg_mumimo(mac, &param);
5245         if (status != HALMAC_RET_SUCCESS)
5246                 return -1;
5247
5248         return 0;
5249 }
5250
5251 #endif /* RTW_BEAMFORMING_VERSION_2 */
5252 #endif /* CONFIG_BEAMFORMING */