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