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