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