1 /**************************************************************************************************
2 * Procedure: Init boot code/firmware code/data session
4 * Description: This routine will initialize 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 **************************************************************************************************/
16 #include "r8192U_hw.h"
17 #include "r819xU_firmware_img.h"
18 #include "r819xU_firmware.h"
19 #include <linux/firmware.h>
20 void firmware_init_param(struct net_device
*dev
)
22 struct r8192_priv
*priv
= ieee80211_priv(dev
);
23 rt_firmware
*pfirmware
= priv
->pFirmware
;
25 pfirmware
->cmdpacket_frag_thresold
= GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE
);
29 * segment the img and use the ptr and length to remember info on each segment
32 bool fw_download_code(struct net_device
*dev
, u8
*code_virtual_address
, u32 buffer_len
)
34 struct r8192_priv
*priv
= ieee80211_priv(dev
);
35 bool rt_status
= true;
37 u16 frag_length
, frag_offset
= 0;
41 rt_firmware
*pfirmware
= priv
->pFirmware
;
43 unsigned char *seg_ptr
;
47 firmware_init_param(dev
);
48 //Fragmentation might be required
49 frag_threshold
= pfirmware
->cmdpacket_frag_thresold
;
51 if((buffer_len
- frag_offset
) > frag_threshold
) {
52 frag_length
= frag_threshold
;
56 frag_length
= buffer_len
- frag_offset
;
61 /* Allocate skb buffer to contain firmware info and tx descriptor info
62 * add 4 to avoid packet appending overflow.
65 skb
= dev_alloc_skb(USB_HWDESC_HEADER_LEN
+ frag_length
+ 4);
67 skb
= dev_alloc_skb(frag_length
+ 4);
69 memcpy((unsigned char *)(skb
->cb
),&dev
,sizeof(dev
));
70 tcb_desc
= (cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
71 tcb_desc
->queue_index
= TXCMD_QUEUE
;
72 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_INIT
;
73 tcb_desc
->bLastIniPkt
= bLastIniPkt
;
76 skb_reserve(skb
, USB_HWDESC_HEADER_LEN
);
80 * Transform from little endian to big endian
83 for(i
=0 ; i
< frag_length
; i
+=4) {
84 *seg_ptr
++ = ((i
+0)<frag_length
)?code_virtual_address
[i
+3]:0;
85 *seg_ptr
++ = ((i
+1)<frag_length
)?code_virtual_address
[i
+2]:0;
86 *seg_ptr
++ = ((i
+2)<frag_length
)?code_virtual_address
[i
+1]:0;
87 *seg_ptr
++ = ((i
+3)<frag_length
)?code_virtual_address
[i
+0]:0;
89 tcb_desc
->txbuf_size
= (u16
)i
;
92 if(!priv
->ieee80211
->check_nic_enough_desc(dev
,tcb_desc
->queue_index
)||
93 (!skb_queue_empty(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
]))||\
94 (priv
->ieee80211
->queue_stop
) ) {
95 RT_TRACE(COMP_FIRMWARE
,"=====================================================> tx full!\n");
96 skb_queue_tail(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
], skb
);
98 priv
->ieee80211
->softmac_hard_start_xmit(skb
,dev
);
101 code_virtual_address
+= frag_length
;
102 frag_offset
+= frag_length
;
104 }while(frag_offset
< buffer_len
);
112 struct net_device
*dev
,
116 bool rtStatus
= true;
117 struct r8192_priv
*priv
= ieee80211_priv(dev
);
120 unsigned char *ptr_buf
;
121 bool bLastInitPacket
= false;
123 //PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
125 //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
126 skb
= dev_alloc_skb(Length
+ 4);
127 memcpy((unsigned char *)(skb
->cb
),&dev
,sizeof(dev
));
128 tcb_desc
= (cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
129 tcb_desc
->queue_index
= TXCMD_QUEUE
;
130 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_INIT
;
131 tcb_desc
->bLastIniPkt
= bLastInitPacket
;
132 ptr_buf
= skb_put(skb
, Length
);
133 memset(ptr_buf
,0,Length
);
134 tcb_desc
->txbuf_size
= (u16
)Length
;
136 if(!priv
->ieee80211
->check_nic_enough_desc(dev
,tcb_desc
->queue_index
)||
137 (!skb_queue_empty(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
]))||\
138 (priv
->ieee80211
->queue_stop
) ) {
139 RT_TRACE(COMP_FIRMWARE
,"===================NULL packet==================================> tx full!\n");
140 skb_queue_tail(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
], skb
);
142 priv
->ieee80211
->softmac_hard_start_xmit(skb
,dev
);
145 //PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
150 //-----------------------------------------------------------------------------
151 // Procedure: Check whether main code is download OK. If OK, turn on CPU
153 // Description: CPU register locates in different page against general register.
154 // Switch to CPU register in the begin and switch back before return
157 // Arguments: The pointer of the adapter
160 // NDIS_STATUS_FAILURE - the following initialization process should be terminated
161 // NDIS_STATUS_SUCCESS - if firmware initialization process success
162 //-----------------------------------------------------------------------------
163 bool CPUcheck_maincodeok_turnonCPU(struct net_device
*dev
)
165 bool rt_status
= true;
166 int check_putcodeOK_time
= 200000, check_bootOk_time
= 200000;
169 /* Check whether put code OK */
171 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
173 if(CPU_status
&CPU_GEN_PUT_CODE_OK
)
176 }while(check_putcodeOK_time
--);
178 if(!(CPU_status
&CPU_GEN_PUT_CODE_OK
)) {
179 RT_TRACE(COMP_ERR
, "Download Firmware: Put code fail!\n");
180 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
182 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Put code ok!\n");
186 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
187 write_nic_byte(dev
, CPU_GEN
, (u8
)((CPU_status
|CPU_GEN_PWR_STB_CPU
)&0xff));
190 /* Check whether CPU boot OK */
192 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
194 if(CPU_status
&CPU_GEN_BOOT_RDY
)
196 }while(check_bootOk_time
--);
198 if(!(CPU_status
&CPU_GEN_BOOT_RDY
)) {
199 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
201 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Boot ready!\n");
206 CPUCheckMainCodeOKAndTurnOnCPU_Fail
:
207 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
212 bool CPUcheck_firmware_ready(struct net_device
*dev
)
215 bool rt_status
= true;
216 int check_time
= 200000;
219 /* Check Firmware Ready */
221 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
223 if(CPU_status
&CPU_GEN_FIRM_RDY
)
226 }while(check_time
--);
228 if(!(CPU_status
&CPU_GEN_FIRM_RDY
))
229 goto CPUCheckFirmwareReady_Fail
;
231 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Firmware ready!\n");
235 CPUCheckFirmwareReady_Fail
:
236 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
242 bool init_firmware(struct net_device
*dev
)
244 struct r8192_priv
*priv
= ieee80211_priv(dev
);
245 bool rt_status
= TRUE
;
248 u8
*mapped_file
= NULL
;
250 opt_rst_type_e rst_opt
= OPT_SYSTEM_RESET
;
251 firmware_init_step_e starting_state
= FW_INIT_STEP0_BOOT
;
253 rt_firmware
*pfirmware
= priv
->pFirmware
;
254 const struct firmware
*fw_entry
;
255 const char *fw_name
[3] = { "RTL8192U/boot.img",
257 "RTL8192U/data.img"};
260 RT_TRACE(COMP_FIRMWARE
, " PlatformInitFirmware()==>\n");
262 if (pfirmware
->firmware_status
== FW_STATUS_0_INIT
) {
263 /* it is called by reset */
264 rst_opt
= OPT_SYSTEM_RESET
;
265 starting_state
= FW_INIT_STEP0_BOOT
;
266 // TODO: system reset
268 }else if(pfirmware
->firmware_status
== FW_STATUS_5_READY
) {
269 /* it is called by Initialize */
270 rst_opt
= OPT_FIRMWARE_RESET
;
271 starting_state
= FW_INIT_STEP2_DATA
;
273 RT_TRACE(COMP_FIRMWARE
, "PlatformInitFirmware: undefined firmware state\n");
277 * Download boot, main, and data image for System reset.
278 * Download data image for firmware reseta
280 for(init_step
= starting_state
; init_step
<= FW_INIT_STEP2_DATA
; init_step
++) {
282 * Open Image file, and map file to contineous memory if open file success.
283 * or read image file from array. Default load from IMG file
285 if(rst_opt
== OPT_SYSTEM_RESET
) {
286 rc
= request_firmware(&fw_entry
, fw_name
[init_step
],&priv
->udev
->dev
);
288 RT_TRACE(COMP_ERR
, "request firmware fail!\n");
289 goto download_firmware_fail
;
292 if(fw_entry
->size
> sizeof(pfirmware
->firmware_buf
)) {
293 RT_TRACE(COMP_ERR
, "img file size exceed the container buffer fail!\n");
294 goto download_firmware_fail
;
297 if(init_step
!= FW_INIT_STEP1_MAIN
) {
298 memcpy(pfirmware
->firmware_buf
,fw_entry
->data
,fw_entry
->size
);
299 mapped_file
= pfirmware
->firmware_buf
;
300 file_length
= fw_entry
->size
;
303 memcpy(pfirmware
->firmware_buf
,fw_entry
->data
,fw_entry
->size
);
304 mapped_file
= pfirmware
->firmware_buf
;
305 file_length
= fw_entry
->size
;
307 memset(pfirmware
->firmware_buf
,0,128);
308 memcpy(&pfirmware
->firmware_buf
[128],fw_entry
->data
,fw_entry
->size
);
309 mapped_file
= pfirmware
->firmware_buf
;
310 file_length
= fw_entry
->size
+ 128;
313 pfirmware
->firmware_buf_size
= file_length
;
314 }else if(rst_opt
== OPT_FIRMWARE_RESET
) {
315 /* we only need to download data.img here */
316 mapped_file
= pfirmware
->firmware_buf
;
317 file_length
= pfirmware
->firmware_buf_size
;
320 /* Download image file */
321 /* The firmware download process is just as following,
322 * 1. that is each packet will be segmented and inserted to the wait queue.
323 * 2. each packet segment will be put in the skb_buff packet.
324 * 3. each skb_buff packet data content will already include the firmware info
325 * and Tx descriptor info
327 rt_status
= fw_download_code(dev
,mapped_file
,file_length
);
328 if(rst_opt
== OPT_SYSTEM_RESET
) {
329 release_firmware(fw_entry
);
332 if(rt_status
!= TRUE
) {
333 goto download_firmware_fail
;
337 case FW_INIT_STEP0_BOOT
:
339 * initialize command descriptor.
340 * will set polling bit when firmware code is also configured
342 pfirmware
->firmware_status
= FW_STATUS_1_MOVE_BOOT_CODE
;
344 // To initialize IMEM, CPU move code from 0x80000080, hence, we send 0x80 byte packet
345 rt_status
= fwSendNullPacket(dev
, RTL8190_CPU_START_OFFSET
);
346 if(rt_status
!= true)
348 RT_TRACE(COMP_INIT
, "fwSendNullPacket() fail ! \n");
349 goto download_firmware_fail
;
354 * To initialize IMEM, CPU move code from 0x80000080,
355 * hence, we send 0x80 byte packet
359 case FW_INIT_STEP1_MAIN
:
360 /* Download firmware code. Wait until Boot Ready and Turn on CPU */
361 pfirmware
->firmware_status
= FW_STATUS_2_MOVE_MAIN_CODE
;
363 /* Check Put Code OK and Turn On CPU */
364 rt_status
= CPUcheck_maincodeok_turnonCPU(dev
);
365 if(rt_status
!= TRUE
) {
366 RT_TRACE(COMP_ERR
, "CPUcheck_maincodeok_turnonCPU fail!\n");
367 goto download_firmware_fail
;
370 pfirmware
->firmware_status
= FW_STATUS_3_TURNON_CPU
;
373 case FW_INIT_STEP2_DATA
:
374 /* download initial data code */
375 pfirmware
->firmware_status
= FW_STATUS_4_MOVE_DATA_CODE
;
378 rt_status
= CPUcheck_firmware_ready(dev
);
379 if(rt_status
!= TRUE
) {
380 RT_TRACE(COMP_ERR
, "CPUcheck_firmware_ready fail(%d)!\n",rt_status
);
381 goto download_firmware_fail
;
384 /* wait until data code is initialized ready.*/
385 pfirmware
->firmware_status
= FW_STATUS_5_READY
;
390 RT_TRACE(COMP_FIRMWARE
, "Firmware Download Success\n");
391 //assert(pfirmware->firmware_status == FW_STATUS_5_READY, ("Firmware Download Fail\n"));
395 download_firmware_fail
:
396 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
402 MODULE_FIRMWARE("RTL8192U/boot.img");
403 MODULE_FIRMWARE("RTL8192U/main.img");
404 MODULE_FIRMWARE("RTL8192U/data.img");