1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2010  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  * The full GNU General Public License is included in this distribution in the
19  * file called LICENSE.
20  *
21  * Contact Information:
22  * wlanfae <wlanfae@realtek.com>
23  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24  * Hsinchu 300, Taiwan.
25  *
26  * Larry Finger <Larry.Finger@lwfinger.net>
27  *
28  *****************************************************************************/
29 
30 #include "../wifi.h"
31 #include "../pci.h"
32 #include "../base.h"
33 #include "reg.h"
34 #include "def.h"
35 #include "fw.h"
36 #include "sw.h"
37 
_rtl92d_is_fw_downloaded(struct rtl_priv * rtlpriv)38 static bool _rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv)
39 {
40 	return (rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY) ?
41 		true : false;
42 }
43 
_rtl92d_enable_fw_download(struct ieee80211_hw * hw,bool enable)44 static void _rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable)
45 {
46 	struct rtl_priv *rtlpriv = rtl_priv(hw);
47 	u8 tmp;
48 
49 	if (enable) {
50 		tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
51 		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
52 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
53 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
54 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
55 		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
56 	} else {
57 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
58 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
59 		/* Reserved for fw extension.
60 		 * 0x81[7] is used for mac0 status ,
61 		 * so don't write this reg here
62 		 * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);*/
63 	}
64 }
65 
_rtl92d_fw_block_write(struct ieee80211_hw * hw,const u8 * buffer,u32 size)66 static void _rtl92d_fw_block_write(struct ieee80211_hw *hw,
67 				   const u8 *buffer, u32 size)
68 {
69 	struct rtl_priv *rtlpriv = rtl_priv(hw);
70 	u32 blocksize = sizeof(u32);
71 	u8 *bufferptr = (u8 *) buffer;
72 	u32 *pu4BytePtr = (u32 *) buffer;
73 	u32 i, offset, blockCount, remainSize;
74 
75 	blockCount = size / blocksize;
76 	remainSize = size % blocksize;
77 	for (i = 0; i < blockCount; i++) {
78 		offset = i * blocksize;
79 		rtl_write_dword(rtlpriv, (FW_8192D_START_ADDRESS + offset),
80 				*(pu4BytePtr + i));
81 	}
82 	if (remainSize) {
83 		offset = blockCount * blocksize;
84 		bufferptr += offset;
85 		for (i = 0; i < remainSize; i++) {
86 			rtl_write_byte(rtlpriv, (FW_8192D_START_ADDRESS +
87 						 offset + i), *(bufferptr + i));
88 		}
89 	}
90 }
91 
_rtl92d_fw_page_write(struct ieee80211_hw * hw,u32 page,const u8 * buffer,u32 size)92 static void _rtl92d_fw_page_write(struct ieee80211_hw *hw,
93 				  u32 page, const u8 *buffer, u32 size)
94 {
95 	struct rtl_priv *rtlpriv = rtl_priv(hw);
96 	u8 value8;
97 	u8 u8page = (u8) (page & 0x07);
98 
99 	value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
100 	rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
101 	_rtl92d_fw_block_write(hw, buffer, size);
102 }
103 
_rtl92d_fill_dummy(u8 * pfwbuf,u32 * pfwlen)104 static void _rtl92d_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
105 {
106 	u32 fwlen = *pfwlen;
107 	u8 remain = (u8) (fwlen % 4);
108 
109 	remain = (remain == 0) ? 0 : (4 - remain);
110 	while (remain > 0) {
111 		pfwbuf[fwlen] = 0;
112 		fwlen++;
113 		remain--;
114 	}
115 	*pfwlen = fwlen;
116 }
117 
_rtl92d_write_fw(struct ieee80211_hw * hw,enum version_8192d version,u8 * buffer,u32 size)118 static void _rtl92d_write_fw(struct ieee80211_hw *hw,
119 			     enum version_8192d version, u8 *buffer, u32 size)
120 {
121 	struct rtl_priv *rtlpriv = rtl_priv(hw);
122 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
123 	u8 *bufferPtr = (u8 *) buffer;
124 	u32 pagenums, remainSize;
125 	u32 page, offset;
126 
127 	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
128 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
129 		_rtl92d_fill_dummy(bufferPtr, &size);
130 	pagenums = size / FW_8192D_PAGE_SIZE;
131 	remainSize = size % FW_8192D_PAGE_SIZE;
132 	if (pagenums > 8) {
133 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
134 			 ("Page numbers should not greater then 8\n"));
135 	}
136 	for (page = 0; page < pagenums; page++) {
137 		offset = page * FW_8192D_PAGE_SIZE;
138 		_rtl92d_fw_page_write(hw, page, (bufferPtr + offset),
139 				      FW_8192D_PAGE_SIZE);
140 	}
141 	if (remainSize) {
142 		offset = pagenums * FW_8192D_PAGE_SIZE;
143 		page = pagenums;
144 		_rtl92d_fw_page_write(hw, page, (bufferPtr + offset),
145 				      remainSize);
146 	}
147 }
148 
_rtl92d_fw_free_to_go(struct ieee80211_hw * hw)149 static int _rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
150 {
151 	struct rtl_priv *rtlpriv = rtl_priv(hw);
152 	u32 counter = 0;
153 	u32 value32;
154 
155 	do {
156 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
157 	} while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
158 		 (!(value32 & FWDL_ChkSum_rpt)));
159 	if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
160 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
161 			 ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
162 			 value32));
163 		return -EIO;
164 	}
165 	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
166 		 ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32));
167 	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
168 	value32 |= MCUFWDL_RDY;
169 	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
170 	return 0;
171 }
172 
rtl92d_firmware_selfreset(struct ieee80211_hw * hw)173 void rtl92d_firmware_selfreset(struct ieee80211_hw *hw)
174 {
175 	struct rtl_priv *rtlpriv = rtl_priv(hw);
176 	u8 u1b_tmp;
177 	u8 delay = 100;
178 
179 	/* Set (REG_HMETFR + 3) to  0x20 is reset 8051 */
180 	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
181 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
182 	while (u1b_tmp & BIT(2)) {
183 		delay--;
184 		if (delay == 0)
185 			break;
186 		udelay(50);
187 		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
188 	}
189 	RT_ASSERT((delay > 0), ("8051 reset failed!\n"));
190 	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
191 		 ("=====> 8051 reset success (%d) .\n", delay));
192 }
193 
_rtl92d_fw_init(struct ieee80211_hw * hw)194 static int _rtl92d_fw_init(struct ieee80211_hw *hw)
195 {
196 	struct rtl_priv *rtlpriv = rtl_priv(hw);
197 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
198 	u32 counter;
199 
200 	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, ("FW already have download\n"));
201 	/* polling for FW ready */
202 	counter = 0;
203 	do {
204 		if (rtlhal->interfaceindex == 0) {
205 			if (rtl_read_byte(rtlpriv, FW_MAC0_READY) &
206 			    MAC0_READY) {
207 				RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
208 					 ("Polling FW ready success!! "
209 					 "REG_MCUFWDL: 0x%x .\n",
210 					 rtl_read_byte(rtlpriv,
211 					 FW_MAC0_READY)));
212 				return 0;
213 			}
214 			udelay(5);
215 		} else {
216 			if (rtl_read_byte(rtlpriv, FW_MAC1_READY) &
217 			    MAC1_READY) {
218 				RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
219 					 ("Polling FW ready success!! "
220 					 "REG_MCUFWDL: 0x%x .\n",
221 					 rtl_read_byte(rtlpriv,
222 						       FW_MAC1_READY)));
223 				return 0;
224 			}
225 			udelay(5);
226 		}
227 	} while (counter++ < POLLING_READY_TIMEOUT_COUNT);
228 
229 	if (rtlhal->interfaceindex == 0) {
230 		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
231 			 ("Polling FW ready fail!! MAC0 FW init not ready: "
232 			 "0x%x .\n",
233 			 rtl_read_byte(rtlpriv, FW_MAC0_READY)));
234 	} else {
235 		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
236 			 ("Polling FW ready fail!! MAC1 FW init not ready: "
237 			 "0x%x .\n",
238 			 rtl_read_byte(rtlpriv, FW_MAC1_READY)));
239 	}
240 	RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
241 		 ("Polling FW ready fail!! REG_MCUFWDL:0x%08ul .\n",
242 		 rtl_read_dword(rtlpriv, REG_MCUFWDL)));
243 	return -1;
244 }
245 
rtl92d_download_fw(struct ieee80211_hw * hw)246 int rtl92d_download_fw(struct ieee80211_hw *hw)
247 {
248 	struct rtl_priv *rtlpriv = rtl_priv(hw);
249 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
250 	u8 *pfwheader;
251 	u8 *pfwdata;
252 	u32 fwsize;
253 	int err;
254 	enum version_8192d version = rtlhal->version;
255 	u8 value;
256 	u32 count;
257 	bool fw_downloaded = false, fwdl_in_process = false;
258 	unsigned long flags;
259 
260 	if (!rtlhal->pfirmware)
261 		return 1;
262 	fwsize = rtlhal->fwsize;
263 	pfwheader = (u8 *) rtlhal->pfirmware;
264 	pfwdata = (u8 *) rtlhal->pfirmware;
265 	rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
266 	rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
267 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, (" FirmwareVersion(%d),"
268 		 "FirmwareSubVersion(%d), Signature(%#x)\n",
269 		 rtlhal->fw_version,	rtlhal->fw_subversion,
270 		 GET_FIRMWARE_HDR_SIGNATURE(pfwheader)));
271 	if (IS_FW_HEADER_EXIST(pfwheader)) {
272 		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
273 			 ("Shift 32 bytes for FW header!!\n"));
274 		pfwdata = pfwdata + 32;
275 		fwsize = fwsize - 32;
276 	}
277 
278 	spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
279 	fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
280 	if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
281 		fwdl_in_process = true;
282 	else
283 		fwdl_in_process = false;
284 	if (fw_downloaded) {
285 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
286 		goto exit;
287 	} else if (fwdl_in_process) {
288 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
289 		for (count = 0; count < 5000; count++) {
290 			udelay(500);
291 			spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
292 			fw_downloaded = _rtl92d_is_fw_downloaded(rtlpriv);
293 			if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
294 				fwdl_in_process = true;
295 			else
296 				fwdl_in_process = false;
297 			spin_unlock_irqrestore(&globalmutex_for_fwdownload,
298 					       flags);
299 			if (fw_downloaded)
300 				goto exit;
301 			else if (!fwdl_in_process)
302 				break;
303 			else
304 				RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
305 					 ("Wait for another mac "
306 					 "download fw\n"));
307 		}
308 		spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
309 		value = rtl_read_byte(rtlpriv, 0x1f);
310 		value |= BIT(5);
311 		rtl_write_byte(rtlpriv, 0x1f, value);
312 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
313 	} else {
314 		value = rtl_read_byte(rtlpriv, 0x1f);
315 		value |= BIT(5);
316 		rtl_write_byte(rtlpriv, 0x1f, value);
317 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
318 	}
319 
320 	/* If 8051 is running in RAM code, driver should
321 	 * inform Fw to reset by itself, or it will cause
322 	 * download Fw fail.*/
323 	/* 8051 RAM code */
324 	if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
325 		rtl92d_firmware_selfreset(hw);
326 		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
327 	}
328 	_rtl92d_enable_fw_download(hw, true);
329 	_rtl92d_write_fw(hw, version, pfwdata, fwsize);
330 	_rtl92d_enable_fw_download(hw, false);
331 	spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
332 	err = _rtl92d_fw_free_to_go(hw);
333 	/* download fw over,clear 0x1f[5] */
334 	value = rtl_read_byte(rtlpriv, 0x1f);
335 	value &= (~BIT(5));
336 	rtl_write_byte(rtlpriv, 0x1f, value);
337 	spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
338 	if (err) {
339 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
340 			 ("fw is not ready to run!\n"));
341 		goto exit;
342 	} else {
343 		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
344 			 ("fw is ready to run!\n"));
345 	}
346 exit:
347 	err = _rtl92d_fw_init(hw);
348 	return err;
349 }
350 
_rtl92d_check_fw_read_last_h2c(struct ieee80211_hw * hw,u8 boxnum)351 static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
352 {
353 	struct rtl_priv *rtlpriv = rtl_priv(hw);
354 	u8 val_hmetfr;
355 	bool result = false;
356 
357 	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
358 	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
359 		result = true;
360 	return result;
361 }
362 
_rtl92d_fill_h2c_command(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmdbuffer)363 static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw,
364 			      u8 element_id, u32 cmd_len, u8 *cmdbuffer)
365 {
366 	struct rtl_priv *rtlpriv = rtl_priv(hw);
367 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
368 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
369 	u8 boxnum;
370 	u16 box_reg = 0, box_extreg = 0;
371 	u8 u1b_tmp;
372 	bool isfw_read = false;
373 	u8 buf_index = 0;
374 	bool bwrite_sucess = false;
375 	u8 wait_h2c_limmit = 100;
376 	u8 wait_writeh2c_limmit = 100;
377 	u8 boxcontent[4], boxextcontent[2];
378 	u32 h2c_waitcounter = 0;
379 	unsigned long flag;
380 	u8 idx;
381 
382 	if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) {
383 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
384 			 ("Return as RF is off!!!\n"));
385 		return;
386 	}
387 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
388 	while (true) {
389 		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
390 		if (rtlhal->h2c_setinprogress) {
391 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
392 				 ("H2C set in progress! Wait to set.."
393 				 "element_id(%d).\n", element_id));
394 
395 			while (rtlhal->h2c_setinprogress) {
396 				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
397 						       flag);
398 				h2c_waitcounter++;
399 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
400 					 ("Wait 100 us (%d times)...\n",
401 					 h2c_waitcounter));
402 				udelay(100);
403 
404 				if (h2c_waitcounter > 1000)
405 					return;
406 
407 				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
408 						  flag);
409 			}
410 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
411 		} else {
412 			rtlhal->h2c_setinprogress = true;
413 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
414 			break;
415 		}
416 	}
417 	while (!bwrite_sucess) {
418 		wait_writeh2c_limmit--;
419 		if (wait_writeh2c_limmit == 0) {
420 			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
421 				 ("Write H2C fail because no trigger "
422 				 "for FW INT!\n"));
423 			break;
424 		}
425 		boxnum = rtlhal->last_hmeboxnum;
426 		switch (boxnum) {
427 		case 0:
428 			box_reg = REG_HMEBOX_0;
429 			box_extreg = REG_HMEBOX_EXT_0;
430 			break;
431 		case 1:
432 			box_reg = REG_HMEBOX_1;
433 			box_extreg = REG_HMEBOX_EXT_1;
434 			break;
435 		case 2:
436 			box_reg = REG_HMEBOX_2;
437 			box_extreg = REG_HMEBOX_EXT_2;
438 			break;
439 		case 3:
440 			box_reg = REG_HMEBOX_3;
441 			box_extreg = REG_HMEBOX_EXT_3;
442 			break;
443 		default:
444 			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
445 				 ("switch case not process\n"));
446 			break;
447 		}
448 		isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
449 		while (!isfw_read) {
450 			wait_h2c_limmit--;
451 			if (wait_h2c_limmit == 0) {
452 				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
453 					 ("Wating too long for FW read "
454 					 "clear HMEBox(%d)!\n", boxnum));
455 				break;
456 			}
457 			udelay(10);
458 			isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
459 			u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
460 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
461 				 ("Wating for FW read clear HMEBox(%d)!!! "
462 				 "0x1BF = %2x\n", boxnum, u1b_tmp));
463 		}
464 		if (!isfw_read) {
465 			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
466 				 ("Write H2C register BOX[%d] fail!!!!! "
467 				 "Fw do not read.\n", boxnum));
468 			break;
469 		}
470 		memset(boxcontent, 0, sizeof(boxcontent));
471 		memset(boxextcontent, 0, sizeof(boxextcontent));
472 		boxcontent[0] = element_id;
473 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
474 			 ("Write element_id box_reg(%4x) = %2x\n",
475 			 box_reg, element_id));
476 		switch (cmd_len) {
477 		case 1:
478 			boxcontent[0] &= ~(BIT(7));
479 			memcpy(boxcontent + 1, cmdbuffer + buf_index, 1);
480 			for (idx = 0; idx < 4; idx++)
481 				rtl_write_byte(rtlpriv, box_reg + idx,
482 					       boxcontent[idx]);
483 			break;
484 		case 2:
485 			boxcontent[0] &= ~(BIT(7));
486 			memcpy(boxcontent + 1, cmdbuffer + buf_index, 2);
487 			for (idx = 0; idx < 4; idx++)
488 				rtl_write_byte(rtlpriv, box_reg + idx,
489 					       boxcontent[idx]);
490 			break;
491 		case 3:
492 			boxcontent[0] &= ~(BIT(7));
493 			memcpy(boxcontent + 1, cmdbuffer + buf_index, 3);
494 			for (idx = 0; idx < 4; idx++)
495 				rtl_write_byte(rtlpriv, box_reg + idx,
496 					       boxcontent[idx]);
497 			break;
498 		case 4:
499 			boxcontent[0] |= (BIT(7));
500 			memcpy(boxextcontent, cmdbuffer + buf_index, 2);
501 			memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 2);
502 			for (idx = 0; idx < 2; idx++)
503 				rtl_write_byte(rtlpriv, box_extreg + idx,
504 					       boxextcontent[idx]);
505 			for (idx = 0; idx < 4; idx++)
506 				rtl_write_byte(rtlpriv, box_reg + idx,
507 					       boxcontent[idx]);
508 			break;
509 		case 5:
510 			boxcontent[0] |= (BIT(7));
511 			memcpy(boxextcontent, cmdbuffer + buf_index, 2);
512 			memcpy(boxcontent + 1, cmdbuffer + buf_index + 2, 3);
513 			for (idx = 0; idx < 2; idx++)
514 				rtl_write_byte(rtlpriv, box_extreg + idx,
515 					       boxextcontent[idx]);
516 			for (idx = 0; idx < 4; idx++)
517 				rtl_write_byte(rtlpriv, box_reg + idx,
518 					       boxcontent[idx]);
519 			break;
520 		default:
521 			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
522 				("switch case not process\n"));
523 			break;
524 		}
525 		bwrite_sucess = true;
526 		rtlhal->last_hmeboxnum = boxnum + 1;
527 		if (rtlhal->last_hmeboxnum == 4)
528 			rtlhal->last_hmeboxnum = 0;
529 		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
530 			 ("pHalData->last_hmeboxnum  = %d\n",
531 			  rtlhal->last_hmeboxnum));
532 	}
533 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
534 	rtlhal->h2c_setinprogress = false;
535 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
536 	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
537 }
538 
rtl92d_fill_h2c_cmd(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmdbuffer)539 void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
540 			 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
541 {
542 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
543 	u32 tmp_cmdbuf[2];
544 
545 	if (rtlhal->fw_ready == false) {
546 		RT_ASSERT(false, ("return H2C cmd because of Fw "
547 				  "download fail!!!\n"));
548 		return;
549 	}
550 	memset(tmp_cmdbuf, 0, 8);
551 	memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
552 	_rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
553 	return;
554 }
555 
rtl92d_set_fw_pwrmode_cmd(struct ieee80211_hw * hw,u8 mode)556 void rtl92d_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
557 {
558 	struct rtl_priv *rtlpriv = rtl_priv(hw);
559 	u8 u1_h2c_set_pwrmode[3] = { 0 };
560 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
561 
562 	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
563 	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
564 	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
565 	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
566 					      ppsc->reg_max_lps_awakeintvl);
567 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
568 		      "rtl92d_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
569 		      u1_h2c_set_pwrmode, 3);
570 	rtl92d_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
571 }
572 
_rtl92d_cmd_send_packet(struct ieee80211_hw * hw,struct sk_buff * skb)573 static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
574 				    struct sk_buff *skb)
575 {
576 	struct rtl_priv *rtlpriv = rtl_priv(hw);
577 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
578 	struct rtl8192_tx_ring *ring;
579 	struct rtl_tx_desc *pdesc;
580 	u8 idx = 0;
581 	unsigned long flags;
582 	struct sk_buff *pskb;
583 
584 	ring = &rtlpci->tx_ring[BEACON_QUEUE];
585 	pskb = __skb_dequeue(&ring->queue);
586 	if (pskb)
587 		kfree_skb(pskb);
588 	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
589 	pdesc = &ring->desc[idx];
590 	/* discard output from call below */
591 	rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
592 	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
593 	__skb_queue_tail(&ring->queue, skb);
594 	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
595 	rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
596 	return true;
597 }
598 
599 #define BEACON_PG		0	/*->1 */
600 #define PSPOLL_PG		2
601 #define NULL_PG			3
602 #define PROBERSP_PG		4	/*->5 */
603 #define TOTAL_RESERVED_PKT_LEN	768
604 
605 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
606 	/* page 0 beacon */
607 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
608 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
609 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
610 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
612 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
613 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
614 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
615 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
616 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
617 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
621 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623 
624 	/* page 1 beacon */
625 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 	0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
638 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641 
642 	/* page 2  ps-poll */
643 	0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
644 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
645 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 	0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
656 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
657 	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
659 
660 	/* page 3  null */
661 	0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
662 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
663 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
664 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
665 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
666 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 	0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
674 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
675 	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677 
678 	/* page 4  probe_resp */
679 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
680 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
681 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
682 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
683 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
684 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
685 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
686 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
687 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
688 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
689 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
693 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695 
696 	/* page 5  probe_resp */
697 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
698 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
699 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
701 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
704 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
707 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
708 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
711 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
713 };
714 
rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw * hw,bool dl_finished)715 void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
716 {
717 	struct rtl_priv *rtlpriv = rtl_priv(hw);
718 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
719 	struct sk_buff *skb = NULL;
720 	u32 totalpacketlen;
721 	bool rtstatus;
722 	u8 u1RsvdPageLoc[3] = { 0 };
723 	bool dlok = false;
724 	u8 *beacon;
725 	u8 *p_pspoll;
726 	u8 *nullfunc;
727 	u8 *p_probersp;
728 	/*---------------------------------------------------------
729 						(1) beacon
730 	---------------------------------------------------------*/
731 	beacon = &reserved_page_packet[BEACON_PG * 128];
732 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
733 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
734 	/*-------------------------------------------------------
735 						(2) ps-poll
736 	--------------------------------------------------------*/
737 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
738 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
739 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
740 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
741 	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
742 	/*--------------------------------------------------------
743 						(3) null data
744 	---------------------------------------------------------*/
745 	nullfunc = &reserved_page_packet[NULL_PG * 128];
746 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
747 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
748 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
749 	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
750 	/*---------------------------------------------------------
751 						(4) probe response
752 	----------------------------------------------------------*/
753 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
754 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
755 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
756 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
757 	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
758 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
759 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
760 		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
761 		      &reserved_page_packet[0], totalpacketlen);
762 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
763 		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
764 		      u1RsvdPageLoc, 3);
765 	skb = dev_alloc_skb(totalpacketlen);
766 	memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet,
767 		totalpacketlen);
768 	rtstatus = _rtl92d_cmd_send_packet(hw, skb);
769 
770 	if (rtstatus)
771 		dlok = true;
772 	if (dlok) {
773 		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
774 			("Set RSVD page location to Fw.\n"));
775 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
776 			      "H2C_RSVDPAGE:\n", u1RsvdPageLoc, 3);
777 		rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
778 			sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
779 	} else
780 		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
781 			("Set RSVD page location to Fw FAIL!!!!!!.\n"));
782 }
783 
rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw * hw,u8 mstatus)784 void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
785 {
786 	u8 u1_joinbssrpt_parm[1] = {0};
787 
788 	SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
789 	rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
790 }
791