PageRenderTime 41ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 1ms

/drivers/staging/rtl8192su/r8192S_firmware.c

https://github.com/dmitriy103/bravo_kernel-2.6.35
C | 475 lines | 345 code | 67 blank | 63 comment | 45 complexity | f0344b7ee9be72e67cf04bc62deee89c MD5 | raw file
  1. /**************************************************************************************************
  2. * Procedure: Init boot code/firmware code/data session
  3. *
  4. * Description: This routine will intialize 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 "r8192S_firmware.h"
  15. #include <linux/unistd.h>
  16. #include "r8192S_hw.h"
  17. #include "r8192SU_HWImg.h"
  18. #include <linux/firmware.h>
  19. #define byte(x,n) ( (x >> (8 * n)) & 0xff )
  20. //
  21. // Description: This routine will intialize firmware. If any error occurs during the initialization
  22. // process, the routine shall terminate immediately and return fail.
  23. //
  24. // Arguments: The pointer of the adapter
  25. // Code address (Virtual address, should fill descriptor with physical address)
  26. // Code size
  27. // Created by Roger, 2008.04.10.
  28. //
  29. bool FirmwareDownloadCode(struct net_device *dev,
  30. u8 *code_virtual_address,
  31. u32 buffer_len)
  32. {
  33. struct r8192_priv *priv = ieee80211_priv(dev);
  34. bool rt_status = true;
  35. /* Fragmentation might be required in 90/92 but not in 92S */
  36. u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE;
  37. u16 frag_length, frag_offset = 0;
  38. struct sk_buff *skb;
  39. unsigned char *seg_ptr;
  40. cb_desc *tcb_desc;
  41. u8 bLastIniPkt = 0;
  42. u16 ExtraDescOffset = 0;
  43. if (buffer_len >= MAX_FIRMWARE_CODE_SIZE - USB_HWDESC_HEADER_LEN) {
  44. RT_TRACE(COMP_ERR, "(%s): Firmware exceeds"
  45. " MAX_FIRMWARE_CODE_SIZE\n", __func__);
  46. goto cmdsend_downloadcode_fail;
  47. }
  48. ExtraDescOffset = USB_HWDESC_HEADER_LEN;
  49. do {
  50. if((buffer_len-frag_offset) > frag_threshold)
  51. frag_length = frag_threshold + ExtraDescOffset;
  52. else {
  53. frag_length = (u16)(buffer_len -
  54. frag_offset + ExtraDescOffset);
  55. bLastIniPkt = 1;
  56. }
  57. /*
  58. * Allocate skb buffer to contain firmware info
  59. * and tx descriptor info.
  60. */
  61. skb = dev_alloc_skb(frag_length);
  62. if (skb == NULL) {
  63. RT_TRACE(COMP_ERR, "(%s): unable to alloc skb buffer\n",
  64. __func__);
  65. goto cmdsend_downloadcode_fail;
  66. }
  67. memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
  68. tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
  69. tcb_desc->queue_index = TXCMD_QUEUE;
  70. tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
  71. tcb_desc->bLastIniPkt = bLastIniPkt;
  72. skb_reserve(skb, ExtraDescOffset);
  73. seg_ptr = (u8 *)skb_put(skb,
  74. (u32)(frag_length - ExtraDescOffset));
  75. memcpy(seg_ptr, code_virtual_address + frag_offset,
  76. (u32)(frag_length-ExtraDescOffset));
  77. tcb_desc->txbuf_size = frag_length;
  78. if (!priv->ieee80211->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
  79. (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index])) ||
  80. (priv->ieee80211->queue_stop)) {
  81. RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
  82. skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
  83. } else
  84. priv->ieee80211->softmac_hard_start_xmit(skb, dev);
  85. frag_offset += (frag_length - ExtraDescOffset);
  86. } while (frag_offset < buffer_len);
  87. return rt_status ;
  88. cmdsend_downloadcode_fail:
  89. rt_status = false;
  90. RT_TRACE(COMP_ERR, "(%s): failed\n", __func__);
  91. return rt_status;
  92. }
  93. bool FirmwareEnableCPU(struct net_device *dev)
  94. {
  95. bool rtStatus = true;
  96. u8 tmpU1b, CPUStatus = 0;
  97. u16 tmpU2b;
  98. u32 iCheckTime = 200;
  99. /* Enable CPU. */
  100. tmpU1b = read_nic_byte(dev, SYS_CLKR);
  101. /* AFE source */
  102. write_nic_byte(dev, SYS_CLKR, (tmpU1b|SYS_CPU_CLKSEL));
  103. tmpU2b = read_nic_word(dev, SYS_FUNC_EN);
  104. write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|FEN_CPUEN));
  105. /* Poll IMEM Ready after CPU has refilled. */
  106. do {
  107. CPUStatus = read_nic_byte(dev, TCR);
  108. if (CPUStatus & IMEM_RDY)
  109. /* success */
  110. break;
  111. udelay(100);
  112. } while (iCheckTime--);
  113. if (!(CPUStatus & IMEM_RDY)) {
  114. RT_TRACE(COMP_ERR, "%s(): failed to enable CPU", __func__);
  115. rtStatus = false;
  116. }
  117. return rtStatus;
  118. }
  119. FIRMWARE_8192S_STATUS
  120. FirmwareGetNextStatus(FIRMWARE_8192S_STATUS FWCurrentStatus)
  121. {
  122. FIRMWARE_8192S_STATUS NextFWStatus = 0;
  123. switch(FWCurrentStatus)
  124. {
  125. case FW_STATUS_INIT:
  126. NextFWStatus = FW_STATUS_LOAD_IMEM;
  127. break;
  128. case FW_STATUS_LOAD_IMEM:
  129. NextFWStatus = FW_STATUS_LOAD_EMEM;
  130. break;
  131. case FW_STATUS_LOAD_EMEM:
  132. NextFWStatus = FW_STATUS_LOAD_DMEM;
  133. break;
  134. case FW_STATUS_LOAD_DMEM:
  135. NextFWStatus = FW_STATUS_READY;
  136. break;
  137. default:
  138. RT_TRACE(COMP_ERR,"Invalid FW Status(%#x)!!\n", FWCurrentStatus);
  139. break;
  140. }
  141. return NextFWStatus;
  142. }
  143. bool FirmwareCheckReady(struct net_device *dev, u8 LoadFWStatus)
  144. {
  145. struct r8192_priv *priv = ieee80211_priv(dev);
  146. bool rtStatus = true;
  147. rt_firmware *pFirmware = priv->pFirmware;
  148. int PollingCnt = 1000;
  149. u8 CPUStatus = 0;
  150. u32 tmpU4b;
  151. pFirmware->FWStatus = (FIRMWARE_8192S_STATUS)LoadFWStatus;
  152. switch (LoadFWStatus) {
  153. case FW_STATUS_LOAD_IMEM:
  154. do { /* Polling IMEM code done. */
  155. CPUStatus = read_nic_byte(dev, TCR);
  156. if(CPUStatus& IMEM_CODE_DONE)
  157. break;
  158. udelay(5);
  159. } while (PollingCnt--);
  160. if (!(CPUStatus & IMEM_CHK_RPT) || PollingCnt <= 0) {
  161. RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\r\n", CPUStatus);
  162. goto FirmwareCheckReadyFail;
  163. }
  164. break;
  165. case FW_STATUS_LOAD_EMEM: /* Check Put Code OK and Turn On CPU */
  166. do { /* Polling EMEM code done. */
  167. CPUStatus = read_nic_byte(dev, TCR);
  168. if(CPUStatus& EMEM_CODE_DONE)
  169. break;
  170. udelay(5);
  171. } while (PollingCnt--);
  172. if (!(CPUStatus & EMEM_CHK_RPT)) {
  173. RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\r\n", CPUStatus);
  174. goto FirmwareCheckReadyFail;
  175. }
  176. /* Turn On CPU */
  177. if (FirmwareEnableCPU(dev) != true) {
  178. RT_TRACE(COMP_ERR, "%s(): failed to enable CPU",
  179. __func__);
  180. goto FirmwareCheckReadyFail;
  181. }
  182. break;
  183. case FW_STATUS_LOAD_DMEM:
  184. do { /* Polling DMEM code done */
  185. CPUStatus = read_nic_byte(dev, TCR);
  186. if(CPUStatus& DMEM_CODE_DONE)
  187. break;
  188. udelay(5);
  189. } while (PollingCnt--);
  190. if (!(CPUStatus & DMEM_CODE_DONE)) {
  191. RT_TRACE(COMP_ERR, "Polling DMEM code done fail ! CPUStatus(%#x)\n", CPUStatus);
  192. goto FirmwareCheckReadyFail;
  193. }
  194. RT_TRACE(COMP_FIRMWARE, "%s(): DMEM code download success, "
  195. "CPUStatus(%#x)",
  196. __func__, CPUStatus);
  197. PollingCnt = 10000; /* Set polling cycle to 10ms. */
  198. do { /* Polling Load Firmware ready */
  199. CPUStatus = read_nic_byte(dev, TCR);
  200. if(CPUStatus & FWRDY)
  201. break;
  202. udelay(100);
  203. } while (PollingCnt--);
  204. RT_TRACE(COMP_FIRMWARE, "%s(): polling load firmware ready, "
  205. "CPUStatus(%x)",
  206. __func__, CPUStatus);
  207. if ((CPUStatus & LOAD_FW_READY) != LOAD_FW_READY) {
  208. RT_TRACE(COMP_ERR, "Polling Load Firmware ready failed "
  209. "CPUStatus(%x)\n", CPUStatus);
  210. goto FirmwareCheckReadyFail;
  211. }
  212. /*
  213. * USB interface will update
  214. * reserved followings parameters later
  215. */
  216. //
  217. // <Roger_Notes> If right here, we can set TCR/RCR to desired value
  218. // and config MAC lookback mode to normal mode. 2008.08.28.
  219. //
  220. tmpU4b = read_nic_dword(dev,TCR);
  221. write_nic_dword(dev, TCR, (tmpU4b&(~TCR_ICV)));
  222. tmpU4b = read_nic_dword(dev, RCR);
  223. write_nic_dword(dev, RCR,
  224. (tmpU4b|RCR_APPFCS|RCR_APP_ICV|RCR_APP_MIC));
  225. RT_TRACE(COMP_FIRMWARE, "%s(): Current RCR settings(%#x)",
  226. __func__, tmpU4b);
  227. // Set to normal mode.
  228. write_nic_byte(dev, LBKMD_SEL, LBK_NORMAL);
  229. break;
  230. default:
  231. break;
  232. }
  233. RT_TRACE(COMP_FIRMWARE, "%s(): LoadFWStatus(%d), success",
  234. __func__, LoadFWStatus);
  235. return rtStatus;
  236. FirmwareCheckReadyFail:
  237. rtStatus = false;
  238. RT_TRACE(COMP_FIRMWARE, "%s(): LoadFWStatus(%d), failed",
  239. __func__, LoadFWStatus);
  240. return rtStatus;
  241. }
  242. //
  243. // Description: This routine is to update the RF types in FW header partially.
  244. //
  245. // Created by Roger, 2008.12.24.
  246. //
  247. u8 FirmwareHeaderMapRfType(struct net_device *dev)
  248. {
  249. struct r8192_priv *priv = ieee80211_priv(dev);
  250. switch(priv->rf_type)
  251. {
  252. case RF_1T1R: return 0x11;
  253. case RF_1T2R: return 0x12;
  254. case RF_2T2R: return 0x22;
  255. case RF_2T2R_GREEN: return 0x92;
  256. default:
  257. RT_TRACE(COMP_INIT, "Unknown RF type(%x)\n",priv->rf_type);
  258. break;
  259. }
  260. return 0x22;
  261. }
  262. //
  263. // Description: This routine is to update the private parts in FW header partially.
  264. //
  265. // Created by Roger, 2008.12.18.
  266. //
  267. void FirmwareHeaderPriveUpdate(struct net_device *dev, PRT_8192S_FIRMWARE_PRIV pFwPriv)
  268. {
  269. struct r8192_priv *priv = ieee80211_priv(dev);
  270. // Update USB endpoint number for RQPN settings.
  271. pFwPriv->usb_ep_num = priv->EEPROMUsbEndPointNumber; // endpoint number: 4, 6 and 11.
  272. RT_TRACE(COMP_INIT, "FirmwarePriveUpdate(): usb_ep_num(%#x)\n", pFwPriv->usb_ep_num);
  273. // Update RF types for RATR settings.
  274. pFwPriv->rf_config = FirmwareHeaderMapRfType(dev);
  275. }
  276. bool FirmwareRequest92S(struct net_device *dev, rt_firmware *pFirmware)
  277. {
  278. struct r8192_priv *priv = ieee80211_priv(dev);
  279. bool rtStatus = true;
  280. const char *pFwImageFileName[1] = {"RTL8192SU/rtl8192sfw.bin"};
  281. u8 *pucMappedFile = NULL;
  282. u32 ulInitStep = 0;
  283. u8 FwHdrSize = RT_8192S_FIRMWARE_HDR_SIZE;
  284. PRT_8192S_FIRMWARE_HDR pFwHdr = NULL;
  285. u32 file_length = 0;
  286. int rc;
  287. const struct firmware *fw_entry;
  288. rc = request_firmware(&fw_entry,
  289. pFwImageFileName[ulInitStep],
  290. &priv->udev->dev);
  291. if (rc < 0)
  292. goto RequestFirmware_Fail;
  293. if (fw_entry->size > sizeof(pFirmware->szFwTmpBuffer)) {
  294. RT_TRACE(COMP_ERR, "%s(): image file too large"
  295. "for container buffer", __func__);
  296. release_firmware(fw_entry);
  297. goto RequestFirmware_Fail;
  298. }
  299. memcpy(pFirmware->szFwTmpBuffer, fw_entry->data, fw_entry->size);
  300. pFirmware->szFwTmpBufferLen = fw_entry->size;
  301. release_firmware(fw_entry);
  302. pucMappedFile = pFirmware->szFwTmpBuffer;
  303. file_length = pFirmware->szFwTmpBufferLen;
  304. /* Retrieve FW header. */
  305. pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;
  306. pFwHdr = pFirmware->pFwHeader;
  307. RT_TRACE(COMP_FIRMWARE, "%s(): signature: %x, version: %x, "
  308. "size: %x, imemsize: %x, sram size: %x",
  309. __func__, pFwHdr->Signature, pFwHdr->Version,
  310. pFwHdr->DMEMSize, pFwHdr->IMG_IMEM_SIZE,
  311. pFwHdr->IMG_SRAM_SIZE);
  312. pFirmware->FirmwareVersion = byte(pFwHdr->Version , 0);
  313. if ((pFwHdr->IMG_IMEM_SIZE == 0) ||
  314. (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM))) {
  315. RT_TRACE(COMP_ERR, "%s(): memory for data image is less than"
  316. " IMEM requires", __func__);
  317. goto RequestFirmware_Fail;
  318. } else {
  319. pucMappedFile += FwHdrSize;
  320. /* Retrieve IMEM image. */
  321. memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
  322. pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;
  323. }
  324. if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM)) {
  325. RT_TRACE(COMP_ERR, "%s(): memory for data image is less than"
  326. " EMEM requires", __func__);
  327. goto RequestFirmware_Fail;
  328. } else {
  329. pucMappedFile += pFirmware->FwIMEMLen;
  330. /* Retriecve EMEM image */
  331. memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);
  332. pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
  333. }
  334. return rtStatus;
  335. RequestFirmware_Fail:
  336. RT_TRACE(COMP_ERR, "%s(): failed with TCR-Status: %x\n",
  337. __func__, read_nic_word(dev, TCR));
  338. rtStatus = false;
  339. return rtStatus;
  340. }
  341. bool FirmwareDownload92S(struct net_device *dev)
  342. {
  343. struct r8192_priv *priv = ieee80211_priv(dev);
  344. bool rtStatus = true;
  345. u8 *pucMappedFile = NULL;
  346. u32 ulFileLength;
  347. u8 FwHdrSize = RT_8192S_FIRMWARE_HDR_SIZE;
  348. rt_firmware *pFirmware = priv->pFirmware;
  349. u8 FwStatus = FW_STATUS_INIT;
  350. PRT_8192S_FIRMWARE_HDR pFwHdr = NULL;
  351. PRT_8192S_FIRMWARE_PRIV pFwPriv = NULL;
  352. pFirmware->FWStatus = FW_STATUS_INIT;
  353. /*
  354. * Load the firmware from RTL8192SU/rtl8192sfw.bin if necessary
  355. */
  356. if (pFirmware->szFwTmpBufferLen == 0) {
  357. if (FirmwareRequest92S(dev, pFirmware) != true)
  358. goto DownloadFirmware_Fail;
  359. }
  360. FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
  361. while (FwStatus != FW_STATUS_READY) {
  362. /* Image buffer redirection. */
  363. switch (FwStatus) {
  364. case FW_STATUS_LOAD_IMEM:
  365. pucMappedFile = pFirmware->FwIMEM;
  366. ulFileLength = pFirmware->FwIMEMLen;
  367. break;
  368. case FW_STATUS_LOAD_EMEM:
  369. pucMappedFile = pFirmware->FwEMEM;
  370. ulFileLength = pFirmware->FwEMEMLen;
  371. break;
  372. case FW_STATUS_LOAD_DMEM:
  373. /* Partial update the content of private header */
  374. pFwHdr = pFirmware->pFwHeader;
  375. pFwPriv = (PRT_8192S_FIRMWARE_PRIV)&pFwHdr->FWPriv;
  376. FirmwareHeaderPriveUpdate(dev, pFwPriv);
  377. pucMappedFile = (u8 *)(pFirmware->pFwHeader) +
  378. RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
  379. ulFileLength = FwHdrSize -
  380. RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
  381. break;
  382. default:
  383. RT_TRACE(COMP_ERR, "Unexpected Download step!!\n");
  384. goto DownloadFirmware_Fail;
  385. break;
  386. }
  387. /* <2> Download image file */
  388. rtStatus = FirmwareDownloadCode(dev,
  389. pucMappedFile,
  390. ulFileLength);
  391. if(rtStatus != true)
  392. goto DownloadFirmware_Fail;
  393. /* <3> Check whether load FW process is ready */
  394. rtStatus = FirmwareCheckReady(dev, FwStatus);
  395. if(rtStatus != true)
  396. goto DownloadFirmware_Fail;
  397. FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
  398. }
  399. RT_TRACE(COMP_FIRMWARE, "%s(): Firmware Download Success", __func__);
  400. return rtStatus;
  401. DownloadFirmware_Fail:
  402. RT_TRACE(COMP_ERR, "%s(): failed with TCR-Status: %x\n",
  403. __func__, read_nic_word(dev, TCR));
  404. rtStatus = false;
  405. return rtStatus;
  406. }
  407. MODULE_FIRMWARE("RTL8192SU/rtl8192sfw.bin");