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
16 #include <drv_types.h>
17
18 #ifdef CONFIG_IOL
rtw_IOL_accquire_xmit_frame(ADAPTER * adapter)19 struct xmit_frame *rtw_IOL_accquire_xmit_frame(ADAPTER *adapter)
20 {
21 struct xmit_frame *xmit_frame;
22 struct xmit_buf *xmitbuf;
23 struct pkt_attrib *pattrib;
24 struct xmit_priv *pxmitpriv = &(adapter->xmitpriv);
25
26 #if 1
27 xmit_frame = rtw_alloc_xmitframe(pxmitpriv, 0);
28 if (xmit_frame == NULL) {
29 RTW_INFO("%s rtw_alloc_xmitframe return null\n", __FUNCTION__);
30 goto exit;
31 }
32
33 xmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
34 if (xmitbuf == NULL) {
35 RTW_INFO("%s rtw_alloc_xmitbuf return null\n", __FUNCTION__);
36 rtw_free_xmitframe(pxmitpriv, xmit_frame);
37 xmit_frame = NULL;
38 goto exit;
39 }
40
41 xmit_frame->frame_tag = MGNT_FRAMETAG;
42 xmit_frame->pxmitbuf = xmitbuf;
43 xmit_frame->buf_addr = xmitbuf->pbuf;
44 xmitbuf->priv_data = xmit_frame;
45
46 pattrib = &xmit_frame->attrib;
47 update_mgntframe_attrib(adapter, pattrib);
48 pattrib->qsel = QSLT_BEACON;/* Beacon */
49 pattrib->subtype = WIFI_BEACON;
50 pattrib->pktlen = pattrib->last_txcmdsz = 0;
51
52 #else
53 xmit_frame = alloc_mgtxmitframe(pxmitpriv);
54 if (xmit_frame == NULL)
55 RTW_INFO("%s alloc_mgtxmitframe return null\n", __FUNCTION__);
56 else {
57 pattrib = &xmit_frame->attrib;
58 update_mgntframe_attrib(adapter, pattrib);
59 pattrib->qsel = QSLT_BEACON;
60 pattrib->pktlen = pattrib->last_txcmdsz = 0;
61 }
62 #endif
63
64 exit:
65 return xmit_frame;
66 }
67
68
rtw_IOL_append_cmds(struct xmit_frame * xmit_frame,u8 * IOL_cmds,u32 cmd_len)69 int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds, u32 cmd_len)
70 {
71 struct pkt_attrib *pattrib = &xmit_frame->attrib;
72 u16 buf_offset;
73 u32 ori_len;
74
75 buf_offset = TXDESC_OFFSET;
76 ori_len = buf_offset + pattrib->pktlen;
77
78 /* check if the io_buf can accommodate new cmds */
79 if (ori_len + cmd_len + 8 > MAX_XMITBUF_SZ) {
80 RTW_INFO("%s %u is large than MAX_XMITBUF_SZ:%u, can't accommodate new cmds\n", __FUNCTION__
81 , ori_len + cmd_len + 8, MAX_XMITBUF_SZ);
82 return _FAIL;
83 }
84
85 _rtw_memcpy(xmit_frame->buf_addr + buf_offset + pattrib->pktlen, IOL_cmds, cmd_len);
86 pattrib->pktlen += cmd_len;
87 pattrib->last_txcmdsz += cmd_len;
88
89 /* RTW_INFO("%s ori:%u + cmd_len:%u = %u\n", __FUNCTION__, ori_len, cmd_len, buf_offset+pattrib->pktlen); */
90
91 return _SUCCESS;
92 }
93
rtw_IOL_applied(ADAPTER * adapter)94 bool rtw_IOL_applied(ADAPTER *adapter)
95 {
96 if (1 == adapter->registrypriv.fw_iol)
97 return _TRUE;
98
99 #ifdef CONFIG_USB_HCI
100 if ((2 == adapter->registrypriv.fw_iol) && (IS_FULL_SPEED_USB(adapter)))
101 return _TRUE;
102 #endif
103
104 return _FALSE;
105 }
106
rtw_IOL_exec_cmds_sync(ADAPTER * adapter,struct xmit_frame * xmit_frame,u32 max_wating_ms,u32 bndy_cnt)107 int rtw_IOL_exec_cmds_sync(ADAPTER *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt)
108 {
109 return rtw_hal_iol_cmd(adapter, xmit_frame, max_wating_ms, bndy_cnt);
110 }
111
112 #ifdef CONFIG_IOL_NEW_GENERATION
rtw_IOL_append_LLT_cmd(struct xmit_frame * xmit_frame,u8 page_boundary)113 int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary)
114 {
115 return _SUCCESS;
116 }
_rtw_IOL_append_WB_cmd(struct xmit_frame * xmit_frame,u16 addr,u8 value,u8 mask)117 int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, u8 mask)
118 {
119 struct ioreg_cfg cmd = {8, IOREG_CMD_WB_REG, 0x0, 0x0, 0x0};
120
121 /* RTW_PUT_LE16((u8*)&cmd.address, addr); */
122 /* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
123 cmd.address = cpu_to_le16(addr);
124 cmd.data = cpu_to_le32(value);
125
126 if (mask != 0xFF) {
127 cmd.length = 12;
128 /* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
129 cmd.mask = cpu_to_le32(mask);
130 }
131
132 /* RTW_INFO("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FUNCTION__, addr,value,mask); */
133
134 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
135
136 }
_rtw_IOL_append_WW_cmd(struct xmit_frame * xmit_frame,u16 addr,u16 value,u16 mask)137 int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, u16 mask)
138 {
139 struct ioreg_cfg cmd = {8, IOREG_CMD_WW_REG, 0x0, 0x0, 0x0};
140
141 /* RTW_PUT_LE16((u8*)&cmd.address, addr); */
142 /* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
143 cmd.address = cpu_to_le16(addr);
144 cmd.data = cpu_to_le32(value);
145
146 if (mask != 0xFFFF) {
147 cmd.length = 12;
148 /* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
149 cmd.mask = cpu_to_le32(mask);
150 }
151
152 /* RTW_INFO("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FUNCTION__, addr,value,mask); */
153
154 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
155
156 }
_rtw_IOL_append_WD_cmd(struct xmit_frame * xmit_frame,u16 addr,u32 value,u32 mask)157 int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, u32 mask)
158 {
159 struct ioreg_cfg cmd = {8, IOREG_CMD_WD_REG, 0x0, 0x0, 0x0};
160
161 /* RTW_PUT_LE16((u8*)&cmd.address, addr); */
162 /* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
163 cmd.address = cpu_to_le16(addr);
164 cmd.data = cpu_to_le32(value);
165
166 if (mask != 0xFFFFFFFF) {
167 cmd.length = 12;
168 /* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
169 cmd.mask = cpu_to_le32(mask);
170 }
171
172 /* RTW_INFO("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FU2NCTION__, addr,value,mask); */
173
174 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
175
176 }
177
_rtw_IOL_append_WRF_cmd(struct xmit_frame * xmit_frame,u8 rf_path,u16 addr,u32 value,u32 mask)178 int _rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path, u16 addr, u32 value, u32 mask)
179 {
180 struct ioreg_cfg cmd = {8, IOREG_CMD_W_RF, 0x0, 0x0, 0x0};
181
182 /* RTW_PUT_LE16((u8*)&cmd.address, addr); */
183 /* RTW_PUT_LE32((u8*)&cmd.value, (u32)value); */
184 cmd.address = (rf_path << 8) | ((addr) & 0xFF);
185 cmd.data = cpu_to_le32(value);
186
187 if (mask != 0x000FFFFF) {
188 cmd.length = 12;
189 /* RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask); */
190 cmd.mask = cpu_to_le32(mask);
191 }
192
193 /* RTW_INFO("%s rf_path:0x%02x addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FU2NCTION__,rf_path, addr,value,mask); */
194
195 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
196
197 }
198
199
200
rtw_IOL_append_DELAY_US_cmd(struct xmit_frame * xmit_frame,u16 us)201 int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
202 {
203 struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
204 /* RTW_PUT_LE16((u8*)&cmd.address, us); */
205 cmd.address = cpu_to_le16(us);
206
207 /* RTW_INFO("%s %u\n", __FUNCTION__, us); */
208 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
209 }
210
rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame * xmit_frame,u16 ms)211 int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
212 {
213 struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
214
215 /* RTW_PUT_LE16((u8*)&cmd.address, ms); */
216 cmd.address = cpu_to_le16(ms);
217
218 /* RTW_INFO("%s %u\n", __FUNCTION__, ms); */
219 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
220 }
rtw_IOL_append_END_cmd(struct xmit_frame * xmit_frame)221 int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
222 {
223 struct ioreg_cfg cmd = {4, IOREG_CMD_END, 0xFFFF, 0xFF, 0x0};
224 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
225
226 }
227
rtw_IOL_cmd_boundary_handle(struct xmit_frame * pxmit_frame)228 u8 rtw_IOL_cmd_boundary_handle(struct xmit_frame *pxmit_frame)
229 {
230 u8 is_cmd_bndy = _FALSE;
231 if (((pxmit_frame->attrib.pktlen + 32) % 256) + 8 >= 256) {
232 rtw_IOL_append_END_cmd(pxmit_frame);
233 pxmit_frame->attrib.pktlen = ((((pxmit_frame->attrib.pktlen + 32) / 256) + 1) * 256);
234
235 /* printk("==> %s, pktlen(%d)\n",__FUNCTION__,pxmit_frame->attrib.pktlen); */
236 pxmit_frame->attrib.last_txcmdsz = pxmit_frame->attrib.pktlen;
237 is_cmd_bndy = _TRUE;
238 }
239 return is_cmd_bndy;
240 }
241
rtw_IOL_cmd_buf_dump(ADAPTER * Adapter,int buf_len,u8 * pbuf)242 void rtw_IOL_cmd_buf_dump(ADAPTER *Adapter, int buf_len, u8 *pbuf)
243 {
244 int i;
245 int j = 1;
246
247 printk("###### %s ######\n", __FUNCTION__);
248 for (i = 0; i < buf_len; i++) {
249 printk("%02x-", *(pbuf + i));
250
251 if (j % 32 == 0)
252 printk("\n");
253 j++;
254 }
255 printk("\n");
256 printk("============= ioreg_cmd len = %d ===============\n", buf_len);
257 }
258
259
260 #else /* CONFIG_IOL_NEW_GENERATION */
rtw_IOL_append_LLT_cmd(struct xmit_frame * xmit_frame,u8 page_boundary)261 int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary)
262 {
263 IOL_CMD cmd = {0x0, IOL_CMD_LLT, 0x0, 0x0};
264
265 RTW_PUT_BE32((u8 *)&cmd.value, (u32)page_boundary);
266
267 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
268 }
269
_rtw_IOL_append_WB_cmd(struct xmit_frame * xmit_frame,u16 addr,u8 value)270 int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value)
271 {
272 IOL_CMD cmd = {0x0, IOL_CMD_WB_REG, 0x0, 0x0};
273
274 RTW_PUT_BE16((u8 *)&cmd.address, (u16)addr);
275 RTW_PUT_BE32((u8 *)&cmd.value, (u32)value);
276
277 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
278 }
279
_rtw_IOL_append_WW_cmd(struct xmit_frame * xmit_frame,u16 addr,u16 value)280 int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value)
281 {
282 IOL_CMD cmd = {0x0, IOL_CMD_WW_REG, 0x0, 0x0};
283
284 RTW_PUT_BE16((u8 *)&cmd.address, (u16)addr);
285 RTW_PUT_BE32((u8 *)&cmd.value, (u32)value);
286
287 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
288 }
289
_rtw_IOL_append_WD_cmd(struct xmit_frame * xmit_frame,u16 addr,u32 value)290 int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value)
291 {
292 IOL_CMD cmd = {0x0, IOL_CMD_WD_REG, 0x0, 0x0};
293 u8 *pos = (u8 *)&cmd;
294
295 RTW_PUT_BE16((u8 *)&cmd.address, (u16)addr);
296 RTW_PUT_BE32((u8 *)&cmd.value, (u32)value);
297
298 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
299 }
300
301 #ifdef DBG_IO
dbg_rtw_IOL_append_WB_cmd(struct xmit_frame * xmit_frame,u16 addr,u8 value,const char * caller,const int line)302 int dbg_rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, const char *caller, const int line)
303 {
304 if (match_write_sniff(xmit_frame->padapter, addr, 1, value)) {
305 RTW_INFO("DBG_IO %s:%d IOL_WB(0x%04x, 0x%02x)\n"
306 , caller, line, addr, value);
307 }
308
309 return _rtw_IOL_append_WB_cmd(xmit_frame, addr, value);
310 }
311
dbg_rtw_IOL_append_WW_cmd(struct xmit_frame * xmit_frame,u16 addr,u16 value,const char * caller,const int line)312 int dbg_rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, const char *caller, const int line)
313 {
314 if (match_write_sniff(xmit_frame->padapter, addr, 2, value)) {
315 RTW_INFO("DBG_IO %s:%d IOL_WW(0x%04x, 0x%04x)\n"
316 , caller, line, addr, value);
317 }
318
319 return _rtw_IOL_append_WW_cmd(xmit_frame, addr, value);
320 }
321
dbg_rtw_IOL_append_WD_cmd(struct xmit_frame * xmit_frame,u16 addr,u32 value,const char * caller,const int line)322 int dbg_rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, const char *caller, const int line)
323 {
324 if (match_write_sniff(xmit_frame->padapter, addr, 4, value)) {
325 RTW_INFO("DBG_IO %s:%d IOL_WD(0x%04x, 0x%08x)\n"
326 , caller, line, addr, value);
327 }
328
329 return _rtw_IOL_append_WD_cmd(xmit_frame, addr, value);
330 }
331 #endif
332
rtw_IOL_append_DELAY_US_cmd(struct xmit_frame * xmit_frame,u16 us)333 int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
334 {
335 IOL_CMD cmd = {0x0, IOL_CMD_DELAY_US, 0x0, 0x0};
336
337 RTW_PUT_BE32((u8 *)&cmd.value, (u32)us);
338
339 /* RTW_INFO("%s %u\n", __FUNCTION__, us); */
340
341 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
342 }
343
rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame * xmit_frame,u16 ms)344 int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
345 {
346 IOL_CMD cmd = {0x0, IOL_CMD_DELAY_MS, 0x0, 0x0};
347
348 RTW_PUT_BE32((u8 *)&cmd.value, (u32)ms);
349
350 /* RTW_INFO("%s %u\n", __FUNCTION__, ms); */
351
352 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 8);
353 }
354
rtw_IOL_append_END_cmd(struct xmit_frame * xmit_frame)355 int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
356 {
357 IOL_CMD end_cmd = {0x0, IOL_CMD_END, 0x0, 0x0};
358
359
360 return rtw_IOL_append_cmds(xmit_frame, (u8 *)&end_cmd, 8);
361
362 }
363
rtw_IOL_exec_cmd_array_sync(PADAPTER adapter,u8 * IOL_cmds,u32 cmd_num,u32 max_wating_ms)364 int rtw_IOL_exec_cmd_array_sync(PADAPTER adapter, u8 *IOL_cmds, u32 cmd_num, u32 max_wating_ms)
365 {
366 struct xmit_frame *xmit_frame;
367
368 xmit_frame = rtw_IOL_accquire_xmit_frame(adapter);
369 if (xmit_frame == NULL)
370 return _FAIL;
371
372 if (rtw_IOL_append_cmds(xmit_frame, IOL_cmds, cmd_num << 3) == _FAIL)
373 return _FAIL;
374
375 return rtw_IOL_exec_cmds_sync(adapter, xmit_frame, max_wating_ms, 0);
376 }
377
rtw_IOL_exec_empty_cmds_sync(ADAPTER * adapter,u32 max_wating_ms)378 int rtw_IOL_exec_empty_cmds_sync(ADAPTER *adapter, u32 max_wating_ms)
379 {
380 IOL_CMD end_cmd = {0x0, IOL_CMD_END, 0x0, 0x0};
381 return rtw_IOL_exec_cmd_array_sync(adapter, (u8 *)&end_cmd, 1, max_wating_ms);
382 }
383 #endif /* CONFIG_IOL_NEW_GENERATION */
384
385
386
387
388 #endif /* CONFIG_IOL */
389