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