rtw_iol.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2017 Realtek Corporation.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. *****************************************************************************/
  15. #include <drv_types.h>
  16. #ifdef CONFIG_IOL
  17. struct xmit_frame *rtw_IOL_accquire_xmit_frame(ADAPTER *adapter)
  18. {
  19. struct xmit_frame *xmit_frame;
  20. struct xmit_buf *xmitbuf;
  21. struct pkt_attrib *pattrib;
  22. struct xmit_priv *pxmitpriv = &(adapter->xmitpriv);
  23. #if 1
  24. xmit_frame = rtw_alloc_xmitframe(pxmitpriv);
  25. if (xmit_frame == NULL) {
  26. RTW_INFO("%s rtw_alloc_xmitframe return null\n", __FUNCTION__);
  27. goto exit;
  28. }
  29. xmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
  30. if (xmitbuf == NULL) {
  31. RTW_INFO("%s rtw_alloc_xmitbuf return null\n", __FUNCTION__);
  32. rtw_free_xmitframe(pxmitpriv, xmit_frame);
  33. xmit_frame = NULL;
  34. goto exit;
  35. }
  36. xmit_frame->frame_tag = MGNT_FRAMETAG;
  37. xmit_frame->pxmitbuf = xmitbuf;
  38. xmit_frame->buf_addr = xmitbuf->pbuf;
  39. xmitbuf->priv_data = xmit_frame;
  40. pattrib = &xmit_frame->attrib;
  41. update_mgntframe_attrib(adapter, pattrib);
  42. pattrib->qsel = QSLT_BEACON;/* Beacon */
  43. pattrib->subtype = WIFI_BEACON;
  44. pattrib->pktlen = pattrib->last_txcmdsz = 0;
  45. #else
  46. xmit_frame = alloc_mgtxmitframe(pxmitpriv);
  47. if (xmit_frame == NULL)
  48. RTW_INFO("%s alloc_mgtxmitframe return null\n", __FUNCTION__);
  49. else {
  50. pattrib = &xmit_frame->attrib;
  51. update_mgntframe_attrib(adapter, pattrib);
  52. pattrib->qsel = QSLT_BEACON;
  53. pattrib->pktlen = pattrib->last_txcmdsz = 0;
  54. }
  55. #endif
  56. exit:
  57. return xmit_frame;
  58. }
  59. int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds, u32 cmd_len)
  60. {
  61. struct pkt_attrib *pattrib = &xmit_frame->attrib;
  62. u16 buf_offset;
  63. u32 ori_len;
  64. buf_offset = TXDESC_OFFSET;
  65. ori_len = buf_offset + pattrib->pktlen;
  66. /* check if the io_buf can accommodate new cmds */
  67. if (ori_len + cmd_len + 8 > MAX_XMITBUF_SZ) {
  68. RTW_INFO("%s %u is large than MAX_XMITBUF_SZ:%u, can't accommodate new cmds\n", __FUNCTION__
  69. , ori_len + cmd_len + 8, MAX_XMITBUF_SZ);
  70. return _FAIL;
  71. }
  72. _rtw_memcpy(xmit_frame->buf_addr + buf_offset + pattrib->pktlen, IOL_cmds, cmd_len);
  73. pattrib->pktlen += cmd_len;
  74. pattrib->last_txcmdsz += cmd_len;
  75. /* RTW_INFO("%s ori:%u + cmd_len:%u = %u\n", __FUNCTION__, ori_len, cmd_len, buf_offset+pattrib->pktlen); */
  76. return _SUCCESS;
  77. }
  78. bool rtw_IOL_applied(ADAPTER *adapter)
  79. {
  80. if (1 == adapter->registrypriv.fw_iol)
  81. return _TRUE;
  82. #ifdef CONFIG_USB_HCI
  83. if ((2 == adapter->registrypriv.fw_iol) && (IS_FULL_SPEED_USB(adapter)))
  84. return _TRUE;
  85. #endif
  86. return _FALSE;
  87. }
  88. int rtw_IOL_exec_cmds_sync(ADAPTER *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt)
  89. {
  90. return rtw_hal_iol_cmd(adapter, xmit_frame, max_wating_ms, bndy_cnt);
  91. }
  92. #ifdef CONFIG_IOL_NEW_GENERATION
  93. int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary)
  94. {
  95. return _SUCCESS;
  96. }
  97. int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, u8 mask)
  98. {
  99. struct ioreg_cfg cmd = {8, IOREG_CMD_WB_REG, 0x0, 0x0, 0x0};
  100. /* RTW_PUT_LE16((u8*)&cmd.address, addr); */
  101. /* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
  102. cmd.address = cpu_to_le16(addr);
  103. cmd.data = cpu_to_le32(value);
  104. if (mask != 0xFF) {
  105. cmd.length = 12;
  106. /* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
  107. cmd.mask = cpu_to_le32(mask);
  108. }
  109. /* RTW_INFO("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FUNCTION__, addr,value,mask); */
  110. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
  111. }
  112. int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, u16 mask)
  113. {
  114. struct ioreg_cfg cmd = {8, IOREG_CMD_WW_REG, 0x0, 0x0, 0x0};
  115. /* RTW_PUT_LE16((u8*)&cmd.address, addr); */
  116. /* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
  117. cmd.address = cpu_to_le16(addr);
  118. cmd.data = cpu_to_le32(value);
  119. if (mask != 0xFFFF) {
  120. cmd.length = 12;
  121. /* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
  122. cmd.mask = cpu_to_le32(mask);
  123. }
  124. /* RTW_INFO("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FUNCTION__, addr,value,mask); */
  125. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
  126. }
  127. int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, u32 mask)
  128. {
  129. struct ioreg_cfg cmd = {8, IOREG_CMD_WD_REG, 0x0, 0x0, 0x0};
  130. /* RTW_PUT_LE16((u8*)&cmd.address, addr); */
  131. /* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
  132. cmd.address = cpu_to_le16(addr);
  133. cmd.data = cpu_to_le32(value);
  134. if (mask != 0xFFFFFFFF) {
  135. cmd.length = 12;
  136. /* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
  137. cmd.mask = cpu_to_le32(mask);
  138. }
  139. /* RTW_INFO("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FU2NCTION__, addr,value,mask); */
  140. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
  141. }
  142. int _rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path, u16 addr, u32 value, u32 mask)
  143. {
  144. struct ioreg_cfg cmd = {8, IOREG_CMD_W_RF, 0x0, 0x0, 0x0};
  145. /* RTW_PUT_LE16((u8*)&cmd.address, addr); */
  146. /* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
  147. cmd.address = (rf_path << 8) | ((addr) & 0xFF);
  148. cmd.data = cpu_to_le32(value);
  149. if (mask != 0x000FFFFF) {
  150. cmd.length = 12;
  151. /* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
  152. cmd.mask = cpu_to_le32(mask);
  153. }
  154. /* RTW_INFO("%s rf_path:0x%02x addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FU2NCTION__,rf_path, addr,value,mask); */
  155. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
  156. }
  157. int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
  158. {
  159. struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
  160. /* RTW_PUT_LE16((u8*)&cmd.address, us); */
  161. cmd.address = cpu_to_le16(us);
  162. /* RTW_INFO("%s %u\n", __FUNCTION__, us); */
  163. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
  164. }
  165. int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
  166. {
  167. struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
  168. /* RTW_PUT_LE16((u8*)&cmd.address, ms); */
  169. cmd.address = cpu_to_le16(ms);
  170. /* RTW_INFO("%s %u\n", __FUNCTION__, ms); */
  171. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
  172. }
  173. int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
  174. {
  175. struct ioreg_cfg cmd = {4, IOREG_CMD_END, 0xFFFF, 0xFF, 0x0};
  176. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
  177. }
  178. u8 rtw_IOL_cmd_boundary_handle(struct xmit_frame *pxmit_frame)
  179. {
  180. u8 is_cmd_bndy = _FALSE;
  181. if (((pxmit_frame->attrib.pktlen + 32) % 256) + 8 >= 256) {
  182. rtw_IOL_append_END_cmd(pxmit_frame);
  183. pxmit_frame->attrib.pktlen = ((((pxmit_frame->attrib.pktlen + 32) / 256) + 1) * 256);
  184. /* printk("==> %s, pktlen(%d)\n",__FUNCTION__,pxmit_frame->attrib.pktlen); */
  185. pxmit_frame->attrib.last_txcmdsz = pxmit_frame->attrib.pktlen;
  186. is_cmd_bndy = _TRUE;
  187. }
  188. return is_cmd_bndy;
  189. }
  190. void rtw_IOL_cmd_buf_dump(ADAPTER *Adapter, int buf_len, u8 *pbuf)
  191. {
  192. int i;
  193. int j = 1;
  194. printk("###### %s ######\n", __FUNCTION__);
  195. for (i = 0; i < buf_len; i++) {
  196. printk("%02x-", *(pbuf + i));
  197. if (j % 32 == 0)
  198. printk("\n");
  199. j++;
  200. }
  201. printk("\n");
  202. printk("============= ioreg_cmd len = %d ===============\n", buf_len);
  203. }
  204. #else /* CONFIG_IOL_NEW_GENERATION */
  205. int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary)
  206. {
  207. IOL_CMD cmd = {0x0, IOL_CMD_LLT, 0x0, 0x0};
  208. RTW_PUT_BE32((u8 *)&cmd.value, (u32)page_boundary);
  209. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
  210. }
  211. int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value)
  212. {
  213. IOL_CMD cmd = {0x0, IOL_CMD_WB_REG, 0x0, 0x0};
  214. RTW_PUT_BE16((u8 *)&cmd.address, (u16)addr);
  215. RTW_PUT_BE32((u8 *)&cmd.value, (u32)value);
  216. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
  217. }
  218. int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value)
  219. {
  220. IOL_CMD cmd = {0x0, IOL_CMD_WW_REG, 0x0, 0x0};
  221. RTW_PUT_BE16((u8 *)&cmd.address, (u16)addr);
  222. RTW_PUT_BE32((u8 *)&cmd.value, (u32)value);
  223. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
  224. }
  225. int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value)
  226. {
  227. IOL_CMD cmd = {0x0, IOL_CMD_WD_REG, 0x0, 0x0};
  228. u8 *pos = (u8 *)&cmd;
  229. RTW_PUT_BE16((u8 *)&cmd.address, (u16)addr);
  230. RTW_PUT_BE32((u8 *)&cmd.value, (u32)value);
  231. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
  232. }
  233. #ifdef DBG_IO
  234. int dbg_rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, const char *caller, const int line)
  235. {
  236. const struct rtw_io_sniff_ent *ent = match_write_sniff(xmit_frame->padapter, addr, 1, value);
  237. if (ent) {
  238. RTW_INFO("DBG_IO %s:%d IOL_WB(0x%04x, 0x%02x) %s\n"
  239. , caller, line, addr, value, rtw_io_sniff_ent_get_tag(ent));
  240. }
  241. return _rtw_IOL_append_WB_cmd(xmit_frame, addr, value);
  242. }
  243. int dbg_rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, const char *caller, const int line)
  244. {
  245. const struct rtw_io_sniff_ent *ent = match_write_sniff(xmit_frame->padapter, addr, 2, value);
  246. if (ent) {
  247. RTW_INFO("DBG_IO %s:%d IOL_WW(0x%04x, 0x%04x) %s\n"
  248. , caller, line, addr, value, rtw_io_sniff_ent_get_tag(ent));
  249. }
  250. return _rtw_IOL_append_WW_cmd(xmit_frame, addr, value);
  251. }
  252. int dbg_rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, const char *caller, const int line)
  253. {
  254. const struct rtw_io_sniff_ent *ent = match_write_sniff(xmit_frame->padapter, addr, 4, value);
  255. if (ent) {
  256. RTW_INFO("DBG_IO %s:%d IOL_WD(0x%04x, 0x%08x) %s\n"
  257. , caller, line, addr, value, rtw_io_sniff_ent_get_tag(ent));
  258. }
  259. return _rtw_IOL_append_WD_cmd(xmit_frame, addr, value);
  260. }
  261. #endif
  262. int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
  263. {
  264. IOL_CMD cmd = {0x0, IOL_CMD_DELAY_US, 0x0, 0x0};
  265. RTW_PUT_BE32((u8 *)&cmd.value, (u32)us);
  266. /* RTW_INFO("%s %u\n", __FUNCTION__, us); */
  267. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
  268. }
  269. int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
  270. {
  271. IOL_CMD cmd = {0x0, IOL_CMD_DELAY_MS, 0x0, 0x0};
  272. RTW_PUT_BE32((u8 *)&cmd.value, (u32)ms);
  273. /* RTW_INFO("%s %u\n", __FUNCTION__, ms); */
  274. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
  275. }
  276. int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
  277. {
  278. IOL_CMD end_cmd = {0x0, IOL_CMD_END, 0x0, 0x0};
  279. return rtw_IOL_append_cmds(xmit_frame, (u8 *)&end_cmd, 8);
  280. }
  281. int rtw_IOL_exec_cmd_array_sync(PADAPTER adapter, u8 *IOL_cmds, u32 cmd_num, u32 max_wating_ms)
  282. {
  283. struct xmit_frame *xmit_frame;
  284. xmit_frame = rtw_IOL_accquire_xmit_frame(adapter);
  285. if (xmit_frame == NULL)
  286. return _FAIL;
  287. if (rtw_IOL_append_cmds(xmit_frame, IOL_cmds, cmd_num << 3) == _FAIL)
  288. return _FAIL;
  289. return rtw_IOL_exec_cmds_sync(adapter, xmit_frame, max_wating_ms, 0);
  290. }
  291. int rtw_IOL_exec_empty_cmds_sync(ADAPTER *adapter, u32 max_wating_ms)
  292. {
  293. IOL_CMD end_cmd = {0x0, IOL_CMD_END, 0x0, 0x0};
  294. return rtw_IOL_exec_cmd_array_sync(adapter, (u8 *)&end_cmd, 1, max_wating_ms);
  295. }
  296. #endif /* CONFIG_IOL_NEW_GENERATION */
  297. #endif /* CONFIG_IOL */