blob: db0d2d5fc61b30bb2d5c94a7a29af1f9c3a8d2a7 [file] [log] [blame]
Florian Schilhabel653e99e2010-07-14 14:47:27 +02001/******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
Jerry Chuang5f53d8c2009-05-21 22:16:02 -07003 *
Florian Schilhabel653e99e2010-07-14 14:47:27 +02004 * This program is distributed in the hope that it will be useful, but WITHOUT
5 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
7 * more details.
Jerry Chuang5f53d8c2009-05-21 22:16:02 -07008 *
Florian Schilhabel653e99e2010-07-14 14:47:27 +02009 * You should have received a copy of the GNU General Public License along with
10 * this program; if not, write to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
12 *
13 * The full GNU General Public License is included in this distribution in the
14 * file called LICENSE.
15 *
16 * Contact Information:
17 * wlanfae <wlanfae@realtek.com>
18******************************************************************************/
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070019
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070020#include "r8192U.h"
21#include "r8192S_firmware.h"
22#include <linux/unistd.h>
23
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070024#include "r8192S_hw.h"
25#include "r8192SU_HWImg.h"
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070026
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070027#include <linux/firmware.h>
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070028
29#define byte(x,n) ( (x >> (8 * n)) & 0xff )
30
31//
32// Description: This routine will intialize firmware. If any error occurs during the initialization
33// process, the routine shall terminate immediately and return fail.
34//
35// Arguments: The pointer of the adapter
36// Code address (Virtual address, should fill descriptor with physical address)
37// Code size
38// Created by Roger, 2008.04.10.
39//
Florian Schilhabel199ef62a2010-05-04 14:23:43 +020040bool FirmwareDownloadCode(struct net_device *dev,
41 u8 *code_virtual_address,
42 u32 buffer_len)
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070043{
Florian Schilhabel199ef62a2010-05-04 14:23:43 +020044 struct r8192_priv *priv = ieee80211_priv(dev);
45 bool rt_status = true;
46 /* Fragmentation might be required in 90/92 but not in 92S */
47 u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE;
48 u16 frag_length, frag_offset = 0;
49 struct sk_buff *skb;
50 unsigned char *seg_ptr;
51 cb_desc *tcb_desc;
52 u8 bLastIniPkt = 0;
53 u16 ExtraDescOffset = 0;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070054
Florian Schilhabel199ef62a2010-05-04 14:23:43 +020055 if (buffer_len >= MAX_FIRMWARE_CODE_SIZE - USB_HWDESC_HEADER_LEN) {
56 RT_TRACE(COMP_ERR, "(%s): Firmware exceeds"
57 " MAX_FIRMWARE_CODE_SIZE\n", __func__);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070058 goto cmdsend_downloadcode_fail;
59 }
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070060 ExtraDescOffset = USB_HWDESC_HEADER_LEN;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070061 do {
62 if((buffer_len-frag_offset) > frag_threshold)
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070063 frag_length = frag_threshold + ExtraDescOffset;
Florian Schilhabel199ef62a2010-05-04 14:23:43 +020064 else {
65 frag_length = (u16)(buffer_len -
66 frag_offset + ExtraDescOffset);
67 bLastIniPkt = 1;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070068 }
Florian Schilhabel199ef62a2010-05-04 14:23:43 +020069 /*
70 * Allocate skb buffer to contain firmware info
71 * and tx descriptor info.
72 */
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070073 skb = dev_alloc_skb(frag_length);
Florian Schilhabel199ef62a2010-05-04 14:23:43 +020074 if (skb == NULL) {
75 RT_TRACE(COMP_ERR, "(%s): unable to alloc skb buffer\n",
76 __func__);
77 goto cmdsend_downloadcode_fail;
78 }
79 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070080
81 tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
82 tcb_desc->queue_index = TXCMD_QUEUE;
83 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
84 tcb_desc->bLastIniPkt = bLastIniPkt;
85
86 skb_reserve(skb, ExtraDescOffset);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070087
Florian Schilhabel199ef62a2010-05-04 14:23:43 +020088 seg_ptr = (u8 *)skb_put(skb,
89 (u32)(frag_length - ExtraDescOffset));
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070090
Florian Schilhabel199ef62a2010-05-04 14:23:43 +020091 memcpy(seg_ptr, code_virtual_address + frag_offset,
92 (u32)(frag_length-ExtraDescOffset));
93
94 tcb_desc->txbuf_size = frag_length;
95
96 if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
97 (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
98 (priv->ieee80211->queue_stop)) {
Jerry Chuang5f53d8c2009-05-21 22:16:02 -070099 RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
100 skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
Florian Schilhabel199ef62a2010-05-04 14:23:43 +0200101 } else
102 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700103
104 frag_offset += (frag_length - ExtraDescOffset);
105
Florian Schilhabel199ef62a2010-05-04 14:23:43 +0200106 } while (frag_offset < buffer_len);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700107 return rt_status ;
108
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700109cmdsend_downloadcode_fail:
110 rt_status = false;
Florian Schilhabel199ef62a2010-05-04 14:23:43 +0200111 RT_TRACE(COMP_ERR, "(%s): failed\n", __func__);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700112 return rt_status;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700113}
114
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700115
Florian Schilhabele695b472010-05-04 14:24:12 +0200116bool FirmwareEnableCPU(struct net_device *dev)
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700117{
Florian Schilhabele695b472010-05-04 14:24:12 +0200118 bool rtStatus = true;
Florian Schilhabel199ef62a2010-05-04 14:23:43 +0200119 u8 tmpU1b, CPUStatus = 0;
120 u16 tmpU2b;
121 u32 iCheckTime = 200;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700122
Florian Schilhabel199ef62a2010-05-04 14:23:43 +0200123 /* Enable CPU. */
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700124 tmpU1b = read_nic_byte(dev, SYS_CLKR);
Florian Schilhabel199ef62a2010-05-04 14:23:43 +0200125 /* AFE source */
126 write_nic_byte(dev, SYS_CLKR, (tmpU1b|SYS_CPU_CLKSEL));
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700127 tmpU2b = read_nic_word(dev, SYS_FUNC_EN);
128 write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|FEN_CPUEN));
Florian Schilhabel199ef62a2010-05-04 14:23:43 +0200129 /* Poll IMEM Ready after CPU has refilled. */
130 do {
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700131 CPUStatus = read_nic_byte(dev, TCR);
Florian Schilhabel199ef62a2010-05-04 14:23:43 +0200132 if (CPUStatus & IMEM_RDY)
133 /* success */
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700134 break;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700135 udelay(100);
Florian Schilhabel199ef62a2010-05-04 14:23:43 +0200136 } while (iCheckTime--);
137 if (!(CPUStatus & IMEM_RDY)) {
Florian Schilhabele695b472010-05-04 14:24:12 +0200138 RT_TRACE(COMP_ERR, "%s(): failed to enable CPU", __func__);
139 rtStatus = false;
Florian Schilhabel199ef62a2010-05-04 14:23:43 +0200140 }
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700141 return rtStatus;
142}
143
144FIRMWARE_8192S_STATUS
145FirmwareGetNextStatus(FIRMWARE_8192S_STATUS FWCurrentStatus)
146{
147 FIRMWARE_8192S_STATUS NextFWStatus = 0;
148
149 switch(FWCurrentStatus)
150 {
151 case FW_STATUS_INIT:
152 NextFWStatus = FW_STATUS_LOAD_IMEM;
153 break;
154
155 case FW_STATUS_LOAD_IMEM:
156 NextFWStatus = FW_STATUS_LOAD_EMEM;
157 break;
158
159 case FW_STATUS_LOAD_EMEM:
160 NextFWStatus = FW_STATUS_LOAD_DMEM;
161 break;
162
163 case FW_STATUS_LOAD_DMEM:
164 NextFWStatus = FW_STATUS_READY;
165 break;
166
167 default:
168 RT_TRACE(COMP_ERR,"Invalid FW Status(%#x)!!\n", FWCurrentStatus);
169 break;
170 }
171 return NextFWStatus;
172}
173
Florian Schilhabele695b472010-05-04 14:24:12 +0200174bool FirmwareCheckReady(struct net_device *dev, u8 LoadFWStatus)
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700175{
Florian Schilhabele695b472010-05-04 14:24:12 +0200176 struct r8192_priv *priv = ieee80211_priv(dev);
177 bool rtStatus = true;
178 rt_firmware *pFirmware = priv->pFirmware;
179 int PollingCnt = 1000;
180 u8 CPUStatus = 0;
181 u32 tmpU4b;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700182
183 pFirmware->FWStatus = (FIRMWARE_8192S_STATUS)LoadFWStatus;
Florian Schilhabele695b472010-05-04 14:24:12 +0200184 switch (LoadFWStatus) {
185 case FW_STATUS_LOAD_IMEM:
186 do { /* Polling IMEM code done. */
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700187 CPUStatus = read_nic_byte(dev, TCR);
188 if(CPUStatus& IMEM_CODE_DONE)
189 break;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700190 udelay(5);
Florian Schilhabele695b472010-05-04 14:24:12 +0200191 } while (PollingCnt--);
192 if (!(CPUStatus & IMEM_CHK_RPT) || PollingCnt <= 0) {
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700193 RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\r\n", CPUStatus);
Florian Schilhabele695b472010-05-04 14:24:12 +0200194 goto FirmwareCheckReadyFail;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700195 }
Florian Schilhabele695b472010-05-04 14:24:12 +0200196 break;
197 case FW_STATUS_LOAD_EMEM: /* Check Put Code OK and Turn On CPU */
198 do { /* Polling EMEM code done. */
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700199 CPUStatus = read_nic_byte(dev, TCR);
200 if(CPUStatus& EMEM_CODE_DONE)
201 break;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700202 udelay(5);
Florian Schilhabele695b472010-05-04 14:24:12 +0200203 } while (PollingCnt--);
204 if (!(CPUStatus & EMEM_CHK_RPT)) {
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700205 RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\r\n", CPUStatus);
Florian Schilhabele695b472010-05-04 14:24:12 +0200206 goto FirmwareCheckReadyFail;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700207 }
Florian Schilhabele695b472010-05-04 14:24:12 +0200208 /* Turn On CPU */
209 if (FirmwareEnableCPU(dev) != true) {
210 RT_TRACE(COMP_ERR, "%s(): failed to enable CPU",
211 __func__);
212 goto FirmwareCheckReadyFail;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700213 }
Florian Schilhabele695b472010-05-04 14:24:12 +0200214 break;
215 case FW_STATUS_LOAD_DMEM:
216 do { /* Polling DMEM code done */
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700217 CPUStatus = read_nic_byte(dev, TCR);
218 if(CPUStatus& DMEM_CODE_DONE)
219 break;
220
221 udelay(5);
Florian Schilhabele695b472010-05-04 14:24:12 +0200222 } while (PollingCnt--);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700223
Florian Schilhabele695b472010-05-04 14:24:12 +0200224 if (!(CPUStatus & DMEM_CODE_DONE)) {
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700225 RT_TRACE(COMP_ERR, "Polling DMEM code done fail ! CPUStatus(%#x)\n", CPUStatus);
Florian Schilhabele695b472010-05-04 14:24:12 +0200226 goto FirmwareCheckReadyFail;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700227 }
228
Florian Schilhabele695b472010-05-04 14:24:12 +0200229 RT_TRACE(COMP_FIRMWARE, "%s(): DMEM code download success, "
230 "CPUStatus(%#x)",
231 __func__, CPUStatus);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700232
Florian Schilhabele695b472010-05-04 14:24:12 +0200233 PollingCnt = 10000; /* Set polling cycle to 10ms. */
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700234
Florian Schilhabele695b472010-05-04 14:24:12 +0200235 do { /* Polling Load Firmware ready */
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700236 CPUStatus = read_nic_byte(dev, TCR);
237 if(CPUStatus & FWRDY)
238 break;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700239 udelay(100);
Florian Schilhabele695b472010-05-04 14:24:12 +0200240 } while (PollingCnt--);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700241
Florian Schilhabele695b472010-05-04 14:24:12 +0200242 RT_TRACE(COMP_FIRMWARE, "%s(): polling load firmware ready, "
243 "CPUStatus(%x)",
244 __func__, CPUStatus);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700245
Florian Schilhabele695b472010-05-04 14:24:12 +0200246 if ((CPUStatus & LOAD_FW_READY) != LOAD_FW_READY) {
247 RT_TRACE(COMP_ERR, "Polling Load Firmware ready failed "
248 "CPUStatus(%x)\n", CPUStatus);
249 goto FirmwareCheckReadyFail;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700250 }
Florian Schilhabele695b472010-05-04 14:24:12 +0200251 /*
252 * USB interface will update
253 * reserved followings parameters later
254 */
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700255
256 //
257 // <Roger_Notes> If right here, we can set TCR/RCR to desired value
258 // and config MAC lookback mode to normal mode. 2008.08.28.
259 //
260 tmpU4b = read_nic_dword(dev,TCR);
261 write_nic_dword(dev, TCR, (tmpU4b&(~TCR_ICV)));
262
263 tmpU4b = read_nic_dword(dev, RCR);
264 write_nic_dword(dev, RCR,
265 (tmpU4b|RCR_APPFCS|RCR_APP_ICV|RCR_APP_MIC));
266
Florian Schilhabele695b472010-05-04 14:24:12 +0200267 RT_TRACE(COMP_FIRMWARE, "%s(): Current RCR settings(%#x)",
268 __func__, tmpU4b);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700269 // Set to normal mode.
270 write_nic_byte(dev, LBKMD_SEL, LBK_NORMAL);
Florian Schilhabele695b472010-05-04 14:24:12 +0200271 break;
272 default:
273 break;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700274 }
Florian Schilhabele695b472010-05-04 14:24:12 +0200275 RT_TRACE(COMP_FIRMWARE, "%s(): LoadFWStatus(%d), success",
276 __func__, LoadFWStatus);
277 return rtStatus;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700278
Florian Schilhabele695b472010-05-04 14:24:12 +0200279FirmwareCheckReadyFail:
280 rtStatus = false;
281 RT_TRACE(COMP_FIRMWARE, "%s(): LoadFWStatus(%d), failed",
282 __func__, LoadFWStatus);
283 return rtStatus;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700284}
285
286//
287// Description: This routine is to update the RF types in FW header partially.
288//
289// Created by Roger, 2008.12.24.
290//
291u8 FirmwareHeaderMapRfType(struct net_device *dev)
292{
293 struct r8192_priv *priv = ieee80211_priv(dev);
294 switch(priv->rf_type)
295 {
296 case RF_1T1R: return 0x11;
297 case RF_1T2R: return 0x12;
298 case RF_2T2R: return 0x22;
299 case RF_2T2R_GREEN: return 0x92;
300 default:
301 RT_TRACE(COMP_INIT, "Unknown RF type(%x)\n",priv->rf_type);
302 break;
303 }
304 return 0x22;
305}
306
307
308//
309// Description: This routine is to update the private parts in FW header partially.
310//
311// Created by Roger, 2008.12.18.
312//
313void FirmwareHeaderPriveUpdate(struct net_device *dev, PRT_8192S_FIRMWARE_PRIV pFwPriv)
314{
315 struct r8192_priv *priv = ieee80211_priv(dev);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700316 // Update USB endpoint number for RQPN settings.
317 pFwPriv->usb_ep_num = priv->EEPROMUsbEndPointNumber; // endpoint number: 4, 6 and 11.
318 RT_TRACE(COMP_INIT, "FirmwarePriveUpdate(): usb_ep_num(%#x)\n", pFwPriv->usb_ep_num);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700319
320 // Update RF types for RATR settings.
321 pFwPriv->rf_config = FirmwareHeaderMapRfType(dev);
322}
323
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100324bool FirmwareRequest92S(struct net_device *dev, rt_firmware *pFirmware)
325{
326 struct r8192_priv *priv = ieee80211_priv(dev);
327 bool rtStatus = true;
328 const char *pFwImageFileName[1] = {"RTL8192SU/rtl8192sfw.bin"};
329 u8 *pucMappedFile = NULL;
330 u32 ulInitStep = 0;
331 u8 FwHdrSize = RT_8192S_FIRMWARE_HDR_SIZE;
332 PRT_8192S_FIRMWARE_HDR pFwHdr = NULL;
333 u32 file_length = 0;
334 int rc;
335 const struct firmware *fw_entry;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700336
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100337 rc = request_firmware(&fw_entry,
338 pFwImageFileName[ulInitStep],
339 &priv->udev->dev);
340 if (rc < 0)
341 goto RequestFirmware_Fail;
342
343 if (fw_entry->size > sizeof(pFirmware->szFwTmpBuffer)) {
344 RT_TRACE(COMP_ERR, "%s(): image file too large"
345 "for container buffer", __func__);
346 release_firmware(fw_entry);
347 goto RequestFirmware_Fail;
348 }
349
350 memcpy(pFirmware->szFwTmpBuffer, fw_entry->data, fw_entry->size);
351 pFirmware->szFwTmpBufferLen = fw_entry->size;
352 release_firmware(fw_entry);
353
354 pucMappedFile = pFirmware->szFwTmpBuffer;
355 file_length = pFirmware->szFwTmpBufferLen;
356
357 /* Retrieve FW header. */
358 pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;
359 pFwHdr = pFirmware->pFwHeader;
360
361 RT_TRACE(COMP_FIRMWARE, "%s(): signature: %x, version: %x, "
362 "size: %x, imemsize: %x, sram size: %x",
363 __func__, pFwHdr->Signature, pFwHdr->Version,
364 pFwHdr->DMEMSize, pFwHdr->IMG_IMEM_SIZE,
365 pFwHdr->IMG_SRAM_SIZE);
366
367 pFirmware->FirmwareVersion = byte(pFwHdr->Version , 0);
368
369 if ((pFwHdr->IMG_IMEM_SIZE == 0) ||
370 (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM))) {
371 RT_TRACE(COMP_ERR, "%s(): memory for data image is less than"
372 " IMEM requires", __func__);
373 goto RequestFirmware_Fail;
374 } else {
375 pucMappedFile += FwHdrSize;
376 /* Retrieve IMEM image. */
377 memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
378 pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;
379 }
380
381 if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM)) {
382 RT_TRACE(COMP_ERR, "%s(): memory for data image is less than"
383 " EMEM requires", __func__);
384 goto RequestFirmware_Fail;
385 } else {
386 pucMappedFile += pFirmware->FwIMEMLen;
387 /* Retriecve EMEM image */
388 memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);
389 pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
390 }
391 return rtStatus;
392
393RequestFirmware_Fail:
394 RT_TRACE(COMP_ERR, "%s(): failed with TCR-Status: %x\n",
395 __func__, read_nic_word(dev, TCR));
396 rtStatus = false;
397 return rtStatus;
398}
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700399
400bool FirmwareDownload92S(struct net_device *dev)
401{
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100402 struct r8192_priv *priv = ieee80211_priv(dev);
403 bool rtStatus = true;
404 u8 *pucMappedFile = NULL;
405 u32 ulFileLength;
406 u8 FwHdrSize = RT_8192S_FIRMWARE_HDR_SIZE;
407 rt_firmware *pFirmware = priv->pFirmware;
408 u8 FwStatus = FW_STATUS_INIT;
409 PRT_8192S_FIRMWARE_HDR pFwHdr = NULL;
410 PRT_8192S_FIRMWARE_PRIV pFwPriv = NULL;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700411
412 pFirmware->FWStatus = FW_STATUS_INIT;
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100413 /*
414 * Load the firmware from RTL8192SU/rtl8192sfw.bin if necessary
415 */
416 if (pFirmware->szFwTmpBufferLen == 0) {
417 if (FirmwareRequest92S(dev, pFirmware) != true)
418 goto DownloadFirmware_Fail;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700419 }
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700420 FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100421 while (FwStatus != FW_STATUS_READY) {
422 /* Image buffer redirection. */
423 switch (FwStatus) {
424 case FW_STATUS_LOAD_IMEM:
425 pucMappedFile = pFirmware->FwIMEM;
426 ulFileLength = pFirmware->FwIMEMLen;
427 break;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700428
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100429 case FW_STATUS_LOAD_EMEM:
430 pucMappedFile = pFirmware->FwEMEM;
431 ulFileLength = pFirmware->FwEMEMLen;
432 break;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700433
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100434 case FW_STATUS_LOAD_DMEM:
435 /* Partial update the content of private header */
436 pFwHdr = pFirmware->pFwHeader;
437 pFwPriv = (PRT_8192S_FIRMWARE_PRIV)&pFwHdr->FWPriv;
438 FirmwareHeaderPriveUpdate(dev, pFwPriv);
439 pucMappedFile = (u8 *)(pFirmware->pFwHeader) +
440 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700441
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100442 ulFileLength = FwHdrSize -
443 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
444 break;
445
446 default:
447 RT_TRACE(COMP_ERR, "Unexpected Download step!!\n");
448 goto DownloadFirmware_Fail;
449 break;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700450 }
451
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100452 /* <2> Download image file */
453
454 rtStatus = FirmwareDownloadCode(dev,
455 pucMappedFile,
456 ulFileLength);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700457
458 if(rtStatus != true)
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700459 goto DownloadFirmware_Fail;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700460
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100461 /* <3> Check whether load FW process is ready */
462
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700463 rtStatus = FirmwareCheckReady(dev, FwStatus);
464
465 if(rtStatus != true)
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700466 goto DownloadFirmware_Fail;
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700467
468 FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
469 }
470
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100471 RT_TRACE(COMP_FIRMWARE, "%s(): Firmware Download Success", __func__);
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700472 return rtStatus;
473
Florian Schilhabelf06ebfe2010-03-18 15:17:29 +0100474DownloadFirmware_Fail:
475 RT_TRACE(COMP_ERR, "%s(): failed with TCR-Status: %x\n",
476 __func__, read_nic_word(dev, TCR));
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700477 rtStatus = false;
478 return rtStatus;
479}
Jerry Chuang5f53d8c2009-05-21 22:16:02 -0700480
Ben Hutchings5d929a72010-01-13 23:36:09 +0000481MODULE_FIRMWARE("RTL8192SU/rtl8192sfw.bin");