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 #include <linux/firmware.h>
25 void firmware_init_param(struct net_device
*dev
)
27 struct r8192_priv
*priv
= ieee80211_priv(dev
);
28 rt_firmware
*pfirmware
= priv
->pFirmware
;
30 pfirmware
->cmdpacket_frag_thresold
= GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE
);
34 * segment the img and use the ptr and length to remember info on each segment
37 static bool fw_download_code(struct net_device
*dev
, u8
*code_virtual_address
, u32 buffer_len
)
39 struct r8192_priv
*priv
= ieee80211_priv(dev
);
40 bool rt_status
= true;
42 u16 frag_length
, frag_offset
= 0;
46 rt_firmware
*pfirmware
= priv
->pFirmware
;
48 unsigned char *seg_ptr
;
52 firmware_init_param(dev
);
53 //Fragmentation might be required
54 frag_threshold
= pfirmware
->cmdpacket_frag_thresold
;
56 if((buffer_len
- frag_offset
) > frag_threshold
) {
57 frag_length
= frag_threshold
;
61 frag_length
= buffer_len
- frag_offset
;
66 /* Allocate skb buffer to contain firmware info and tx descriptor info
67 * add 4 to avoid packet appending overflow.
69 //skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
70 skb
= dev_alloc_skb(frag_length
+ 4);
71 memcpy((unsigned char *)(skb
->cb
),&dev
,sizeof(dev
));
72 tcb_desc
= (cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
73 tcb_desc
->queue_index
= TXCMD_QUEUE
;
74 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_INIT
;
75 tcb_desc
->bLastIniPkt
= bLastIniPkt
;
77 //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
;
91 priv
->ieee80211
->softmac_hard_start_xmit(skb
,dev
);
93 code_virtual_address
+= frag_length
;
94 frag_offset
+= frag_length
;
96 }while(frag_offset
< buffer_len
);
101 //-----------------------------------------------------------------------------
102 // Procedure: Check whether main code is download OK. If OK, turn on CPU
104 // Description: CPU register locates in different page against general register.
105 // Switch to CPU register in the begin and switch back before return
108 // Arguments: The pointer of the adapter
111 // NDIS_STATUS_FAILURE - the following initialization process should be terminated
112 // NDIS_STATUS_SUCCESS - if firmware initialization process success
113 //-----------------------------------------------------------------------------
114 static bool CPUcheck_maincodeok_turnonCPU(struct net_device
*dev
)
116 bool rt_status
= true;
117 int check_putcodeOK_time
= 200000, check_bootOk_time
= 200000;
120 /* Check whether put code OK */
122 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
124 if(CPU_status
&CPU_GEN_PUT_CODE_OK
)
127 }while(check_putcodeOK_time
--);
129 if(!(CPU_status
&CPU_GEN_PUT_CODE_OK
)) {
130 RT_TRACE(COMP_ERR
, "Download Firmware: Put code fail!\n");
131 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
133 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Put code ok!\n");
137 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
138 write_nic_byte(dev
, CPU_GEN
, (u8
)((CPU_status
|CPU_GEN_PWR_STB_CPU
)&0xff));
141 /* Check whether CPU boot OK */
143 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
145 if(CPU_status
&CPU_GEN_BOOT_RDY
)
147 }while(check_bootOk_time
--);
149 if(!(CPU_status
&CPU_GEN_BOOT_RDY
)) {
150 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
152 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Boot ready!\n");
157 CPUCheckMainCodeOKAndTurnOnCPU_Fail
:
158 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
163 static bool CPUcheck_firmware_ready(struct net_device
*dev
)
166 bool rt_status
= true;
167 int check_time
= 200000;
170 /* Check Firmware Ready */
172 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
174 if(CPU_status
&CPU_GEN_FIRM_RDY
)
177 }while(check_time
--);
179 if(!(CPU_status
&CPU_GEN_FIRM_RDY
))
180 goto CPUCheckFirmwareReady_Fail
;
182 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Firmware ready!\n");
186 CPUCheckFirmwareReady_Fail
:
187 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
193 bool init_firmware(struct net_device
*dev
)
195 struct r8192_priv
*priv
= ieee80211_priv(dev
);
196 bool rt_status
= TRUE
;
199 u8
*firmware_img_buf
[3] = { &rtl8190_fwboot_array
[0],
200 &rtl8190_fwmain_array
[0],
201 &rtl8190_fwdata_array
[0]};
203 u32 firmware_img_len
[3] = { sizeof(rtl8190_fwboot_array
),
204 sizeof(rtl8190_fwmain_array
),
205 sizeof(rtl8190_fwdata_array
)};
207 u8
*firmware_img_buf
[3] = { &rtl8192e_fwboot_array
[0],
208 &rtl8192e_fwmain_array
[0],
209 &rtl8192e_fwdata_array
[0]};
211 u32 firmware_img_len
[3] = { sizeof(rtl8192e_fwboot_array
),
212 sizeof(rtl8192e_fwmain_array
),
213 sizeof(rtl8192e_fwdata_array
)};
216 u8
*mapped_file
= NULL
;
218 opt_rst_type_e rst_opt
= OPT_SYSTEM_RESET
;
219 firmware_init_step_e starting_state
= FW_INIT_STEP0_BOOT
;
221 rt_firmware
*pfirmware
= priv
->pFirmware
;
222 const struct firmware
*fw_entry
;
224 const char *fw_name
[3] = { "RTL8190P/boot.img",
226 "RTL8190P/data.img"};
229 const char *fw_name
[3] = { "RTL8192E/boot.img",
231 "RTL8192E/data.img"};
235 RT_TRACE(COMP_FIRMWARE
, " PlatformInitFirmware()==>\n");
237 if (pfirmware
->firmware_status
== FW_STATUS_0_INIT
) {
238 /* it is called by reset */
239 rst_opt
= OPT_SYSTEM_RESET
;
240 starting_state
= FW_INIT_STEP0_BOOT
;
241 // TODO: system reset
243 }else if(pfirmware
->firmware_status
== FW_STATUS_5_READY
) {
244 /* it is called by Initialize */
245 rst_opt
= OPT_FIRMWARE_RESET
;
246 starting_state
= FW_INIT_STEP2_DATA
;
248 RT_TRACE(COMP_FIRMWARE
, "PlatformInitFirmware: undefined firmware state\n");
252 * Download boot, main, and data image for System reset.
253 * Download data image for firmware reseta
255 priv
->firmware_source
= FW_SOURCE_IMG_FILE
;
256 for(init_step
= starting_state
; init_step
<= FW_INIT_STEP2_DATA
; init_step
++) {
258 * Open Image file, and map file to contineous memory if open file success.
259 * or read image file from array. Default load from IMG file
261 if(rst_opt
== OPT_SYSTEM_RESET
) {
262 switch(priv
->firmware_source
) {
263 case FW_SOURCE_IMG_FILE
:
265 if(pfirmware
->firmware_buf_size
[init_step
] == 0) {
266 rc
= request_firmware(&fw_entry
, fw_name
[init_step
],&priv
->pdev
->dev
);
268 RT_TRACE(COMP_FIRMWARE
, "request firmware fail!\n");
269 goto download_firmware_fail
;
272 if(fw_entry
->size
> sizeof(pfirmware
->firmware_buf
[init_step
])) {
273 RT_TRACE(COMP_FIRMWARE
, "img file size exceed the container buffer fail!\n");
274 goto download_firmware_fail
;
277 if(init_step
!= FW_INIT_STEP1_MAIN
) {
278 memcpy(pfirmware
->firmware_buf
[init_step
],fw_entry
->data
,fw_entry
->size
);
279 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
;
283 memcpy(pfirmware
->firmware_buf
[init_step
],fw_entry
->data
,fw_entry
->size
);
284 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
;
287 memset(pfirmware
->firmware_buf
[init_step
],0,128);
288 memcpy(&pfirmware
->firmware_buf
[init_step
][128],fw_entry
->data
,fw_entry
->size
);
289 //mapped_file = pfirmware->firmware_buf[init_step];
290 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
+128;
291 //file_length = fw_entry->size + 128;
294 //pfirmware->firmware_buf_size = file_length;
296 if(rst_opt
== OPT_SYSTEM_RESET
) {
297 release_firmware(fw_entry
);
300 mapped_file
= pfirmware
->firmware_buf
[init_step
];
301 file_length
= pfirmware
->firmware_buf_size
[init_step
];
304 case FW_SOURCE_HEADER_FILE
:
305 mapped_file
= firmware_img_buf
[init_step
];
306 file_length
= firmware_img_len
[init_step
];
307 if(init_step
== FW_INIT_STEP2_DATA
) {
308 memcpy(pfirmware
->firmware_buf
[init_step
], mapped_file
, file_length
);
309 pfirmware
->firmware_buf_size
[init_step
] = file_length
;
318 }else if(rst_opt
== OPT_FIRMWARE_RESET
) {
319 /* we only need to download data.img here */
320 mapped_file
= pfirmware
->firmware_buf
[init_step
];
321 file_length
= pfirmware
->firmware_buf_size
[init_step
];
324 /* Download image file */
325 /* The firmware download process is just as following,
326 * 1. that is each packet will be segmented and inserted to the wait queue.
327 * 2. each packet segment will be put in the skb_buff packet.
328 * 3. each skb_buff packet data content will already include the firmware info
329 * and Tx descriptor info
331 rt_status
= fw_download_code(dev
,mapped_file
,file_length
);
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
;
345 * To initialize IMEM, CPU move code from 0x80000080,
346 * hence, we send 0x80 byte packet
350 case FW_INIT_STEP1_MAIN
:
351 /* Download firmware code. Wait until Boot Ready and Turn on CPU */
352 pfirmware
->firmware_status
= FW_STATUS_2_MOVE_MAIN_CODE
;
354 /* Check Put Code OK and Turn On CPU */
355 rt_status
= CPUcheck_maincodeok_turnonCPU(dev
);
356 if(rt_status
!= TRUE
) {
357 RT_TRACE(COMP_FIRMWARE
, "CPUcheck_maincodeok_turnonCPU fail!\n");
358 goto download_firmware_fail
;
361 pfirmware
->firmware_status
= FW_STATUS_3_TURNON_CPU
;
364 case FW_INIT_STEP2_DATA
:
365 /* download initial data code */
366 pfirmware
->firmware_status
= FW_STATUS_4_MOVE_DATA_CODE
;
369 rt_status
= CPUcheck_firmware_ready(dev
);
370 if(rt_status
!= TRUE
) {
371 RT_TRACE(COMP_FIRMWARE
, "CPUcheck_firmware_ready fail(%d)!\n",rt_status
);
372 goto download_firmware_fail
;
375 /* wait until data code is initialized ready.*/
376 pfirmware
->firmware_status
= FW_STATUS_5_READY
;
381 RT_TRACE(COMP_FIRMWARE
, "Firmware Download Success\n");
382 //assert(pfirmware->firmware_status == FW_STATUS_5_READY, ("Firmware Download Fail\n"));
386 download_firmware_fail
:
387 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);