1 /************************************************************************************************** 2 * Procedure: Init boot code/firmware code/data session 3 * 4 * Description: This routine will initialize 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. 7 * 8 * Arguments: The pointer of the adapter 9 10 * Returns: 11 * NDIS_STATUS_FAILURE - the following initialization process should be terminated 12 * NDIS_STATUS_SUCCESS - if firmware initialization process success 13 **************************************************************************************************/ 14 15 #include "r8192U.h" 16 #include "r8192U_hw.h" 17 #include "r819xU_firmware_img.h" 18 #include "r819xU_firmware.h" 19 #include <linux/firmware.h> 20 21 static void firmware_init_param(struct net_device *dev) 22 { 23 struct r8192_priv *priv = ieee80211_priv(dev); 24 rt_firmware *pfirmware = priv->pFirmware; 25 26 pfirmware->cmdpacket_frag_thresold = GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE); 27 } 28 29 /* 30 * segment the img and use the ptr and length to remember info on each segment 31 * 32 */ 33 static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, 34 u32 buffer_len) 35 { 36 struct r8192_priv *priv = ieee80211_priv(dev); 37 bool rt_status = true; 38 u16 frag_threshold; 39 u16 frag_length, frag_offset = 0; 40 int i; 41 42 rt_firmware *pfirmware = priv->pFirmware; 43 struct sk_buff *skb; 44 unsigned char *seg_ptr; 45 cb_desc *tcb_desc; 46 u8 bLastIniPkt; 47 u8 index; 48 49 firmware_init_param(dev); 50 /* Fragmentation might be required */ 51 frag_threshold = pfirmware->cmdpacket_frag_thresold; 52 do { 53 if ((buffer_len - frag_offset) > frag_threshold) { 54 frag_length = frag_threshold; 55 bLastIniPkt = 0; 56 57 } else { 58 frag_length = buffer_len - frag_offset; 59 bLastIniPkt = 1; 60 61 } 62 63 /* Allocate skb buffer to contain firmware info and tx descriptor info 64 * add 4 to avoid packet appending overflow. 65 * */ 66 skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4); 67 if (!skb) 68 return false; 69 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); 70 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); 71 tcb_desc->queue_index = TXCMD_QUEUE; 72 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT; 73 tcb_desc->bLastIniPkt = bLastIniPkt; 74 75 skb_reserve(skb, USB_HWDESC_HEADER_LEN); 76 seg_ptr = skb->data; 77 /* 78 * Transform from little endian to big endian 79 * and pending zero 80 */ 81 for (i = 0; i < frag_length; i += 4) { 82 *seg_ptr++ = ((i+0) < frag_length)?code_virtual_address[i+3] : 0; 83 *seg_ptr++ = ((i+1) < frag_length)?code_virtual_address[i+2] : 0; 84 *seg_ptr++ = ((i+2) < frag_length)?code_virtual_address[i+1] : 0; 85 *seg_ptr++ = ((i+3) < frag_length)?code_virtual_address[i+0] : 0; 86 } 87 tcb_desc->txbuf_size = (u16)i; 88 skb_put(skb, i); 89 90 index = tcb_desc->queue_index; 91 if (!priv->ieee80211->check_nic_enough_desc(dev, index) || 92 (!skb_queue_empty(&priv->ieee80211->skb_waitQ[index])) || 93 (priv->ieee80211->queue_stop)) { 94 RT_TRACE(COMP_FIRMWARE, "=====================================================> tx full!\n"); 95 skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); 96 } else { 97 priv->ieee80211->softmac_hard_start_xmit(skb, dev); 98 } 99 100 code_virtual_address += frag_length; 101 frag_offset += frag_length; 102 103 } while (frag_offset < buffer_len); 104 105 return rt_status; 106 107 } 108 109 /* 110 * Procedure: Check whether main code is download OK. If OK, turn on CPU 111 * 112 * Description: CPU register locates in different page against general register. 113 * Switch to CPU register in the begin and switch back before return 114 * 115 * 116 * Arguments: The pointer of the adapter 117 * 118 * Returns: 119 * NDIS_STATUS_FAILURE - the following initialization process should 120 * be terminated 121 * NDIS_STATUS_SUCCESS - if firmware initialization process success 122 */ 123 static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev) 124 { 125 bool rt_status = true; 126 int check_putcodeOK_time = 200000, check_bootOk_time = 200000; 127 u32 CPU_status = 0; 128 129 /* Check whether put code OK */ 130 do { 131 read_nic_dword(dev, CPU_GEN, &CPU_status); 132 133 if (CPU_status&CPU_GEN_PUT_CODE_OK) 134 break; 135 136 } while (check_putcodeOK_time--); 137 138 if (!(CPU_status&CPU_GEN_PUT_CODE_OK)) { 139 RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n"); 140 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail; 141 } else { 142 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n"); 143 } 144 145 /* Turn On CPU */ 146 read_nic_dword(dev, CPU_GEN, &CPU_status); 147 write_nic_byte(dev, CPU_GEN, 148 (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff)); 149 mdelay(1000); 150 151 /* Check whether CPU boot OK */ 152 do { 153 read_nic_dword(dev, CPU_GEN, &CPU_status); 154 155 if (CPU_status&CPU_GEN_BOOT_RDY) 156 break; 157 } while (check_bootOk_time--); 158 159 if (!(CPU_status&CPU_GEN_BOOT_RDY)) 160 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail; 161 else 162 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n"); 163 164 return rt_status; 165 166 CPUCheckMainCodeOKAndTurnOnCPU_Fail: 167 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__); 168 rt_status = false; 169 return rt_status; 170 } 171 172 static bool CPUcheck_firmware_ready(struct net_device *dev) 173 { 174 175 bool rt_status = true; 176 int check_time = 200000; 177 u32 CPU_status = 0; 178 179 /* Check Firmware Ready */ 180 do { 181 read_nic_dword(dev, CPU_GEN, &CPU_status); 182 183 if (CPU_status&CPU_GEN_FIRM_RDY) 184 break; 185 186 } while (check_time--); 187 188 if (!(CPU_status&CPU_GEN_FIRM_RDY)) 189 goto CPUCheckFirmwareReady_Fail; 190 else 191 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n"); 192 193 return rt_status; 194 195 CPUCheckFirmwareReady_Fail: 196 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__); 197 rt_status = false; 198 return rt_status; 199 200 } 201 202 bool init_firmware(struct net_device *dev) 203 { 204 struct r8192_priv *priv = ieee80211_priv(dev); 205 bool rt_status = true; 206 207 u32 file_length = 0; 208 u8 *mapped_file = NULL; 209 u32 init_step = 0; 210 opt_rst_type_e rst_opt = OPT_SYSTEM_RESET; 211 firmware_init_step_e starting_state = FW_INIT_STEP0_BOOT; 212 213 rt_firmware *pfirmware = priv->pFirmware; 214 const struct firmware *fw_entry; 215 const char *fw_name[3] = { "RTL8192U/boot.img", 216 "RTL8192U/main.img", 217 "RTL8192U/data.img"}; 218 int rc; 219 220 RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n"); 221 222 if (pfirmware->firmware_status == FW_STATUS_0_INIT) { 223 /* it is called by reset */ 224 rst_opt = OPT_SYSTEM_RESET; 225 starting_state = FW_INIT_STEP0_BOOT; 226 /* TODO: system reset */ 227 228 } else if (pfirmware->firmware_status == FW_STATUS_5_READY) { 229 /* it is called by Initialize */ 230 rst_opt = OPT_FIRMWARE_RESET; 231 starting_state = FW_INIT_STEP2_DATA; 232 } else { 233 RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined firmware state\n"); 234 } 235 236 /* 237 * Download boot, main, and data image for System reset. 238 * Download data image for firmware reset 239 */ 240 for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) { 241 /* 242 * Open image file, and map file to continuous memory if open file success. 243 * or read image file from array. Default load from IMG file 244 */ 245 if (rst_opt == OPT_SYSTEM_RESET) { 246 rc = request_firmware(&fw_entry, fw_name[init_step], &priv->udev->dev); 247 if (rc < 0) { 248 RT_TRACE(COMP_ERR, "request firmware fail!\n"); 249 goto download_firmware_fail; 250 } 251 252 if (fw_entry->size > sizeof(pfirmware->firmware_buf)) { 253 RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n"); 254 goto download_firmware_fail; 255 } 256 257 if (init_step != FW_INIT_STEP1_MAIN) { 258 memcpy(pfirmware->firmware_buf, fw_entry->data, fw_entry->size); 259 mapped_file = pfirmware->firmware_buf; 260 file_length = fw_entry->size; 261 } else { 262 memset(pfirmware->firmware_buf, 0, 128); 263 memcpy(&pfirmware->firmware_buf[128], fw_entry->data, fw_entry->size); 264 mapped_file = pfirmware->firmware_buf; 265 file_length = fw_entry->size + 128; 266 } 267 pfirmware->firmware_buf_size = file_length; 268 } else if (rst_opt == OPT_FIRMWARE_RESET) { 269 /* we only need to download data.img here */ 270 mapped_file = pfirmware->firmware_buf; 271 file_length = pfirmware->firmware_buf_size; 272 } 273 274 /* Download image file */ 275 /* The firmware download process is just as following, 276 * 1. that is each packet will be segmented and inserted to the wait queue. 277 * 2. each packet segment will be put in the skb_buff packet. 278 * 3. each skb_buff packet data content will already include the firmware info 279 * and Tx descriptor info 280 * */ 281 rt_status = fw_download_code(dev, mapped_file, file_length); 282 if (rst_opt == OPT_SYSTEM_RESET) 283 release_firmware(fw_entry); 284 285 if (!rt_status) 286 goto download_firmware_fail; 287 288 switch (init_step) { 289 case FW_INIT_STEP0_BOOT: 290 /* Download boot 291 * initialize command descriptor. 292 * will set polling bit when firmware code is also configured 293 */ 294 pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE; 295 /* mdelay(1000); */ 296 /* 297 * To initialize IMEM, CPU move code from 0x80000080, 298 * hence, we send 0x80 byte packet 299 */ 300 break; 301 302 case FW_INIT_STEP1_MAIN: 303 /* Download firmware code. Wait until Boot Ready and Turn on CPU */ 304 pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE; 305 306 /* Check Put Code OK and Turn On CPU */ 307 rt_status = CPUcheck_maincodeok_turnonCPU(dev); 308 if (!rt_status) { 309 RT_TRACE(COMP_ERR, "CPUcheck_maincodeok_turnonCPU fail!\n"); 310 goto download_firmware_fail; 311 } 312 313 pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU; 314 break; 315 316 case FW_INIT_STEP2_DATA: 317 /* download initial data code */ 318 pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE; 319 mdelay(1); 320 321 rt_status = CPUcheck_firmware_ready(dev); 322 if (!rt_status) { 323 RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n", rt_status); 324 goto download_firmware_fail; 325 } 326 327 /* wait until data code is initialized ready.*/ 328 pfirmware->firmware_status = FW_STATUS_5_READY; 329 break; 330 } 331 } 332 333 RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n"); 334 return rt_status; 335 336 download_firmware_fail: 337 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__); 338 rt_status = false; 339 return rt_status; 340 341 } 342 343 MODULE_FIRMWARE("RTL8192U/boot.img"); 344 MODULE_FIRMWARE("RTL8192U/main.img"); 345 MODULE_FIRMWARE("RTL8192U/data.img"); 346