1 /******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
4 * This program is distributed in the hope that it will be useful, but WITHOUT
5 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 * You should have received a copy of the GNU General Public License along with
10 * this program; if not, write to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
13 * The full GNU General Public License is included in this distribution in the
14 * file called LICENSE.
16 * Contact Information:
17 * wlanfae <wlanfae@realtek.com>
18 ******************************************************************************/
21 #include "r8192E_hw.h"
22 #include "r8192E_hwimg.h"
23 #include "r8192E_firmware.h"
24 #include <linux/firmware.h>
26 void firmware_init_param(struct net_device
*dev
)
28 struct r8192_priv
*priv
= rtllib_priv(dev
);
29 struct rt_firmware
*pfirmware
= priv
->pFirmware
;
31 pfirmware
->cmdpacket_frag_thresold
= GET_COMMAND_PACKET_FRAG_THRESHOLD(
32 MAX_TRANSMIT_BUFFER_SIZE
);
35 static bool fw_download_code(struct net_device
*dev
, u8
*code_virtual_address
,
38 struct r8192_priv
*priv
= rtllib_priv(dev
);
39 bool rt_status
= true;
41 u16 frag_length
, frag_offset
= 0;
44 struct rt_firmware
*pfirmware
= priv
->pFirmware
;
46 unsigned char *seg_ptr
;
47 struct cb_desc
*tcb_desc
;
50 firmware_init_param(dev
);
51 frag_threshold
= pfirmware
->cmdpacket_frag_thresold
;
53 if ((buffer_len
- frag_offset
) > frag_threshold
) {
54 frag_length
= frag_threshold
;
58 frag_length
= buffer_len
- frag_offset
;
63 skb
= dev_alloc_skb(frag_length
+ 4);
64 memcpy((unsigned char *)(skb
->cb
), &dev
, sizeof(dev
));
65 tcb_desc
= (struct cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
66 tcb_desc
->queue_index
= TXCMD_QUEUE
;
67 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_INIT
;
68 tcb_desc
->bLastIniPkt
= bLastIniPkt
;
71 for (i
= 0; i
< frag_length
; i
+= 4) {
72 *seg_ptr
++ = ((i
+0) < frag_length
) ?
73 code_virtual_address
[i
+3] : 0;
74 *seg_ptr
++ = ((i
+1) < frag_length
) ?
75 code_virtual_address
[i
+2] : 0;
76 *seg_ptr
++ = ((i
+2) < frag_length
) ?
77 code_virtual_address
[i
+1] : 0;
78 *seg_ptr
++ = ((i
+3) < frag_length
) ?
79 code_virtual_address
[i
+0] : 0;
81 tcb_desc
->txbuf_size
= (u16
)i
;
84 if (!priv
->rtllib
->check_nic_enough_desc(dev
, tcb_desc
->queue_index
) ||
85 (!skb_queue_empty(&priv
->rtllib
->skb_waitQ
[tcb_desc
->queue_index
])) ||
86 (priv
->rtllib
->queue_stop
)) {
87 RT_TRACE(COMP_FIRMWARE
, "===================> tx "
89 skb_queue_tail(&priv
->rtllib
->skb_waitQ
90 [tcb_desc
->queue_index
], skb
);
92 priv
->rtllib
->softmac_hard_start_xmit(skb
, dev
);
95 code_virtual_address
+= frag_length
;
96 frag_offset
+= frag_length
;
98 } while (frag_offset
< buffer_len
);
100 write_nic_byte(dev
, TPPoll
, TPPoll_CQ
);
105 static bool CPUcheck_maincodeok_turnonCPU(struct net_device
*dev
)
107 bool rt_status
= true;
109 unsigned long timeout
;
111 timeout
= jiffies
+ MSECS(200);
112 while (time_before(jiffies
, timeout
)) {
113 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
114 if (CPU_status
& CPU_GEN_PUT_CODE_OK
)
119 if (!(CPU_status
&CPU_GEN_PUT_CODE_OK
)) {
120 RT_TRACE(COMP_ERR
, "Download Firmware: Put code fail!\n");
121 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
123 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Put code ok!\n");
126 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
127 write_nic_byte(dev
, CPU_GEN
,
128 (u8
)((CPU_status
|CPU_GEN_PWR_STB_CPU
)&0xff));
131 timeout
= jiffies
+ MSECS(200);
132 while (time_before(jiffies
, timeout
)) {
133 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
134 if (CPU_status
&CPU_GEN_BOOT_RDY
)
139 if (!(CPU_status
&CPU_GEN_BOOT_RDY
))
140 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
142 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Boot ready!\n");
146 CPUCheckMainCodeOKAndTurnOnCPU_Fail
:
147 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __func__
);
152 static bool CPUcheck_firmware_ready(struct net_device
*dev
)
155 bool rt_status
= true;
157 unsigned long timeout
;
159 timeout
= jiffies
+ MSECS(20);
160 while (time_before(jiffies
, timeout
)) {
161 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
162 if (CPU_status
&CPU_GEN_FIRM_RDY
)
167 if (!(CPU_status
&CPU_GEN_FIRM_RDY
))
168 goto CPUCheckFirmwareReady_Fail
;
170 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Firmware ready!\n");
174 CPUCheckFirmwareReady_Fail
:
175 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __func__
);
181 static bool firmware_check_ready(struct net_device
*dev
,
184 struct r8192_priv
*priv
= rtllib_priv(dev
);
185 struct rt_firmware
*pfirmware
= priv
->pFirmware
;
186 bool rt_status
= true;
188 switch (load_fw_status
) {
189 case FW_INIT_STEP0_BOOT
:
190 pfirmware
->firmware_status
= FW_STATUS_1_MOVE_BOOT_CODE
;
193 case FW_INIT_STEP1_MAIN
:
194 pfirmware
->firmware_status
= FW_STATUS_2_MOVE_MAIN_CODE
;
196 rt_status
= CPUcheck_maincodeok_turnonCPU(dev
);
198 pfirmware
->firmware_status
= FW_STATUS_3_TURNON_CPU
;
200 RT_TRACE(COMP_FIRMWARE
, "CPUcheck_maincodeok_turnon"
205 case FW_INIT_STEP2_DATA
:
206 pfirmware
->firmware_status
= FW_STATUS_4_MOVE_DATA_CODE
;
209 rt_status
= CPUcheck_firmware_ready(dev
);
211 pfirmware
->firmware_status
= FW_STATUS_5_READY
;
213 RT_TRACE(COMP_FIRMWARE
, "CPUcheck_firmware_ready fail"
214 "(%d)!\n", rt_status
);
219 RT_TRACE(COMP_FIRMWARE
, "Unknown firware status");
226 bool init_firmware(struct net_device
*dev
)
228 struct r8192_priv
*priv
= rtllib_priv(dev
);
229 bool rt_status
= true;
231 u8
*firmware_img_buf
[3] = { &Rtl8192PciEFwBootArray
[0],
232 &Rtl8192PciEFwMainArray
[0],
233 &Rtl8192PciEFwDataArray
[0]};
235 u32 firmware_img_len
[3] = { sizeof(Rtl8192PciEFwBootArray
),
236 sizeof(Rtl8192PciEFwMainArray
),
237 sizeof(Rtl8192PciEFwDataArray
)};
239 u8
*mapped_file
= NULL
;
241 enum opt_rst_type rst_opt
= OPT_SYSTEM_RESET
;
242 enum firmware_init_step starting_state
= FW_INIT_STEP0_BOOT
;
244 struct rt_firmware
*pfirmware
= priv
->pFirmware
;
246 RT_TRACE(COMP_FIRMWARE
, " PlatformInitFirmware()==>\n");
248 if (pfirmware
->firmware_status
== FW_STATUS_0_INIT
) {
249 rst_opt
= OPT_SYSTEM_RESET
;
250 starting_state
= FW_INIT_STEP0_BOOT
;
252 } else if (pfirmware
->firmware_status
== FW_STATUS_5_READY
) {
253 rst_opt
= OPT_FIRMWARE_RESET
;
254 starting_state
= FW_INIT_STEP2_DATA
;
256 RT_TRACE(COMP_FIRMWARE
, "PlatformInitFirmware: undefined"
257 " firmware state\n");
260 priv
->firmware_source
= FW_SOURCE_IMG_FILE
;
261 for (init_step
= starting_state
; init_step
<= FW_INIT_STEP2_DATA
;
263 if (rst_opt
== OPT_SYSTEM_RESET
) {
264 switch (priv
->firmware_source
) {
265 case FW_SOURCE_IMG_FILE
:
267 if (pfirmware
->firmware_buf_size
[init_step
] == 0) {
268 const char *fw_name
[3] = { "RTL8192E/boot.img",
272 const struct firmware
*fw_entry
;
274 rc
= request_firmware(&fw_entry
,
275 fw_name
[init_step
], &priv
->pdev
->dev
);
277 RT_TRACE(COMP_FIRMWARE
, "request firm"
279 goto download_firmware_fail
;
282 sizeof(pfirmware
->firmware_buf
[init_step
])) {
283 RT_TRACE(COMP_FIRMWARE
, "img file size "
284 "exceed the container struct "
286 goto download_firmware_fail
;
289 if (init_step
!= FW_INIT_STEP1_MAIN
) {
290 memcpy(pfirmware
->firmware_buf
[init_step
],
291 fw_entry
->data
, fw_entry
->size
);
292 pfirmware
->firmware_buf_size
[init_step
] =
296 memset(pfirmware
->firmware_buf
[init_step
],
298 memcpy(&pfirmware
->firmware_buf
[init_step
][128],
299 fw_entry
->data
, fw_entry
->size
);
300 pfirmware
->firmware_buf_size
[init_step
] =
301 fw_entry
->size
+ 128;
304 if (rst_opt
== OPT_SYSTEM_RESET
)
305 release_firmware(fw_entry
);
307 mapped_file
= pfirmware
->firmware_buf
[init_step
];
308 file_length
= pfirmware
->firmware_buf_size
[init_step
];
311 case FW_SOURCE_HEADER_FILE
:
312 mapped_file
= firmware_img_buf
[init_step
];
313 file_length
= firmware_img_len
[init_step
];
314 if (init_step
== FW_INIT_STEP2_DATA
) {
315 memcpy(pfirmware
->firmware_buf
[init_step
], mapped_file
, file_length
);
316 pfirmware
->firmware_buf_size
[init_step
] = file_length
;
325 } else if (rst_opt
== OPT_FIRMWARE_RESET
) {
326 mapped_file
= pfirmware
->firmware_buf
[init_step
];
327 file_length
= pfirmware
->firmware_buf_size
[init_step
];
330 rt_status
= fw_download_code(dev
, mapped_file
, file_length
);
331 if (rt_status
!= true) {
332 goto download_firmware_fail
;
335 if (!firmware_check_ready(dev
, init_step
)) {
336 goto download_firmware_fail
;
340 RT_TRACE(COMP_FIRMWARE
, "Firmware Download Success\n");
343 download_firmware_fail
:
344 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __func__
);