1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2011 Realtek Corporation. */
3
4 #include "../include/osdep_service.h"
5 #include "../include/drv_types.h"
6
7 #include "../include/hal_intf.h"
8 #include "../include/hal_com.h"
9 #include "../include/rtl8188e_hal.h"
10
11 #define _HAL_INIT_C_
12
dump_chip_info(struct HAL_VERSION chip_vers)13 void dump_chip_info(struct HAL_VERSION chip_vers)
14 {
15 uint cnt = 0;
16 char buf[128];
17
18 cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8188E_");
19 cnt += sprintf((buf + cnt), "%s_", IS_NORMAL_CHIP(chip_vers) ?
20 "Normal_Chip" : "Test_Chip");
21 cnt += sprintf((buf + cnt), "%s_", IS_CHIP_VENDOR_TSMC(chip_vers) ?
22 "TSMC" : "UMC");
23
24 switch (chip_vers.CUTVersion) {
25 case A_CUT_VERSION:
26 cnt += sprintf((buf + cnt), "A_CUT_");
27 break;
28 case B_CUT_VERSION:
29 cnt += sprintf((buf + cnt), "B_CUT_");
30 break;
31 case C_CUT_VERSION:
32 cnt += sprintf((buf + cnt), "C_CUT_");
33 break;
34 case D_CUT_VERSION:
35 cnt += sprintf((buf + cnt), "D_CUT_");
36 break;
37 case E_CUT_VERSION:
38 cnt += sprintf((buf + cnt), "E_CUT_");
39 break;
40 default:
41 cnt += sprintf((buf + cnt), "UNKNOWN_CUT(%d)_", chip_vers.CUTVersion);
42 break;
43 }
44
45 cnt += sprintf((buf + cnt), "1T1R_");
46
47 cnt += sprintf((buf + cnt), "RomVer(%d)\n", 0);
48
49 pr_info("%s", buf);
50 }
51
52 #define CHAN_PLAN_HW 0x80
53
54 u8 /* return the final channel plan decision */
hal_com_get_channel_plan(struct adapter * padapter,u8 hw_channel_plan,u8 sw_channel_plan,u8 def_channel_plan,bool load_fail)55 hal_com_get_channel_plan(struct adapter *padapter, u8 hw_channel_plan,
56 u8 sw_channel_plan, u8 def_channel_plan,
57 bool load_fail)
58 {
59 u8 sw_cfg;
60 u8 chnlplan;
61
62 sw_cfg = true;
63 if (!load_fail) {
64 if (!rtw_is_channel_plan_valid(sw_channel_plan))
65 sw_cfg = false;
66 if (hw_channel_plan & CHAN_PLAN_HW)
67 sw_cfg = false;
68 }
69
70 if (sw_cfg)
71 chnlplan = sw_channel_plan;
72 else
73 chnlplan = hw_channel_plan & (~CHAN_PLAN_HW);
74
75 if (!rtw_is_channel_plan_valid(chnlplan))
76 chnlplan = def_channel_plan;
77
78 return chnlplan;
79 }
80
MRateToHwRate(u8 rate)81 u8 MRateToHwRate(u8 rate)
82 {
83 u8 ret = DESC_RATE1M;
84
85 switch (rate) {
86 /* CCK and OFDM non-HT rates */
87 case IEEE80211_CCK_RATE_1MB:
88 ret = DESC_RATE1M;
89 break;
90 case IEEE80211_CCK_RATE_2MB:
91 ret = DESC_RATE2M;
92 break;
93 case IEEE80211_CCK_RATE_5MB:
94 ret = DESC_RATE5_5M;
95 break;
96 case IEEE80211_CCK_RATE_11MB:
97 ret = DESC_RATE11M;
98 break;
99 case IEEE80211_OFDM_RATE_6MB:
100 ret = DESC_RATE6M;
101 break;
102 case IEEE80211_OFDM_RATE_9MB:
103 ret = DESC_RATE9M;
104 break;
105 case IEEE80211_OFDM_RATE_12MB:
106 ret = DESC_RATE12M;
107 break;
108 case IEEE80211_OFDM_RATE_18MB:
109 ret = DESC_RATE18M;
110 break;
111 case IEEE80211_OFDM_RATE_24MB:
112 ret = DESC_RATE24M;
113 break;
114 case IEEE80211_OFDM_RATE_36MB:
115 ret = DESC_RATE36M;
116 break;
117 case IEEE80211_OFDM_RATE_48MB:
118 ret = DESC_RATE48M;
119 break;
120 case IEEE80211_OFDM_RATE_54MB:
121 ret = DESC_RATE54M;
122 break;
123 default:
124 break;
125 }
126 return ret;
127 }
128
HalSetBrateCfg(struct adapter * adapt,u8 * brates,u16 * rate_cfg)129 void HalSetBrateCfg(struct adapter *adapt, u8 *brates, u16 *rate_cfg)
130 {
131 u8 i, is_brate, brate;
132
133 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
134 is_brate = brates[i] & IEEE80211_BASIC_RATE_MASK;
135 brate = brates[i] & 0x7f;
136
137 if (is_brate) {
138 switch (brate) {
139 case IEEE80211_CCK_RATE_1MB:
140 *rate_cfg |= RATE_1M;
141 break;
142 case IEEE80211_CCK_RATE_2MB:
143 *rate_cfg |= RATE_2M;
144 break;
145 case IEEE80211_CCK_RATE_5MB:
146 *rate_cfg |= RATE_5_5M;
147 break;
148 case IEEE80211_CCK_RATE_11MB:
149 *rate_cfg |= RATE_11M;
150 break;
151 case IEEE80211_OFDM_RATE_6MB:
152 *rate_cfg |= RATE_6M;
153 break;
154 case IEEE80211_OFDM_RATE_9MB:
155 *rate_cfg |= RATE_9M;
156 break;
157 case IEEE80211_OFDM_RATE_12MB:
158 *rate_cfg |= RATE_12M;
159 break;
160 case IEEE80211_OFDM_RATE_18MB:
161 *rate_cfg |= RATE_18M;
162 break;
163 case IEEE80211_OFDM_RATE_24MB:
164 *rate_cfg |= RATE_24M;
165 break;
166 case IEEE80211_OFDM_RATE_36MB:
167 *rate_cfg |= RATE_36M;
168 break;
169 case IEEE80211_OFDM_RATE_48MB:
170 *rate_cfg |= RATE_48M;
171 break;
172 case IEEE80211_OFDM_RATE_54MB:
173 *rate_cfg |= RATE_54M;
174 break;
175 }
176 }
177 }
178 }
179
one_out_pipe(struct adapter * adapter)180 static void one_out_pipe(struct adapter *adapter)
181 {
182 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
183
184 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
185 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
186 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0];/* BE */
187 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */
188
189 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
190 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
191 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
192 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
193 }
194
two_out_pipe(struct adapter * adapter,bool wifi_cfg)195 static void two_out_pipe(struct adapter *adapter, bool wifi_cfg)
196 {
197 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
198
199 if (wifi_cfg) { /* WMM */
200 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
201 /* 0, 1, 0, 1, 0, 0, 0, 0, 0}; */
202 /* 0:H, 1:L */
203
204 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1];/* VO */
205 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
206 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
207 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];/* BK */
208
209 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
210 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
211 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
212 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
213
214 } else {/* typical setting */
215 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
216 /* 1, 1, 0, 0, 0, 0, 0, 0, 0}; */
217 /* 0:H, 1:L */
218
219 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
220 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];/* VI */
221 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1];/* BE */
222 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
223
224 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
225 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
226 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
227 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
228 }
229 }
230
three_out_pipe(struct adapter * adapter,bool wifi_cfg)231 static void three_out_pipe(struct adapter *adapter, bool wifi_cfg)
232 {
233 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
234
235 if (wifi_cfg) {/* for WMM */
236 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
237 /* 1, 2, 1, 0, 0, 0, 0, 0, 0}; */
238 /* 0:H, 1:N, 2:L */
239
240 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
241 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
242 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
243 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1];/* BK */
244
245 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
246 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
247 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
248 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
249
250 } else {/* typical setting */
251 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
252 /* 2, 2, 1, 0, 0, 0, 0, 0, 0}; */
253 /* 0:H, 1:N, 2:L */
254
255 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];/* VO */
256 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1];/* VI */
257 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2];/* BE */
258 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2];/* BK */
259
260 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];/* BCN */
261 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];/* MGT */
262 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];/* HIGH */
263 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];/* TXCMD */
264 }
265 }
266
Hal_MappingOutPipe(struct adapter * adapter,u8 numoutpipe)267 bool Hal_MappingOutPipe(struct adapter *adapter, u8 numoutpipe)
268 {
269 struct registry_priv *pregistrypriv = &adapter->registrypriv;
270 bool wifi_cfg = pregistrypriv->wifi_spec;
271 bool result = true;
272
273 switch (numoutpipe) {
274 case 2:
275 two_out_pipe(adapter, wifi_cfg);
276 break;
277 case 3:
278 three_out_pipe(adapter, wifi_cfg);
279 break;
280 case 1:
281 one_out_pipe(adapter);
282 break;
283 default:
284 result = false;
285 break;
286 }
287 return result;
288 }
289
290 /*
291 * C2H event format:
292 * Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID
293 * BITS [127:120] [119:16] [15:8] [7:4] [3:0]
294 */
295
c2h_evt_read(struct adapter * adapter,u8 * buf)296 s32 c2h_evt_read(struct adapter *adapter, u8 *buf)
297 {
298 s32 ret = _FAIL;
299 struct c2h_evt_hdr *c2h_evt;
300 int i;
301 u8 trigger;
302
303 if (!buf)
304 goto exit;
305
306 ret = rtw_read8(adapter, REG_C2HEVT_CLEAR, &trigger);
307 if (ret)
308 return _FAIL;
309
310 if (trigger == C2H_EVT_HOST_CLOSE)
311 goto exit; /* Not ready */
312 else if (trigger != C2H_EVT_FW_CLOSE)
313 goto clear_evt; /* Not a valid value */
314
315 c2h_evt = (struct c2h_evt_hdr *)buf;
316
317 memset(c2h_evt, 0, 16);
318
319 ret = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL, buf);
320 if (ret) {
321 ret = _FAIL;
322 goto clear_evt;
323 }
324
325 ret = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1, buf + 1);
326 if (ret) {
327 ret = _FAIL;
328 goto clear_evt;
329 }
330 /* Read the content */
331 for (i = 0; i < c2h_evt->plen; i++) {
332 ret = rtw_read8(adapter, REG_C2HEVT_MSG_NORMAL +
333 sizeof(*c2h_evt) + i, c2h_evt->payload + i);
334 if (ret) {
335 ret = _FAIL;
336 goto clear_evt;
337 }
338 }
339
340 ret = _SUCCESS;
341
342 clear_evt:
343 /*
344 * Clear event to notify FW we have read the command.
345 * If this field isn't clear, the FW won't update the next
346 * command message.
347 */
348 rtw_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
349 exit:
350 return ret;
351 }
352