2 * Procedure: Init boot code/firmware code/data session
4 * Description: This routine will intialize firmware. If any error occurs
5 * during the initialization process, the routine shall terminate
6 * immediately and return fail. NIC driver should call
7 * NdisOpenFile only from MiniportInitialize.
9 * Arguments: The pointer of the adapter
12 * NDIS_STATUS_FAILURE - the following initialization process
13 * should be terminated
14 * NDIS_STATUS_SUCCESS - if firmware initialization process
19 #include "r8192E_hw.h"
21 #include <linux/firmware.h>
23 /* It should be double word alignment */
24 #define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4 * (v / 4) - 8)
26 enum firmware_init_step {
27 FW_INIT_STEP0_BOOT = 0,
28 FW_INIT_STEP1_MAIN = 1,
29 FW_INIT_STEP2_DATA = 2,
34 OPT_FIRMWARE_RESET = 1,
37 void firmware_init_param(struct net_device *dev)
39 struct r8192_priv *priv = ieee80211_priv(dev);
40 rt_firmware *pfirmware = priv->pFirmware;
42 pfirmware->cmdpacket_frag_thresold =
43 GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE);
47 * segment the img and use the ptr and length to remember info on each segment
49 static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
52 struct r8192_priv *priv = ieee80211_priv(dev);
53 bool rt_status = true;
55 u16 frag_length, frag_offset = 0;
58 rt_firmware *pfirmware = priv->pFirmware;
60 unsigned char *seg_ptr;
64 firmware_init_param(dev);
66 /* Fragmentation might be required */
67 frag_threshold = pfirmware->cmdpacket_frag_thresold;
69 if ((buffer_len - frag_offset) > frag_threshold) {
70 frag_length = frag_threshold ;
73 frag_length = buffer_len - frag_offset;
78 * Allocate skb buffer to contain firmware info and tx
79 * descriptor info add 4 to avoid packet appending overflow.
81 skb = dev_alloc_skb(frag_length + 4);
82 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
83 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
84 tcb_desc->queue_index = TXCMD_QUEUE;
85 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
86 tcb_desc->bLastIniPkt = bLastIniPkt;
91 * Transform from little endian to big endian and pending zero
93 for (i = 0; i < frag_length; i += 4) {
94 *seg_ptr++ = ((i+0) < frag_length) ? \
95 code_virtual_address[i+3] : 0;
97 *seg_ptr++ = ((i+1) < frag_length) ? \
98 code_virtual_address[i+2] : 0;
100 *seg_ptr++ = ((i+2) < frag_length) ? \
101 code_virtual_address[i+1] : 0;
103 *seg_ptr++ = ((i+3) < frag_length) ? \
104 code_virtual_address[i+0] : 0;
106 tcb_desc->txbuf_size = (u16)i;
108 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
110 code_virtual_address += frag_length;
111 frag_offset += frag_length;
113 } while (frag_offset < buffer_len);
119 * Procedure: Check whether main code is download OK. If OK, turn on CPU
121 * Description: CPU register locates in different page against general
122 * register. Switch to CPU register in the begin and switch
125 * Arguments: The pointer of the adapter
128 * NDIS_STATUS_FAILURE - the following initialization process should be
130 * NDIS_STATUS_SUCCESS - if firmware initialization process success
132 static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
134 unsigned long timeout;
135 bool rt_status = true;
138 /* Check whether put code OK */
139 timeout = jiffies + msecs_to_jiffies(20);
140 while (time_before(jiffies, timeout)) {
141 CPU_status = read_nic_dword(dev, CPU_GEN);
143 if (CPU_status & CPU_GEN_PUT_CODE_OK)
148 if (!(CPU_status & CPU_GEN_PUT_CODE_OK)) {
149 RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
150 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
152 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
156 CPU_status = read_nic_dword(dev, CPU_GEN);
157 write_nic_byte(dev, CPU_GEN,
158 (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff));
161 /* Check whether CPU boot OK */
162 timeout = jiffies + msecs_to_jiffies(20);
163 while (time_before(jiffies, timeout)) {
164 CPU_status = read_nic_dword(dev, CPU_GEN);
166 if (CPU_status & CPU_GEN_BOOT_RDY)
171 if (!(CPU_status & CPU_GEN_BOOT_RDY))
172 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
174 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
178 CPUCheckMainCodeOKAndTurnOnCPU_Fail:
179 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
184 static bool CPUcheck_firmware_ready(struct net_device *dev)
186 unsigned long timeout;
187 bool rt_status = true;
190 /* Check Firmware Ready */
191 timeout = jiffies + msecs_to_jiffies(20);
192 while (time_before(jiffies, timeout)) {
193 CPU_status = read_nic_dword(dev, CPU_GEN);
195 if (CPU_status & CPU_GEN_FIRM_RDY)
200 if (!(CPU_status & CPU_GEN_FIRM_RDY))
201 goto CPUCheckFirmwareReady_Fail;
203 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
207 CPUCheckFirmwareReady_Fail:
208 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
214 bool init_firmware(struct net_device *dev)
216 struct r8192_priv *priv = ieee80211_priv(dev);
217 bool rt_status = true;
219 u8 *mapped_file = NULL;
221 enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
222 enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
224 rt_firmware *pfirmware = priv->pFirmware;
225 const struct firmware *fw_entry;
226 const char *fw_name[3] = { "RTL8192E/boot.img",
228 "RTL8192E/data.img"};
231 RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
233 if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
234 /* it is called by reset */
235 rst_opt = OPT_SYSTEM_RESET;
236 starting_state = FW_INIT_STEP0_BOOT;
237 /* TODO: system reset */
239 } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
240 /* it is called by Initialize */
241 rst_opt = OPT_FIRMWARE_RESET;
242 starting_state = FW_INIT_STEP2_DATA;
244 RT_TRACE(COMP_FIRMWARE,
245 "PlatformInitFirmware: undefined firmware state\n");
249 * Download boot, main, and data image for System reset.
250 * Download data image for firmware reseta
252 for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; \
255 * Open Image file, and map file to contineous memory if open file success.
256 * or read image file from array. Default load from IMG file
258 if (rst_opt == OPT_SYSTEM_RESET) {
259 if (pfirmware->firmware_buf_size[init_step] == 0) {
260 rc = request_firmware(&fw_entry,
261 fw_name[init_step], &priv->pdev->dev);
264 RT_TRACE(COMP_FIRMWARE, "request firmware fail!\n");
265 goto download_firmware_fail;
268 if (fw_entry->size > sizeof(pfirmware->firmware_buf[init_step])) {
269 RT_TRACE(COMP_FIRMWARE, \
270 "img file size exceed the container buffer fail!\n");
271 goto download_firmware_fail;
274 if (init_step != FW_INIT_STEP1_MAIN) {
275 memcpy(pfirmware->firmware_buf[init_step],
276 fw_entry->data, fw_entry->size);
277 pfirmware->firmware_buf_size[init_step] = fw_entry->size;
280 memset(pfirmware->firmware_buf[init_step], 0, 128);
281 memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data,
283 pfirmware->firmware_buf_size[init_step] = fw_entry->size+128;
286 if (rst_opt == OPT_SYSTEM_RESET)
287 release_firmware(fw_entry);
289 mapped_file = pfirmware->firmware_buf[init_step];
290 file_length = pfirmware->firmware_buf_size[init_step];
292 } else if (rst_opt == OPT_FIRMWARE_RESET) {
293 /* we only need to download data.img here */
294 mapped_file = pfirmware->firmware_buf[init_step];
295 file_length = pfirmware->firmware_buf_size[init_step];
298 /* Download image file */
299 /* The firmware download process is just as following,
300 * 1. that is each packet will be segmented and inserted to the
302 * 2. each packet segment will be put in the skb_buff packet.
303 * 3. each skb_buff packet data content will already include
304 * the firmware info and Tx descriptor info
306 rt_status = fw_download_code(dev, mapped_file, file_length);
307 if (rt_status != TRUE)
308 goto download_firmware_fail;
311 case FW_INIT_STEP0_BOOT:
313 * initialize command descriptor.
314 * will set polling bit when firmware code is also
317 pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
320 * To initialize IMEM, CPU move code from 0x80000080,
321 * hence, we send 0x80 byte packet
325 case FW_INIT_STEP1_MAIN:
326 /* Download firmware code.
327 * Wait until Boot Ready and Turn on CPU */
328 pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
330 /* Check Put Code OK and Turn On CPU */
331 rt_status = CPUcheck_maincodeok_turnonCPU(dev);
332 if (rt_status != TRUE) {
333 RT_TRACE(COMP_FIRMWARE,
334 "CPUcheck_maincodeok_turnonCPU fail!\n");
335 goto download_firmware_fail;
338 pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
341 case FW_INIT_STEP2_DATA:
342 /* download initial data code */
343 pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
346 rt_status = CPUcheck_firmware_ready(dev);
347 if (rt_status != TRUE) {
348 RT_TRACE(COMP_FIRMWARE,
349 "CPUcheck_firmware_ready fail(%d)!\n",
351 goto download_firmware_fail;
354 /* wait until data code is initialized ready.*/
355 pfirmware->firmware_status = FW_STATUS_5_READY;
360 RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
363 download_firmware_fail:
364 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
369 MODULE_FIRMWARE("RTL8192E/boot.img");
370 MODULE_FIRMWARE("RTL8192E/main.img");
371 MODULE_FIRMWARE("RTL8192E/data.img");