1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include "r8192E.h"
18#include "r8192E_hw.h"
19#include <linux/firmware.h>
20
21
22#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4 * (v / 4) - 8)
23
24enum firmware_init_step {
25 FW_INIT_STEP0_BOOT = 0,
26 FW_INIT_STEP1_MAIN = 1,
27 FW_INIT_STEP2_DATA = 2,
28};
29
30enum opt_rst_type {
31 OPT_SYSTEM_RESET = 0,
32 OPT_FIRMWARE_RESET = 1,
33};
34
35void firmware_init_param(struct net_device *dev)
36{
37 struct r8192_priv *priv = ieee80211_priv(dev);
38 rt_firmware *pfirmware = priv->pFirmware;
39
40 pfirmware->cmdpacket_frag_thresold =
41 GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE);
42}
43
44
45
46
47static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
48 u32 buffer_len)
49{
50 struct r8192_priv *priv = ieee80211_priv(dev);
51 bool rt_status = true;
52 u16 frag_threshold;
53 u16 frag_length, frag_offset = 0;
54 int i;
55
56 rt_firmware *pfirmware = priv->pFirmware;
57 struct sk_buff *skb;
58 unsigned char *seg_ptr;
59 cb_desc *tcb_desc;
60 u8 bLastIniPkt;
61
62 firmware_init_param(dev);
63
64
65 frag_threshold = pfirmware->cmdpacket_frag_thresold;
66 do {
67 if ((buffer_len - frag_offset) > frag_threshold) {
68 frag_length = frag_threshold ;
69 bLastIniPkt = 0;
70 } else {
71 frag_length = buffer_len - frag_offset;
72 bLastIniPkt = 1;
73 }
74
75
76
77
78
79 skb = dev_alloc_skb(frag_length + 4);
80 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
81 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
82 tcb_desc->queue_index = TXCMD_QUEUE;
83 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
84 tcb_desc->bLastIniPkt = bLastIniPkt;
85
86 seg_ptr = skb->data;
87
88
89
90
91 for (i = 0; i < frag_length; i += 4) {
92 *seg_ptr++ = ((i+0) < frag_length) ? code_virtual_address[i+3] : 0;
93 *seg_ptr++ = ((i+1) < frag_length) ? code_virtual_address[i+2] : 0;
94 *seg_ptr++ = ((i+2) < frag_length) ? code_virtual_address[i+1] : 0;
95 *seg_ptr++ = ((i+3) < frag_length) ? code_virtual_address[i+0] : 0;
96 }
97 tcb_desc->txbuf_size = (u16)i;
98 skb_put(skb, i);
99 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
100
101 code_virtual_address += frag_length;
102 frag_offset += frag_length;
103
104 } while (frag_offset < buffer_len);
105
106 return rt_status;
107}
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
124{
125 unsigned long timeout;
126 bool rt_status = true;
127 u32 CPU_status = 0;
128
129
130 timeout = jiffies + msecs_to_jiffies(20);
131 while (time_before(jiffies, timeout)) {
132 CPU_status = read_nic_dword(dev, CPU_GEN);
133
134 if (CPU_status & CPU_GEN_PUT_CODE_OK)
135 break;
136 msleep(2);
137 }
138
139 if (!(CPU_status & CPU_GEN_PUT_CODE_OK)) {
140 RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
141 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
142 } else {
143 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
144 }
145
146
147 CPU_status = read_nic_dword(dev, CPU_GEN);
148 write_nic_byte(dev, CPU_GEN,
149 (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff));
150 mdelay(1);
151
152
153 timeout = jiffies + msecs_to_jiffies(20);
154 while (time_before(jiffies, timeout)) {
155 CPU_status = read_nic_dword(dev, CPU_GEN);
156
157 if (CPU_status & CPU_GEN_BOOT_RDY)
158 break;
159 msleep(2);
160 }
161
162 if (!(CPU_status & CPU_GEN_BOOT_RDY))
163 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
164 else
165 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
166
167 return rt_status;
168
169CPUCheckMainCodeOKAndTurnOnCPU_Fail:
170 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
171 rt_status = FALSE;
172 return rt_status;
173}
174
175static bool CPUcheck_firmware_ready(struct net_device *dev)
176{
177 unsigned long timeout;
178 bool rt_status = true;
179 u32 CPU_status = 0;
180
181
182 timeout = jiffies + msecs_to_jiffies(20);
183 while (time_before(jiffies, timeout)) {
184 CPU_status = read_nic_dword(dev, CPU_GEN);
185
186 if (CPU_status & CPU_GEN_FIRM_RDY)
187 break;
188 msleep(2);
189 }
190
191 if (!(CPU_status & CPU_GEN_FIRM_RDY))
192 goto CPUCheckFirmwareReady_Fail;
193 else
194 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
195
196 return rt_status;
197
198CPUCheckFirmwareReady_Fail:
199 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
200 rt_status = false;
201 return rt_status;
202
203}
204
205bool init_firmware(struct net_device *dev)
206{
207 struct r8192_priv *priv = ieee80211_priv(dev);
208 bool rt_status = TRUE;
209 u32 file_length = 0;
210 u8 *mapped_file = NULL;
211 u32 init_step = 0;
212 enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
213 enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
214
215 rt_firmware *pfirmware = priv->pFirmware;
216 const struct firmware *fw_entry;
217 const char *fw_name[3] = { "RTL8192E/boot.img",
218 "RTL8192E/main.img",
219 "RTL8192E/data.img"};
220 int rc;
221
222 RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
223
224 if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
225
226 rst_opt = OPT_SYSTEM_RESET;
227 starting_state = FW_INIT_STEP0_BOOT;
228
229
230 } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
231
232 rst_opt = OPT_FIRMWARE_RESET;
233 starting_state = FW_INIT_STEP2_DATA;
234 } else {
235 RT_TRACE(COMP_FIRMWARE,
236 "PlatformInitFirmware: undefined firmware state\n");
237 }
238
239
240
241
242
243 for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) {
244
245
246
247
248 if (rst_opt == OPT_SYSTEM_RESET) {
249 if (pfirmware->firmware_buf_size[init_step] == 0) {
250 rc = request_firmware(&fw_entry, fw_name[init_step], &priv->pdev->dev);
251 if (rc < 0) {
252 RT_TRACE(COMP_FIRMWARE, "request firmware fail!\n");
253 goto download_firmware_fail;
254 }
255
256 if (fw_entry->size > sizeof(pfirmware->firmware_buf[init_step])) {
257 RT_TRACE(COMP_FIRMWARE, "img file size exceed the container buffer fail!\n");
258 goto download_firmware_fail;
259 }
260
261 if (init_step != FW_INIT_STEP1_MAIN) {
262 memcpy(pfirmware->firmware_buf[init_step], fw_entry->data, fw_entry->size);
263 pfirmware->firmware_buf_size[init_step] = fw_entry->size;
264
265 } else {
266 memset(pfirmware->firmware_buf[init_step], 0, 128);
267 memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data, fw_entry->size);
268 pfirmware->firmware_buf_size[init_step] = fw_entry->size+128;
269 }
270
271 if (rst_opt == OPT_SYSTEM_RESET)
272 release_firmware(fw_entry);
273 }
274 mapped_file = pfirmware->firmware_buf[init_step];
275 file_length = pfirmware->firmware_buf_size[init_step];
276 } else if (rst_opt == OPT_FIRMWARE_RESET) {
277
278 mapped_file = pfirmware->firmware_buf[init_step];
279 file_length = pfirmware->firmware_buf_size[init_step];
280 }
281
282
283
284
285
286
287
288
289
290 rt_status = fw_download_code(dev, mapped_file, file_length);
291 if (rt_status != TRUE)
292 goto download_firmware_fail;
293
294 switch (init_step) {
295 case FW_INIT_STEP0_BOOT:
296
297
298
299
300
301 pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
302
303
304
305
306
307 break;
308
309 case FW_INIT_STEP1_MAIN:
310
311
312 pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
313
314
315 rt_status = CPUcheck_maincodeok_turnonCPU(dev);
316 if (rt_status != TRUE) {
317 RT_TRACE(COMP_FIRMWARE,
318 "CPUcheck_maincodeok_turnonCPU fail!\n");
319 goto download_firmware_fail;
320 }
321
322 pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
323 break;
324
325 case FW_INIT_STEP2_DATA:
326
327 pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
328 mdelay(1);
329
330 rt_status = CPUcheck_firmware_ready(dev);
331 if (rt_status != TRUE) {
332 RT_TRACE(COMP_FIRMWARE,
333 "CPUcheck_firmware_ready fail(%d)!\n",
334 rt_status);
335 goto download_firmware_fail;
336 }
337
338
339 pfirmware->firmware_status = FW_STATUS_5_READY;
340 break;
341 }
342 }
343
344 RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
345 return rt_status;
346
347download_firmware_fail:
348 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
349 rt_status = FALSE;
350 return rt_status;
351
352}
353