r819xU_firmware.c 10 KB

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