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