source: mainline/uspace/drv/nic/ar9271/wmi.c@ fb1007ef

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fb1007ef was fb1007ef, checked in by Jan Vesely <jano.vesely@…>, 10 years ago

ar9271: Add missing headers

  • Property mode set to 100644
File size: 8.2 KB
Line 
1/*
2 * Copyright (c) 2014 Jan Kolarik
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file wmi.c
30 *
31 * Implementation of Atheros WMI communication.
32 *
33 */
34
35#include <usb/debug.h>
36#include <errno.h>
37#include <malloc.h>
38#include <mem.h>
39#include <byteorder.h>
40#include "wmi.h"
41
42/** WMI registry read.
43 *
44 * @param htc_device HTC device structure.
45 * @param reg_offset Registry offset (address) to be read.
46 * @param res Stored result.
47 *
48 * @return EOK if succeed, negative error code otherwise.
49 *
50 */
51int wmi_reg_read(htc_device_t *htc_device, uint32_t reg_offset, uint32_t *res)
52{
53 uint32_t cmd_value = host2uint32_t_be(reg_offset);
54
55 void *resp_buffer =
56 malloc(htc_device->ath_device->ctrl_response_length);
57
58 int rc = wmi_send_command(htc_device, WMI_REG_READ,
59 (uint8_t *) &cmd_value, sizeof(cmd_value), resp_buffer);
60
61 if (rc != EOK) {
62 usb_log_error("Failed to read registry value.\n");
63 return rc;
64 }
65
66 uint32_t *resp_value = (uint32_t *) ((void *) resp_buffer +
67 sizeof(htc_frame_header_t) + sizeof(wmi_command_header_t));
68
69 *res = uint32_t_be2host(*resp_value);
70
71 return rc;
72}
73
74/** WMI registry write.
75 *
76 * @param htc_device HTC device structure.
77 * @param reg_offset Registry offset (address) to be written.
78 * @param val Value to be written
79 *
80 * @return EOK if succeed, negative error code otherwise.
81 *
82 */
83int wmi_reg_write(htc_device_t *htc_device, uint32_t reg_offset, uint32_t val)
84{
85 uint32_t cmd_buffer[] = {
86 host2uint32_t_be(reg_offset),
87 host2uint32_t_be(val)
88 };
89
90 void *resp_buffer =
91 malloc(htc_device->ath_device->ctrl_response_length);
92
93 int rc = wmi_send_command(htc_device, WMI_REG_WRITE,
94 (uint8_t *) &cmd_buffer, sizeof(cmd_buffer), resp_buffer);
95
96 free(resp_buffer);
97
98 if (rc != EOK) {
99 usb_log_error("Failed to write registry value.\n");
100 return rc;
101 }
102
103 return rc;
104}
105
106/** WMI registry set or clear specified bits.
107 *
108 * @param htc_device HTC device structure.
109 * @param reg_offset Registry offset (address) to be written.
110 * @param set_bit Bit to be set.
111 * @param clear_bit Bit to be cleared.
112 *
113 * @return EOK if succeed, negative error code otherwise.
114 *
115 */
116int wmi_reg_set_clear_bit(htc_device_t *htc_device, uint32_t reg_offset,
117 uint32_t set_bit, uint32_t clear_bit)
118{
119 uint32_t value;
120
121 int rc = wmi_reg_read(htc_device, reg_offset, &value);
122 if (rc != EOK) {
123 usb_log_error("Failed to read registry value in RMW "
124 "function.\n");
125 return rc;
126 }
127
128 value &= ~clear_bit;
129 value |= set_bit;
130
131 rc = wmi_reg_write(htc_device, reg_offset, value);
132 if (rc != EOK) {
133 usb_log_error("Failed to write registry value in RMW "
134 "function.\n");
135 return rc;
136 }
137
138 return rc;
139}
140
141/** WMI registry set specified bit.
142 *
143 * @param htc_device HTC device structure.
144 * @param reg_offset Registry offset (address) to be written.
145 * @param set_bit Bit to be set.
146 *
147 * @return EOK if succeed, negative error code otherwise.
148 *
149 */
150int wmi_reg_set_bit(htc_device_t *htc_device, uint32_t reg_offset,
151 uint32_t set_bit)
152{
153 return wmi_reg_set_clear_bit(htc_device, reg_offset, set_bit, 0);
154}
155
156/** WMI registry clear specified bit.
157 *
158 * @param htc_device HTC device structure.
159 * @param reg_offset Registry offset (address) to be written.
160 * @param clear_bit Bit to be cleared.
161 *
162 * @return EOK if succeed, negative error code otherwise.
163 *
164 */
165int wmi_reg_clear_bit(htc_device_t *htc_device, uint32_t reg_offset,
166 uint32_t clear_bit)
167{
168 return wmi_reg_set_clear_bit(htc_device, reg_offset, 0, clear_bit);
169}
170
171/** WMI multi registry write.
172 *
173 * @param htc_device HTC device structure.
174 * @param reg_buffer Array of registry values to be written.
175 * @param elements Number of elements in array.
176 *
177 * @return EOK if succeed, negative error code otherwise.
178 *
179 */
180int wmi_reg_buffer_write(htc_device_t *htc_device, wmi_reg_t *reg_buffer,
181 size_t elements)
182{
183 size_t buffer_size = sizeof(wmi_reg_t) * elements;
184 void *buffer = malloc(buffer_size);
185 void *resp_buffer =
186 malloc(htc_device->ath_device->ctrl_response_length);
187
188 /* Convert values to correct endianness. */
189 for (size_t i = 0; i < elements; i++) {
190 wmi_reg_t *buffer_element = &reg_buffer[i];
191 wmi_reg_t *buffer_it = (wmi_reg_t *)
192 ((void *) buffer + i * sizeof(wmi_reg_t));
193 buffer_it->offset =
194 host2uint32_t_be(buffer_element->offset);
195 buffer_it->value =
196 host2uint32_t_be(buffer_element->value);
197 }
198
199 int rc = wmi_send_command(htc_device, WMI_REG_WRITE,
200 (uint8_t *) buffer, buffer_size, resp_buffer);
201
202 free(buffer);
203 free(resp_buffer);
204
205 if (rc != EOK) {
206 usb_log_error("Failed to write multi registry value.\n");
207 return rc;
208 }
209
210 return rc;
211}
212
213/** Send WMI message to HTC device.
214 *
215 * @param htc_device HTC device structure.
216 * @param command_id Command identification.
217 * @param command_buffer Buffer with command data.
218 * @param command_length Length of command data.
219 * @param response_buffer Buffer with response data.
220 *
221 * @return EOK if succeed, negative error code otherwise.
222 *
223 */
224int wmi_send_command(htc_device_t *htc_device, wmi_command_t command_id,
225 uint8_t *command_buffer, uint32_t command_length, void *response_buffer)
226{
227 size_t header_size = sizeof(wmi_command_header_t) +
228 sizeof(htc_frame_header_t);
229 size_t buffer_size = header_size + command_length;
230 void *buffer = malloc(buffer_size);
231
232 if (command_buffer != NULL)
233 memcpy(buffer+header_size, command_buffer, command_length);
234
235 /* Set up WMI header */
236 wmi_command_header_t *wmi_header = (wmi_command_header_t *)
237 ((void *) buffer + sizeof(htc_frame_header_t));
238 wmi_header->command_id = host2uint16_t_be(command_id);
239 wmi_header->sequence_number =
240 host2uint16_t_be(++htc_device->sequence_number);
241
242 /* Send message. */
243 int rc = htc_send_control_message(htc_device, buffer, buffer_size,
244 htc_device->endpoints.wmi_endpoint);
245 if (rc != EOK) {
246 free(buffer);
247 usb_log_error("Failed to send WMI message. Error: %d\n", rc);
248 return rc;
249 }
250
251 free(buffer);
252
253 bool clean_resp_buffer = false;
254 size_t response_buffer_size =
255 htc_device->ath_device->ctrl_response_length;
256 if (response_buffer == NULL) {
257 response_buffer = malloc(response_buffer_size);
258 clean_resp_buffer = true;
259 }
260
261 /* Read response. */
262 /* TODO: Ignoring WMI management RX messages ~ TX statuses etc. */
263 uint16_t cmd_id;
264 do {
265 rc = htc_read_control_message(htc_device, response_buffer,
266 response_buffer_size, NULL);
267 if (rc != EOK) {
268 free(buffer);
269 usb_log_error("Failed to receive WMI message response. "
270 "Error: %d\n", rc);
271 return rc;
272 }
273
274 if (response_buffer_size < sizeof(htc_frame_header_t) +
275 sizeof(wmi_command_header_t)) {
276 free(buffer);
277 usb_log_error("Corrupted response received.\n");
278 return EINVAL;
279 }
280
281 wmi_command_header_t *wmi_hdr = (wmi_command_header_t *)
282 ((void *) response_buffer + sizeof(htc_frame_header_t));
283 cmd_id = uint16_t_be2host(wmi_hdr->command_id);
284 } while(cmd_id & WMI_MGMT_CMD_MASK);
285
286 if (clean_resp_buffer)
287 free(response_buffer);
288
289 return rc;
290}
Note: See TracBrowser for help on using the repository browser.