1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2011 Realtek Corporation. */
3 
4 #include "../include/rtw_iol.h"
5 
rtw_IOL_accquire_xmit_frame(struct adapter * adapter)6 struct xmit_frame	*rtw_IOL_accquire_xmit_frame(struct adapter  *adapter)
7 {
8 	struct xmit_frame	*xmit_frame;
9 	struct xmit_buf	*xmitbuf;
10 	struct pkt_attrib	*pattrib;
11 	struct xmit_priv	*pxmitpriv = &adapter->xmitpriv;
12 
13 	xmit_frame = rtw_alloc_xmitframe(pxmitpriv);
14 	if (!xmit_frame) {
15 		DBG_88E("%s rtw_alloc_xmitframe return null\n", __func__);
16 		return NULL;
17 	}
18 
19 	xmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
20 	if (!xmitbuf) {
21 		DBG_88E("%s rtw_alloc_xmitbuf return null\n", __func__);
22 		rtw_free_xmitframe(pxmitpriv, xmit_frame);
23 		return NULL;
24 	}
25 
26 	xmit_frame->frame_tag = MGNT_FRAMETAG;
27 	xmit_frame->pxmitbuf = xmitbuf;
28 	xmit_frame->buf_addr = xmitbuf->pbuf;
29 	xmitbuf->priv_data = xmit_frame;
30 
31 	pattrib = &xmit_frame->attrib;
32 	update_mgntframe_attrib(adapter, pattrib);
33 	pattrib->qsel = 0x10;/* Beacon */
34 	pattrib->subtype = WIFI_BEACON;
35 	pattrib->pktlen = 0;
36 	pattrib->last_txcmdsz = 0;
37 
38 	return xmit_frame;
39 }
40 
rtw_IOL_append_cmds(struct xmit_frame * xmit_frame,u8 * IOL_cmds,u32 cmd_len)41 int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds, u32 cmd_len)
42 {
43 	struct pkt_attrib	*pattrib = &xmit_frame->attrib;
44 	u16 buf_offset;
45 	u32 ori_len;
46 
47 	buf_offset = TXDESC_OFFSET;
48 	ori_len = buf_offset + pattrib->pktlen;
49 
50 	/* check if the io_buf can accommodate new cmds */
51 	if (ori_len + cmd_len + 8 > MAX_XMITBUF_SZ) {
52 		DBG_88E("%s %u is large than MAX_XMITBUF_SZ:%u, can't accommodate new cmds\n",
53 			__func__, ori_len + cmd_len + 8, MAX_XMITBUF_SZ);
54 		return _FAIL;
55 	}
56 
57 	memcpy(xmit_frame->buf_addr + buf_offset + pattrib->pktlen, IOL_cmds, cmd_len);
58 	pattrib->pktlen += cmd_len;
59 	pattrib->last_txcmdsz += cmd_len;
60 
61 	return _SUCCESS;
62 }
63 
rtw_IOL_applied(struct adapter * adapter)64 bool rtw_IOL_applied(struct adapter  *adapter)
65 {
66 	if (1 == adapter->registrypriv.fw_iol)
67 		return true;
68 
69 	if ((2 == adapter->registrypriv.fw_iol) && (!adapter_to_dvobj(adapter)->ishighspeed))
70 		return true;
71 	return false;
72 }
73 
_rtw_IOL_append_WB_cmd(struct xmit_frame * xmit_frame,u16 addr,u8 value,u8 mask)74 int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, u8 mask)
75 {
76 	struct ioreg_cfg cmd = {8, IOREG_CMD_WB_REG, 0x0, 0x0, 0x0};
77 
78 	cmd.address = cpu_to_le16(addr);
79 	cmd.data = cpu_to_le32(value);
80 
81 	if (mask != 0xFF) {
82 		cmd.length = 12;
83 		cmd.mask = cpu_to_le32(mask);
84 	}
85 	return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
86 }
87 
_rtw_IOL_append_WW_cmd(struct xmit_frame * xmit_frame,u16 addr,u16 value,u16 mask)88 int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, u16 mask)
89 {
90 	struct ioreg_cfg cmd = {8, IOREG_CMD_WW_REG, 0x0, 0x0, 0x0};
91 
92 	cmd.address = cpu_to_le16(addr);
93 	cmd.data = cpu_to_le32(value);
94 
95 	if (mask != 0xFFFF) {
96 		cmd.length = 12;
97 		cmd.mask =  cpu_to_le32(mask);
98 	}
99 	return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
100 }
101 
_rtw_IOL_append_WD_cmd(struct xmit_frame * xmit_frame,u16 addr,u32 value,u32 mask)102 int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, u32 mask)
103 {
104 	struct ioreg_cfg cmd = {8, IOREG_CMD_WD_REG, 0x0, 0x0, 0x0};
105 
106 	cmd.address = cpu_to_le16(addr);
107 	cmd.data = cpu_to_le32(value);
108 
109 	if (mask != 0xFFFFFFFF) {
110 		cmd.length = 12;
111 		cmd.mask =  cpu_to_le32(mask);
112 	}
113 	return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
114 }
115 
_rtw_IOL_append_WRF_cmd(struct xmit_frame * xmit_frame,u8 rf_path,u16 addr,u32 value,u32 mask)116 int _rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path, u16 addr, u32 value, u32 mask)
117 {
118 	struct ioreg_cfg cmd = {8, IOREG_CMD_W_RF, 0x0, 0x0, 0x0};
119 
120 	cmd.address = cpu_to_le16((rf_path << 8) | ((addr) & 0xFF));
121 	cmd.data = cpu_to_le32(value);
122 
123 	if (mask != 0x000FFFFF) {
124 		cmd.length = 12;
125 		cmd.mask =  cpu_to_le32(mask);
126 	}
127 	return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, cmd.length);
128 }
129 
rtw_IOL_append_DELAY_US_cmd(struct xmit_frame * xmit_frame,u16 us)130 int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
131 {
132 	struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
133 	cmd.address = cpu_to_le16(us);
134 
135 	return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
136 }
137 
rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame * xmit_frame,u16 ms)138 int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
139 {
140 	struct ioreg_cfg cmd = {4, IOREG_CMD_DELAY_US, 0x0, 0x0, 0x0};
141 
142 	cmd.address = cpu_to_le16(ms);
143 	return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
144 }
145 
rtw_IOL_append_END_cmd(struct xmit_frame * xmit_frame)146 int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
147 {
148 	struct ioreg_cfg cmd = {4, IOREG_CMD_END, cpu_to_le16(0xFFFF), cpu_to_le32(0xFF), 0x0};
149 
150 	return rtw_IOL_append_cmds(xmit_frame, (u8 *)&cmd, 4);
151 }
152 
rtw_IOL_cmd_boundary_handle(struct xmit_frame * pxmit_frame)153 u8 rtw_IOL_cmd_boundary_handle(struct xmit_frame *pxmit_frame)
154 {
155 	u8 is_cmd_bndy = false;
156 	if (((pxmit_frame->attrib.pktlen + 32) % 256) + 8 >= 256) {
157 		rtw_IOL_append_END_cmd(pxmit_frame);
158 		pxmit_frame->attrib.pktlen = ((((pxmit_frame->attrib.pktlen + 32) / 256) + 1) * 256);
159 
160 		pxmit_frame->attrib.last_txcmdsz = pxmit_frame->attrib.pktlen;
161 		is_cmd_bndy = true;
162 	}
163 	return is_cmd_bndy;
164 }
165