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 **************************************************************************************************/
14 //#include "ieee80211.h"
16 #include "r8192E_hw.h"
18 #include "r819xP_firmware_img.h"
20 #include "r819xE_firmware_img.h"
22 #include "r819xE_firmware.h"
23 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
24 #include <linux/firmware.h>
27 void firmware_init_param(struct net_device
*dev
)
29 struct r8192_priv
*priv
= ieee80211_priv(dev
);
30 rt_firmware
*pfirmware
= priv
->pFirmware
;
32 pfirmware
->cmdpacket_frag_thresold
= GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE
);
36 * segment the img and use the ptr and length to remember info on each segment
39 static bool fw_download_code(struct net_device
*dev
, u8
*code_virtual_address
, u32 buffer_len
)
41 struct r8192_priv
*priv
= ieee80211_priv(dev
);
42 bool rt_status
= true;
44 u16 frag_length
, frag_offset
= 0;
48 rt_firmware
*pfirmware
= priv
->pFirmware
;
50 unsigned char *seg_ptr
;
54 firmware_init_param(dev
);
55 //Fragmentation might be required
56 frag_threshold
= pfirmware
->cmdpacket_frag_thresold
;
58 if((buffer_len
- frag_offset
) > frag_threshold
) {
59 frag_length
= frag_threshold
;
63 frag_length
= buffer_len
- frag_offset
;
68 /* Allocate skb buffer to contain firmware info and tx descriptor info
69 * add 4 to avoid packet appending overflow.
71 //skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
72 skb
= dev_alloc_skb(frag_length
+ 4);
73 memcpy((unsigned char *)(skb
->cb
),&dev
,sizeof(dev
));
74 tcb_desc
= (cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
75 tcb_desc
->queue_index
= TXCMD_QUEUE
;
76 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_INIT
;
77 tcb_desc
->bLastIniPkt
= bLastIniPkt
;
79 //skb_reserve(skb, USB_HWDESC_HEADER_LEN);
82 * Transform from little endian to big endian
85 for(i
=0 ; i
< frag_length
; i
+=4) {
86 *seg_ptr
++ = ((i
+0)<frag_length
)?code_virtual_address
[i
+3]:0;
87 *seg_ptr
++ = ((i
+1)<frag_length
)?code_virtual_address
[i
+2]:0;
88 *seg_ptr
++ = ((i
+2)<frag_length
)?code_virtual_address
[i
+1]:0;
89 *seg_ptr
++ = ((i
+3)<frag_length
)?code_virtual_address
[i
+0]:0;
91 tcb_desc
->txbuf_size
= (u16
)i
;
93 priv
->ieee80211
->softmac_hard_start_xmit(skb
,dev
);
95 code_virtual_address
+= frag_length
;
96 frag_offset
+= frag_length
;
98 }while(frag_offset
< buffer_len
);
103 //-----------------------------------------------------------------------------
104 // Procedure: Check whether main code is download OK. If OK, turn on CPU
106 // Description: CPU register locates in different page against general register.
107 // Switch to CPU register in the begin and switch back before return
110 // Arguments: The pointer of the adapter
113 // NDIS_STATUS_FAILURE - the following initialization process should be terminated
114 // NDIS_STATUS_SUCCESS - if firmware initialization process success
115 //-----------------------------------------------------------------------------
116 static bool CPUcheck_maincodeok_turnonCPU(struct net_device
*dev
)
118 bool rt_status
= true;
119 int check_putcodeOK_time
= 200000, check_bootOk_time
= 200000;
122 /* Check whether put code OK */
124 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
126 if(CPU_status
&CPU_GEN_PUT_CODE_OK
)
129 }while(check_putcodeOK_time
--);
131 if(!(CPU_status
&CPU_GEN_PUT_CODE_OK
)) {
132 RT_TRACE(COMP_ERR
, "Download Firmware: Put code fail!\n");
133 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
135 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Put code ok!\n");
139 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
140 write_nic_byte(dev
, CPU_GEN
, (u8
)((CPU_status
|CPU_GEN_PWR_STB_CPU
)&0xff));
143 /* Check whether CPU boot OK */
145 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
147 if(CPU_status
&CPU_GEN_BOOT_RDY
)
149 }while(check_bootOk_time
--);
151 if(!(CPU_status
&CPU_GEN_BOOT_RDY
)) {
152 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
154 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Boot ready!\n");
159 CPUCheckMainCodeOKAndTurnOnCPU_Fail
:
160 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
165 static bool CPUcheck_firmware_ready(struct net_device
*dev
)
168 bool rt_status
= true;
169 int check_time
= 200000;
172 /* Check Firmware Ready */
174 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
176 if(CPU_status
&CPU_GEN_FIRM_RDY
)
179 }while(check_time
--);
181 if(!(CPU_status
&CPU_GEN_FIRM_RDY
))
182 goto CPUCheckFirmwareReady_Fail
;
184 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Firmware ready!\n");
188 CPUCheckFirmwareReady_Fail
:
189 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
195 bool init_firmware(struct net_device
*dev
)
197 struct r8192_priv
*priv
= ieee80211_priv(dev
);
198 bool rt_status
= TRUE
;
201 u8
*firmware_img_buf
[3] = { &rtl8190_fwboot_array
[0],
202 &rtl8190_fwmain_array
[0],
203 &rtl8190_fwdata_array
[0]};
205 u32 firmware_img_len
[3] = { sizeof(rtl8190_fwboot_array
),
206 sizeof(rtl8190_fwmain_array
),
207 sizeof(rtl8190_fwdata_array
)};
209 u8
*firmware_img_buf
[3] = { &rtl8192e_fwboot_array
[0],
210 &rtl8192e_fwmain_array
[0],
211 &rtl8192e_fwdata_array
[0]};
213 u32 firmware_img_len
[3] = { sizeof(rtl8192e_fwboot_array
),
214 sizeof(rtl8192e_fwmain_array
),
215 sizeof(rtl8192e_fwdata_array
)};
218 u8
*mapped_file
= NULL
;
220 opt_rst_type_e rst_opt
= OPT_SYSTEM_RESET
;
221 firmware_init_step_e starting_state
= FW_INIT_STEP0_BOOT
;
223 rt_firmware
*pfirmware
= priv
->pFirmware
;
224 const struct firmware
*fw_entry
;
226 const char *fw_name
[3] = { "RTL8190P/boot.img",
228 "RTL8190P/data.img"};
231 const char *fw_name
[3] = { "RTL8192E/boot.img",
233 "RTL8192E/data.img"};
237 RT_TRACE(COMP_FIRMWARE
, " PlatformInitFirmware()==>\n");
239 if (pfirmware
->firmware_status
== FW_STATUS_0_INIT
) {
240 /* it is called by reset */
241 rst_opt
= OPT_SYSTEM_RESET
;
242 starting_state
= FW_INIT_STEP0_BOOT
;
243 // TODO: system reset
245 }else if(pfirmware
->firmware_status
== FW_STATUS_5_READY
) {
246 /* it is called by Initialize */
247 rst_opt
= OPT_FIRMWARE_RESET
;
248 starting_state
= FW_INIT_STEP2_DATA
;
250 RT_TRACE(COMP_FIRMWARE
, "PlatformInitFirmware: undefined firmware state\n");
254 * Download boot, main, and data image for System reset.
255 * Download data image for firmware reseta
257 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
258 priv
->firmware_source
= FW_SOURCE_HEADER_FILE
;
260 priv
->firmware_source
= FW_SOURCE_IMG_FILE
;
262 for(init_step
= starting_state
; init_step
<= FW_INIT_STEP2_DATA
; init_step
++) {
264 * Open Image file, and map file to contineous memory if open file success.
265 * or read image file from array. Default load from IMG file
267 if(rst_opt
== OPT_SYSTEM_RESET
) {
268 switch(priv
->firmware_source
) {
269 case FW_SOURCE_IMG_FILE
:
271 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
272 if(pfirmware
->firmware_buf_size
[init_step
] == 0) {
273 rc
= request_firmware(&fw_entry
, fw_name
[init_step
],&priv
->pdev
->dev
);
275 RT_TRACE(COMP_FIRMWARE
, "request firmware fail!\n");
276 goto download_firmware_fail
;
279 if(fw_entry
->size
> sizeof(pfirmware
->firmware_buf
[init_step
])) {
280 RT_TRACE(COMP_FIRMWARE
, "img file size exceed the container buffer fail!\n");
281 goto download_firmware_fail
;
284 if(init_step
!= FW_INIT_STEP1_MAIN
) {
285 memcpy(pfirmware
->firmware_buf
[init_step
],fw_entry
->data
,fw_entry
->size
);
286 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
;
290 memcpy(pfirmware
->firmware_buf
[init_step
],fw_entry
->data
,fw_entry
->size
);
291 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
;
294 memset(pfirmware
->firmware_buf
[init_step
],0,128);
295 memcpy(&pfirmware
->firmware_buf
[init_step
][128],fw_entry
->data
,fw_entry
->size
);
296 //mapped_file = pfirmware->firmware_buf[init_step];
297 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
+128;
298 //file_length = fw_entry->size + 128;
301 //pfirmware->firmware_buf_size = file_length;
303 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
304 if(rst_opt
== OPT_SYSTEM_RESET
) {
305 release_firmware(fw_entry
);
309 mapped_file
= pfirmware
->firmware_buf
[init_step
];
310 file_length
= pfirmware
->firmware_buf_size
[init_step
];
314 case FW_SOURCE_HEADER_FILE
:
315 mapped_file
= firmware_img_buf
[init_step
];
316 file_length
= firmware_img_len
[init_step
];
317 if(init_step
== FW_INIT_STEP2_DATA
) {
318 memcpy(pfirmware
->firmware_buf
[init_step
], mapped_file
, file_length
);
319 pfirmware
->firmware_buf_size
[init_step
] = file_length
;
328 }else if(rst_opt
== OPT_FIRMWARE_RESET
) {
329 /* we only need to download data.img here */
330 mapped_file
= pfirmware
->firmware_buf
[init_step
];
331 file_length
= pfirmware
->firmware_buf_size
[init_step
];
334 /* Download image file */
335 /* The firmware download process is just as following,
336 * 1. that is each packet will be segmented and inserted to the wait queue.
337 * 2. each packet segment will be put in the skb_buff packet.
338 * 3. each skb_buff packet data content will already include the firmware info
339 * and Tx descriptor info
341 rt_status
= fw_download_code(dev
,mapped_file
,file_length
);
342 if(rt_status
!= TRUE
) {
343 goto download_firmware_fail
;
347 case FW_INIT_STEP0_BOOT
:
349 * initialize command descriptor.
350 * will set polling bit when firmware code is also configured
352 pfirmware
->firmware_status
= FW_STATUS_1_MOVE_BOOT_CODE
;
355 * To initialize IMEM, CPU move code from 0x80000080,
356 * hence, we send 0x80 byte packet
360 case FW_INIT_STEP1_MAIN
:
361 /* Download firmware code. Wait until Boot Ready and Turn on CPU */
362 pfirmware
->firmware_status
= FW_STATUS_2_MOVE_MAIN_CODE
;
364 /* Check Put Code OK and Turn On CPU */
365 rt_status
= CPUcheck_maincodeok_turnonCPU(dev
);
366 if(rt_status
!= TRUE
) {
367 RT_TRACE(COMP_FIRMWARE
, "CPUcheck_maincodeok_turnonCPU fail!\n");
368 goto download_firmware_fail
;
371 pfirmware
->firmware_status
= FW_STATUS_3_TURNON_CPU
;
374 case FW_INIT_STEP2_DATA
:
375 /* download initial data code */
376 pfirmware
->firmware_status
= FW_STATUS_4_MOVE_DATA_CODE
;
379 rt_status
= CPUcheck_firmware_ready(dev
);
380 if(rt_status
!= TRUE
) {
381 RT_TRACE(COMP_FIRMWARE
, "CPUcheck_firmware_ready fail(%d)!\n",rt_status
);
382 goto download_firmware_fail
;
385 /* wait until data code is initialized ready.*/
386 pfirmware
->firmware_status
= FW_STATUS_5_READY
;
391 RT_TRACE(COMP_FIRMWARE
, "Firmware Download Success\n");
392 //assert(pfirmware->firmware_status == FW_STATUS_5_READY, ("Firmware Download Fail\n"));
396 download_firmware_fail
:
397 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);