GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / rtl8192e / r819xE_firmware.c
blob793a1754555413ac14f027eecf16ad97b0fc608d
1 /*
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
11 * Returns:
12 * NDIS_STATUS_FAILURE - the following initialization process
13 * should be terminated
14 * NDIS_STATUS_SUCCESS - if firmware initialization process
15 * success
18 #include "r8192E.h"
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,
32 enum opt_rst_type {
33 OPT_SYSTEM_RESET = 0,
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,
50 u32 buffer_len)
52 struct r8192_priv *priv = ieee80211_priv(dev);
53 bool rt_status = true;
54 u16 frag_threshold;
55 u16 frag_length, frag_offset = 0;
56 int i;
58 rt_firmware *pfirmware = priv->pFirmware;
59 struct sk_buff *skb;
60 unsigned char *seg_ptr;
61 cb_desc *tcb_desc;
62 u8 bLastIniPkt;
64 firmware_init_param(dev);
66 /* Fragmentation might be required */
67 frag_threshold = pfirmware->cmdpacket_frag_thresold;
68 do {
69 if ((buffer_len - frag_offset) > frag_threshold) {
70 frag_length = frag_threshold ;
71 bLastIniPkt = 0;
72 } else {
73 frag_length = buffer_len - frag_offset;
74 bLastIniPkt = 1;
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;
88 seg_ptr = skb->data;
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;
107 skb_put(skb, 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);
115 return rt_status;
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
123 * back before return
125 * Arguments: The pointer of the adapter
127 * Returns:
128 * NDIS_STATUS_FAILURE - the following initialization process should be
129 * terminated
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;
136 u32 CPU_status = 0;
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)
144 break;
145 msleep(2);
148 if (!(CPU_status & CPU_GEN_PUT_CODE_OK)) {
149 RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
150 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
151 } else {
152 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
155 /* Turn On CPU */
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));
159 mdelay(1);
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)
167 break;
168 msleep(2);
171 if (!(CPU_status & CPU_GEN_BOOT_RDY))
172 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
173 else
174 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
176 return rt_status;
178 CPUCheckMainCodeOKAndTurnOnCPU_Fail:
179 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
180 rt_status = FALSE;
181 return rt_status;
184 static bool CPUcheck_firmware_ready(struct net_device *dev)
186 unsigned long timeout;
187 bool rt_status = true;
188 u32 CPU_status = 0;
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)
196 break;
197 msleep(2);
200 if (!(CPU_status & CPU_GEN_FIRM_RDY))
201 goto CPUCheckFirmwareReady_Fail;
202 else
203 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
205 return rt_status;
207 CPUCheckFirmwareReady_Fail:
208 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
209 rt_status = false;
210 return rt_status;
214 bool init_firmware(struct net_device *dev)
216 struct r8192_priv *priv = ieee80211_priv(dev);
217 bool rt_status = true;
218 u32 file_length = 0;
219 u8 *mapped_file = NULL;
220 u32 init_step = 0;
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",
227 "RTL8192E/main.img",
228 "RTL8192E/data.img"};
229 int rc;
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;
243 } else {
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; \
253 init_step++) {
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);
263 if (rc < 0) {
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;
279 } else {
280 memset(pfirmware->firmware_buf[init_step], 0, 128);
281 memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data,
282 fw_entry->size);
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
301 * wait queue.
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;
310 switch (init_step) {
311 case FW_INIT_STEP0_BOOT:
312 /* Download boot
313 * initialize command descriptor.
314 * will set polling bit when firmware code is also
315 * configured
317 pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
318 /* mdelay(1000); */
320 * To initialize IMEM, CPU move code from 0x80000080,
321 * hence, we send 0x80 byte packet
323 break;
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;
339 break;
341 case FW_INIT_STEP2_DATA:
342 /* download initial data code */
343 pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
344 mdelay(1);
346 rt_status = CPUcheck_firmware_ready(dev);
347 if (rt_status != TRUE) {
348 RT_TRACE(COMP_FIRMWARE,
349 "CPUcheck_firmware_ready fail(%d)!\n",
350 rt_status);
351 goto download_firmware_fail;
354 /* wait until data code is initialized ready.*/
355 pfirmware->firmware_status = FW_STATUS_5_READY;
356 break;
360 RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
361 return rt_status;
363 download_firmware_fail:
364 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
365 rt_status = false;
366 return rt_status;
369 MODULE_FIRMWARE("RTL8192E/boot.img");
370 MODULE_FIRMWARE("RTL8192E/main.img");
371 MODULE_FIRMWARE("RTL8192E/data.img");