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"
17 //#include "r819xE_firmware_img.h"
18 #include "r819xE_firmware.h"
19 #include <linux/firmware.h>
21 void firmware_init_param(struct net_device
*dev
)
23 struct r8192_priv
*priv
= ieee80211_priv(dev
);
24 rt_firmware
*pfirmware
= priv
->pFirmware
;
26 pfirmware
->cmdpacket_frag_thresold
= GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE
);
30 * segment the img and use the ptr and length to remember info on each segment
33 static bool fw_download_code(struct net_device
*dev
, u8
*code_virtual_address
, u32 buffer_len
)
35 struct r8192_priv
*priv
= ieee80211_priv(dev
);
36 bool rt_status
= true;
38 u16 frag_length
, frag_offset
= 0;
42 rt_firmware
*pfirmware
= priv
->pFirmware
;
44 unsigned char *seg_ptr
;
48 firmware_init_param(dev
);
49 //Fragmentation might be required
50 frag_threshold
= pfirmware
->cmdpacket_frag_thresold
;
52 if((buffer_len
- frag_offset
) > frag_threshold
) {
53 frag_length
= frag_threshold
;
57 frag_length
= buffer_len
- frag_offset
;
62 /* Allocate skb buffer to contain firmware info and tx descriptor info
63 * add 4 to avoid packet appending overflow.
65 //skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
66 skb
= dev_alloc_skb(frag_length
+ 4);
67 memcpy((unsigned char *)(skb
->cb
),&dev
,sizeof(dev
));
68 tcb_desc
= (cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
69 tcb_desc
->queue_index
= TXCMD_QUEUE
;
70 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_INIT
;
71 tcb_desc
->bLastIniPkt
= bLastIniPkt
;
73 //skb_reserve(skb, USB_HWDESC_HEADER_LEN);
76 * Transform from little endian to big endian
79 for(i
=0 ; i
< frag_length
; i
+=4) {
80 *seg_ptr
++ = ((i
+0)<frag_length
)?code_virtual_address
[i
+3]:0;
81 *seg_ptr
++ = ((i
+1)<frag_length
)?code_virtual_address
[i
+2]:0;
82 *seg_ptr
++ = ((i
+2)<frag_length
)?code_virtual_address
[i
+1]:0;
83 *seg_ptr
++ = ((i
+3)<frag_length
)?code_virtual_address
[i
+0]:0;
85 tcb_desc
->txbuf_size
= (u16
)i
;
87 priv
->ieee80211
->softmac_hard_start_xmit(skb
,dev
);
89 code_virtual_address
+= frag_length
;
90 frag_offset
+= frag_length
;
92 }while(frag_offset
< buffer_len
);
97 //-----------------------------------------------------------------------------
98 // Procedure: Check whether main code is download OK. If OK, turn on CPU
100 // Description: CPU register locates in different page against general register.
101 // Switch to CPU register in the begin and switch back before return
104 // Arguments: The pointer of the adapter
107 // NDIS_STATUS_FAILURE - the following initialization process should be terminated
108 // NDIS_STATUS_SUCCESS - if firmware initialization process success
109 //-----------------------------------------------------------------------------
110 static bool CPUcheck_maincodeok_turnonCPU(struct net_device
*dev
)
112 bool rt_status
= true;
113 int check_putcodeOK_time
= 200000, check_bootOk_time
= 200000;
116 /* Check whether put code OK */
118 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
120 if(CPU_status
&CPU_GEN_PUT_CODE_OK
)
123 }while(check_putcodeOK_time
--);
125 if(!(CPU_status
&CPU_GEN_PUT_CODE_OK
)) {
126 RT_TRACE(COMP_ERR
, "Download Firmware: Put code fail!\n");
127 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
129 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Put code ok!\n");
133 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
134 write_nic_byte(dev
, CPU_GEN
, (u8
)((CPU_status
|CPU_GEN_PWR_STB_CPU
)&0xff));
137 /* Check whether CPU boot OK */
139 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
141 if(CPU_status
&CPU_GEN_BOOT_RDY
)
143 }while(check_bootOk_time
--);
145 if(!(CPU_status
&CPU_GEN_BOOT_RDY
)) {
146 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
148 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Boot ready!\n");
153 CPUCheckMainCodeOKAndTurnOnCPU_Fail
:
154 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
159 static bool CPUcheck_firmware_ready(struct net_device
*dev
)
162 bool rt_status
= true;
163 int check_time
= 200000;
166 /* Check Firmware Ready */
168 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
170 if(CPU_status
&CPU_GEN_FIRM_RDY
)
173 }while(check_time
--);
175 if(!(CPU_status
&CPU_GEN_FIRM_RDY
))
176 goto CPUCheckFirmwareReady_Fail
;
178 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Firmware ready!\n");
182 CPUCheckFirmwareReady_Fail
:
183 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
189 bool init_firmware(struct net_device
*dev
)
191 struct r8192_priv
*priv
= ieee80211_priv(dev
);
192 bool rt_status
= TRUE
;
194 u8
*firmware_img_buf
[3] = { &rtl8192e_fwboot_array
[0],
195 &rtl8192e_fwmain_array
[0],
196 &rtl8192e_fwdata_array
[0]};
198 u32 firmware_img_len
[3] = { sizeof(rtl8192e_fwboot_array
),
199 sizeof(rtl8192e_fwmain_array
),
200 sizeof(rtl8192e_fwdata_array
)};
202 u8
*mapped_file
= NULL
;
204 opt_rst_type_e rst_opt
= OPT_SYSTEM_RESET
;
205 firmware_init_step_e starting_state
= FW_INIT_STEP0_BOOT
;
207 rt_firmware
*pfirmware
= priv
->pFirmware
;
208 const struct firmware
*fw_entry
;
209 const char *fw_name
[3] = { "RTL8192E/boot.img",
211 "RTL8192E/data.img"};
214 RT_TRACE(COMP_FIRMWARE
, " PlatformInitFirmware()==>\n");
216 if (pfirmware
->firmware_status
== FW_STATUS_0_INIT
) {
217 /* it is called by reset */
218 rst_opt
= OPT_SYSTEM_RESET
;
219 starting_state
= FW_INIT_STEP0_BOOT
;
220 // TODO: system reset
222 }else if(pfirmware
->firmware_status
== FW_STATUS_5_READY
) {
223 /* it is called by Initialize */
224 rst_opt
= OPT_FIRMWARE_RESET
;
225 starting_state
= FW_INIT_STEP2_DATA
;
227 RT_TRACE(COMP_FIRMWARE
, "PlatformInitFirmware: undefined firmware state\n");
231 * Download boot, main, and data image for System reset.
232 * Download data image for firmware reseta
234 priv
->firmware_source
= FW_SOURCE_IMG_FILE
;
235 for(init_step
= starting_state
; init_step
<= FW_INIT_STEP2_DATA
; init_step
++) {
237 * Open Image file, and map file to contineous memory if open file success.
238 * or read image file from array. Default load from IMG file
240 if(rst_opt
== OPT_SYSTEM_RESET
) {
241 switch(priv
->firmware_source
) {
242 case FW_SOURCE_IMG_FILE
:
244 if(pfirmware
->firmware_buf_size
[init_step
] == 0) {
245 rc
= request_firmware(&fw_entry
, fw_name
[init_step
],&priv
->pdev
->dev
);
247 RT_TRACE(COMP_FIRMWARE
, "request firmware fail!\n");
248 goto download_firmware_fail
;
251 if(fw_entry
->size
> sizeof(pfirmware
->firmware_buf
[init_step
])) {
252 RT_TRACE(COMP_FIRMWARE
, "img file size exceed the container buffer fail!\n");
253 goto download_firmware_fail
;
256 if(init_step
!= FW_INIT_STEP1_MAIN
) {
257 memcpy(pfirmware
->firmware_buf
[init_step
],fw_entry
->data
,fw_entry
->size
);
258 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
;
261 memset(pfirmware
->firmware_buf
[init_step
],0,128);
262 memcpy(&pfirmware
->firmware_buf
[init_step
][128],fw_entry
->data
,fw_entry
->size
);
263 //mapped_file = pfirmware->firmware_buf[init_step];
264 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
+128;
265 //file_length = fw_entry->size + 128;
267 //pfirmware->firmware_buf_size = file_length;
269 if(rst_opt
== OPT_SYSTEM_RESET
) {
270 release_firmware(fw_entry
);
273 mapped_file
= pfirmware
->firmware_buf
[init_step
];
274 file_length
= pfirmware
->firmware_buf_size
[init_step
];
277 case FW_SOURCE_HEADER_FILE
:
278 mapped_file
= firmware_img_buf
[init_step
];
279 file_length
= firmware_img_len
[init_step
];
280 if(init_step
== FW_INIT_STEP2_DATA
) {
281 memcpy(pfirmware
->firmware_buf
[init_step
], mapped_file
, file_length
);
282 pfirmware
->firmware_buf_size
[init_step
] = file_length
;
291 }else if(rst_opt
== OPT_FIRMWARE_RESET
) {
292 /* we only need to download data.img here */
293 mapped_file
= pfirmware
->firmware_buf
[init_step
];
294 file_length
= pfirmware
->firmware_buf_size
[init_step
];
297 /* Download image file */
298 /* The firmware download process is just as following,
299 * 1. that is each packet will be segmented and inserted to the wait queue.
300 * 2. each packet segment will be put in the skb_buff packet.
301 * 3. each skb_buff packet data content will already include the firmware info
302 * and Tx descriptor info
304 rt_status
= fw_download_code(dev
,mapped_file
,file_length
);
305 if(rt_status
!= TRUE
) {
306 goto download_firmware_fail
;
310 case FW_INIT_STEP0_BOOT
:
312 * initialize command descriptor.
313 * will set polling bit when firmware code is also configured
315 pfirmware
->firmware_status
= FW_STATUS_1_MOVE_BOOT_CODE
;
318 * To initialize IMEM, CPU move code from 0x80000080,
319 * hence, we send 0x80 byte packet
323 case FW_INIT_STEP1_MAIN
:
324 /* Download firmware code. Wait until Boot Ready and Turn on CPU */
325 pfirmware
->firmware_status
= FW_STATUS_2_MOVE_MAIN_CODE
;
327 /* Check Put Code OK and Turn On CPU */
328 rt_status
= CPUcheck_maincodeok_turnonCPU(dev
);
329 if(rt_status
!= TRUE
) {
330 RT_TRACE(COMP_FIRMWARE
, "CPUcheck_maincodeok_turnonCPU fail!\n");
331 goto download_firmware_fail
;
334 pfirmware
->firmware_status
= FW_STATUS_3_TURNON_CPU
;
337 case FW_INIT_STEP2_DATA
:
338 /* download initial data code */
339 pfirmware
->firmware_status
= FW_STATUS_4_MOVE_DATA_CODE
;
342 rt_status
= CPUcheck_firmware_ready(dev
);
343 if(rt_status
!= TRUE
) {
344 RT_TRACE(COMP_FIRMWARE
, "CPUcheck_firmware_ready fail(%d)!\n",rt_status
);
345 goto download_firmware_fail
;
348 /* wait until data code is initialized ready.*/
349 pfirmware
->firmware_status
= FW_STATUS_5_READY
;
354 RT_TRACE(COMP_FIRMWARE
, "Firmware Download Success\n");
355 //assert(pfirmware->firmware_status == FW_STATUS_5_READY, ("Firmware Download Fail\n"));
359 download_firmware_fail
:
360 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);