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