1 /**************************************************************************************************
2 * Procedure: Init boot code/firmware code/data session
4 * Description: This routine will intialize firmware. If any error occurs during the initialization
5 * process, the routine shall terminate immediately and return fail.
6 * NIC driver should call NdisOpenFile only from MiniportInitialize.
8 * Arguments: The pointer of the adapter
11 * NDIS_STATUS_FAILURE - the following initialization process should be terminated
12 * NDIS_STATUS_SUCCESS - if firmware initialization process success
13 **************************************************************************************************/
15 #include "r8192S_firmware.h"
16 #include <linux/unistd.h>
18 #include "r8192S_hw.h"
19 #include "r8192SU_HWImg.h"
21 #include <linux/firmware.h>
23 #define byte(x,n) ( (x >> (8 * n)) & 0xff )
26 // Description: This routine will intialize firmware. If any error occurs during the initialization
27 // process, the routine shall terminate immediately and return fail.
29 // Arguments: The pointer of the adapter
30 // Code address (Virtual address, should fill descriptor with physical address)
32 // Created by Roger, 2008.04.10.
34 bool FirmwareDownloadCode(struct net_device
*dev
,
35 u8
*code_virtual_address
,
38 struct r8192_priv
*priv
= ieee80211_priv(dev
);
39 bool rt_status
= true;
40 /* Fragmentation might be required in 90/92 but not in 92S */
41 u16 frag_threshold
= MAX_FIRMWARE_CODE_SIZE
;
42 u16 frag_length
, frag_offset
= 0;
44 unsigned char *seg_ptr
;
47 u16 ExtraDescOffset
= 0;
49 if (buffer_len
>= MAX_FIRMWARE_CODE_SIZE
- USB_HWDESC_HEADER_LEN
) {
50 RT_TRACE(COMP_ERR
, "(%s): Firmware exceeds"
51 " MAX_FIRMWARE_CODE_SIZE\n", __func__
);
52 goto cmdsend_downloadcode_fail
;
54 ExtraDescOffset
= USB_HWDESC_HEADER_LEN
;
56 if((buffer_len
-frag_offset
) > frag_threshold
)
57 frag_length
= frag_threshold
+ ExtraDescOffset
;
59 frag_length
= (u16
)(buffer_len
-
60 frag_offset
+ ExtraDescOffset
);
64 * Allocate skb buffer to contain firmware info
65 * and tx descriptor info.
67 skb
= dev_alloc_skb(frag_length
);
69 RT_TRACE(COMP_ERR
, "(%s): unable to alloc skb buffer\n",
71 goto cmdsend_downloadcode_fail
;
73 memcpy((unsigned char *)(skb
->cb
), &dev
, sizeof(dev
));
75 tcb_desc
= (cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
76 tcb_desc
->queue_index
= TXCMD_QUEUE
;
77 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_INIT
;
78 tcb_desc
->bLastIniPkt
= bLastIniPkt
;
80 skb_reserve(skb
, ExtraDescOffset
);
82 seg_ptr
= (u8
*)skb_put(skb
,
83 (u32
)(frag_length
- ExtraDescOffset
));
85 memcpy(seg_ptr
, code_virtual_address
+ frag_offset
,
86 (u32
)(frag_length
-ExtraDescOffset
));
88 tcb_desc
->txbuf_size
= frag_length
;
90 if (!priv
->ieee80211
->check_nic_enough_desc(dev
, tcb_desc
->queue_index
) ||
91 (!skb_queue_empty(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
])) ||
92 (priv
->ieee80211
->queue_stop
)) {
93 RT_TRACE(COMP_FIRMWARE
,"=====================================================> tx full!\n");
94 skb_queue_tail(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
], skb
);
96 priv
->ieee80211
->softmac_hard_start_xmit(skb
, dev
);
98 frag_offset
+= (frag_length
- ExtraDescOffset
);
100 } while (frag_offset
< buffer_len
);
103 cmdsend_downloadcode_fail
:
105 RT_TRACE(COMP_ERR
, "(%s): failed\n", __func__
);
110 bool FirmwareEnableCPU(struct net_device
*dev
)
112 bool rtStatus
= true;
113 u8 tmpU1b
, CPUStatus
= 0;
115 u32 iCheckTime
= 200;
118 tmpU1b
= read_nic_byte(dev
, SYS_CLKR
);
120 write_nic_byte(dev
, SYS_CLKR
, (tmpU1b
|SYS_CPU_CLKSEL
));
121 tmpU2b
= read_nic_word(dev
, SYS_FUNC_EN
);
122 write_nic_word(dev
, SYS_FUNC_EN
, (tmpU2b
|FEN_CPUEN
));
123 /* Poll IMEM Ready after CPU has refilled. */
125 CPUStatus
= read_nic_byte(dev
, TCR
);
126 if (CPUStatus
& IMEM_RDY
)
130 } while (iCheckTime
--);
131 if (!(CPUStatus
& IMEM_RDY
)) {
132 RT_TRACE(COMP_ERR
, "%s(): failed to enable CPU", __func__
);
138 FIRMWARE_8192S_STATUS
139 FirmwareGetNextStatus(FIRMWARE_8192S_STATUS FWCurrentStatus
)
141 FIRMWARE_8192S_STATUS NextFWStatus
= 0;
143 switch(FWCurrentStatus
)
146 NextFWStatus
= FW_STATUS_LOAD_IMEM
;
149 case FW_STATUS_LOAD_IMEM
:
150 NextFWStatus
= FW_STATUS_LOAD_EMEM
;
153 case FW_STATUS_LOAD_EMEM
:
154 NextFWStatus
= FW_STATUS_LOAD_DMEM
;
157 case FW_STATUS_LOAD_DMEM
:
158 NextFWStatus
= FW_STATUS_READY
;
162 RT_TRACE(COMP_ERR
,"Invalid FW Status(%#x)!!\n", FWCurrentStatus
);
168 bool FirmwareCheckReady(struct net_device
*dev
, u8 LoadFWStatus
)
170 struct r8192_priv
*priv
= ieee80211_priv(dev
);
171 bool rtStatus
= true;
172 rt_firmware
*pFirmware
= priv
->pFirmware
;
173 int PollingCnt
= 1000;
177 pFirmware
->FWStatus
= (FIRMWARE_8192S_STATUS
)LoadFWStatus
;
178 switch (LoadFWStatus
) {
179 case FW_STATUS_LOAD_IMEM
:
180 do { /* Polling IMEM code done. */
181 CPUStatus
= read_nic_byte(dev
, TCR
);
182 if(CPUStatus
& IMEM_CODE_DONE
)
185 } while (PollingCnt
--);
186 if (!(CPUStatus
& IMEM_CHK_RPT
) || PollingCnt
<= 0) {
187 RT_TRACE(COMP_ERR
, "FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\r\n", CPUStatus
);
188 goto FirmwareCheckReadyFail
;
191 case FW_STATUS_LOAD_EMEM
: /* Check Put Code OK and Turn On CPU */
192 do { /* Polling EMEM code done. */
193 CPUStatus
= read_nic_byte(dev
, TCR
);
194 if(CPUStatus
& EMEM_CODE_DONE
)
197 } while (PollingCnt
--);
198 if (!(CPUStatus
& EMEM_CHK_RPT
)) {
199 RT_TRACE(COMP_ERR
, "FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\r\n", CPUStatus
);
200 goto FirmwareCheckReadyFail
;
203 if (FirmwareEnableCPU(dev
) != true) {
204 RT_TRACE(COMP_ERR
, "%s(): failed to enable CPU",
206 goto FirmwareCheckReadyFail
;
209 case FW_STATUS_LOAD_DMEM
:
210 do { /* Polling DMEM code done */
211 CPUStatus
= read_nic_byte(dev
, TCR
);
212 if(CPUStatus
& DMEM_CODE_DONE
)
216 } while (PollingCnt
--);
218 if (!(CPUStatus
& DMEM_CODE_DONE
)) {
219 RT_TRACE(COMP_ERR
, "Polling DMEM code done fail ! CPUStatus(%#x)\n", CPUStatus
);
220 goto FirmwareCheckReadyFail
;
223 RT_TRACE(COMP_FIRMWARE
, "%s(): DMEM code download success, "
225 __func__
, CPUStatus
);
227 PollingCnt
= 10000; /* Set polling cycle to 10ms. */
229 do { /* Polling Load Firmware ready */
230 CPUStatus
= read_nic_byte(dev
, TCR
);
231 if(CPUStatus
& FWRDY
)
234 } while (PollingCnt
--);
236 RT_TRACE(COMP_FIRMWARE
, "%s(): polling load firmware ready, "
238 __func__
, CPUStatus
);
240 if ((CPUStatus
& LOAD_FW_READY
) != LOAD_FW_READY
) {
241 RT_TRACE(COMP_ERR
, "Polling Load Firmware ready failed "
242 "CPUStatus(%x)\n", CPUStatus
);
243 goto FirmwareCheckReadyFail
;
246 * USB interface will update
247 * reserved followings parameters later
251 // <Roger_Notes> If right here, we can set TCR/RCR to desired value
252 // and config MAC lookback mode to normal mode. 2008.08.28.
254 tmpU4b
= read_nic_dword(dev
,TCR
);
255 write_nic_dword(dev
, TCR
, (tmpU4b
&(~TCR_ICV
)));
257 tmpU4b
= read_nic_dword(dev
, RCR
);
258 write_nic_dword(dev
, RCR
,
259 (tmpU4b
|RCR_APPFCS
|RCR_APP_ICV
|RCR_APP_MIC
));
261 RT_TRACE(COMP_FIRMWARE
, "%s(): Current RCR settings(%#x)",
263 // Set to normal mode.
264 write_nic_byte(dev
, LBKMD_SEL
, LBK_NORMAL
);
269 RT_TRACE(COMP_FIRMWARE
, "%s(): LoadFWStatus(%d), success",
270 __func__
, LoadFWStatus
);
273 FirmwareCheckReadyFail
:
275 RT_TRACE(COMP_FIRMWARE
, "%s(): LoadFWStatus(%d), failed",
276 __func__
, LoadFWStatus
);
281 // Description: This routine is to update the RF types in FW header partially.
283 // Created by Roger, 2008.12.24.
285 u8
FirmwareHeaderMapRfType(struct net_device
*dev
)
287 struct r8192_priv
*priv
= ieee80211_priv(dev
);
288 switch(priv
->rf_type
)
290 case RF_1T1R
: return 0x11;
291 case RF_1T2R
: return 0x12;
292 case RF_2T2R
: return 0x22;
293 case RF_2T2R_GREEN
: return 0x92;
295 RT_TRACE(COMP_INIT
, "Unknown RF type(%x)\n",priv
->rf_type
);
303 // Description: This routine is to update the private parts in FW header partially.
305 // Created by Roger, 2008.12.18.
307 void FirmwareHeaderPriveUpdate(struct net_device
*dev
, PRT_8192S_FIRMWARE_PRIV pFwPriv
)
309 struct r8192_priv
*priv
= ieee80211_priv(dev
);
310 // Update USB endpoint number for RQPN settings.
311 pFwPriv
->usb_ep_num
= priv
->EEPROMUsbEndPointNumber
; // endpoint number: 4, 6 and 11.
312 RT_TRACE(COMP_INIT
, "FirmwarePriveUpdate(): usb_ep_num(%#x)\n", pFwPriv
->usb_ep_num
);
314 // Update RF types for RATR settings.
315 pFwPriv
->rf_config
= FirmwareHeaderMapRfType(dev
);
318 bool FirmwareRequest92S(struct net_device
*dev
, rt_firmware
*pFirmware
)
320 struct r8192_priv
*priv
= ieee80211_priv(dev
);
321 bool rtStatus
= true;
322 const char *pFwImageFileName
[1] = {"RTL8192SU/rtl8192sfw.bin"};
323 u8
*pucMappedFile
= NULL
;
325 u8 FwHdrSize
= RT_8192S_FIRMWARE_HDR_SIZE
;
326 PRT_8192S_FIRMWARE_HDR pFwHdr
= NULL
;
329 const struct firmware
*fw_entry
;
331 rc
= request_firmware(&fw_entry
,
332 pFwImageFileName
[ulInitStep
],
335 goto RequestFirmware_Fail
;
337 if (fw_entry
->size
> sizeof(pFirmware
->szFwTmpBuffer
)) {
338 RT_TRACE(COMP_ERR
, "%s(): image file too large"
339 "for container buffer", __func__
);
340 release_firmware(fw_entry
);
341 goto RequestFirmware_Fail
;
344 memcpy(pFirmware
->szFwTmpBuffer
, fw_entry
->data
, fw_entry
->size
);
345 pFirmware
->szFwTmpBufferLen
= fw_entry
->size
;
346 release_firmware(fw_entry
);
348 pucMappedFile
= pFirmware
->szFwTmpBuffer
;
349 file_length
= pFirmware
->szFwTmpBufferLen
;
351 /* Retrieve FW header. */
352 pFirmware
->pFwHeader
= (PRT_8192S_FIRMWARE_HDR
) pucMappedFile
;
353 pFwHdr
= pFirmware
->pFwHeader
;
355 RT_TRACE(COMP_FIRMWARE
, "%s(): signature: %x, version: %x, "
356 "size: %x, imemsize: %x, sram size: %x",
357 __func__
, pFwHdr
->Signature
, pFwHdr
->Version
,
358 pFwHdr
->DMEMSize
, pFwHdr
->IMG_IMEM_SIZE
,
359 pFwHdr
->IMG_SRAM_SIZE
);
361 pFirmware
->FirmwareVersion
= byte(pFwHdr
->Version
, 0);
363 if ((pFwHdr
->IMG_IMEM_SIZE
== 0) ||
364 (pFwHdr
->IMG_IMEM_SIZE
> sizeof(pFirmware
->FwIMEM
))) {
365 RT_TRACE(COMP_ERR
, "%s(): memory for data image is less than"
366 " IMEM requires", __func__
);
367 goto RequestFirmware_Fail
;
369 pucMappedFile
+= FwHdrSize
;
370 /* Retrieve IMEM image. */
371 memcpy(pFirmware
->FwIMEM
, pucMappedFile
, pFwHdr
->IMG_IMEM_SIZE
);
372 pFirmware
->FwIMEMLen
= pFwHdr
->IMG_IMEM_SIZE
;
375 if (pFwHdr
->IMG_SRAM_SIZE
> sizeof(pFirmware
->FwEMEM
)) {
376 RT_TRACE(COMP_ERR
, "%s(): memory for data image is less than"
377 " EMEM requires", __func__
);
378 goto RequestFirmware_Fail
;
380 pucMappedFile
+= pFirmware
->FwIMEMLen
;
381 /* Retriecve EMEM image */
382 memcpy(pFirmware
->FwEMEM
, pucMappedFile
, pFwHdr
->IMG_SRAM_SIZE
);
383 pFirmware
->FwEMEMLen
= pFwHdr
->IMG_SRAM_SIZE
;
387 RequestFirmware_Fail
:
388 RT_TRACE(COMP_ERR
, "%s(): failed with TCR-Status: %x\n",
389 __func__
, read_nic_word(dev
, TCR
));
394 bool FirmwareDownload92S(struct net_device
*dev
)
396 struct r8192_priv
*priv
= ieee80211_priv(dev
);
397 bool rtStatus
= true;
398 u8
*pucMappedFile
= NULL
;
400 u8 FwHdrSize
= RT_8192S_FIRMWARE_HDR_SIZE
;
401 rt_firmware
*pFirmware
= priv
->pFirmware
;
402 u8 FwStatus
= FW_STATUS_INIT
;
403 PRT_8192S_FIRMWARE_HDR pFwHdr
= NULL
;
404 PRT_8192S_FIRMWARE_PRIV pFwPriv
= NULL
;
406 pFirmware
->FWStatus
= FW_STATUS_INIT
;
408 * Load the firmware from RTL8192SU/rtl8192sfw.bin if necessary
410 if (pFirmware
->szFwTmpBufferLen
== 0) {
411 if (FirmwareRequest92S(dev
, pFirmware
) != true)
412 goto DownloadFirmware_Fail
;
414 FwStatus
= FirmwareGetNextStatus(pFirmware
->FWStatus
);
415 while (FwStatus
!= FW_STATUS_READY
) {
416 /* Image buffer redirection. */
418 case FW_STATUS_LOAD_IMEM
:
419 pucMappedFile
= pFirmware
->FwIMEM
;
420 ulFileLength
= pFirmware
->FwIMEMLen
;
423 case FW_STATUS_LOAD_EMEM
:
424 pucMappedFile
= pFirmware
->FwEMEM
;
425 ulFileLength
= pFirmware
->FwEMEMLen
;
428 case FW_STATUS_LOAD_DMEM
:
429 /* Partial update the content of private header */
430 pFwHdr
= pFirmware
->pFwHeader
;
431 pFwPriv
= (PRT_8192S_FIRMWARE_PRIV
)&pFwHdr
->FWPriv
;
432 FirmwareHeaderPriveUpdate(dev
, pFwPriv
);
433 pucMappedFile
= (u8
*)(pFirmware
->pFwHeader
) +
434 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE
;
436 ulFileLength
= FwHdrSize
-
437 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE
;
441 RT_TRACE(COMP_ERR
, "Unexpected Download step!!\n");
442 goto DownloadFirmware_Fail
;
446 /* <2> Download image file */
448 rtStatus
= FirmwareDownloadCode(dev
,
453 goto DownloadFirmware_Fail
;
455 /* <3> Check whether load FW process is ready */
457 rtStatus
= FirmwareCheckReady(dev
, FwStatus
);
460 goto DownloadFirmware_Fail
;
462 FwStatus
= FirmwareGetNextStatus(pFirmware
->FWStatus
);
465 RT_TRACE(COMP_FIRMWARE
, "%s(): Firmware Download Success", __func__
);
468 DownloadFirmware_Fail
:
469 RT_TRACE(COMP_ERR
, "%s(): failed with TCR-Status: %x\n",
470 __func__
, read_nic_word(dev
, TCR
));
475 MODULE_FIRMWARE("RTL8192SU/rtl8192sfw.bin");