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