source: mainline/uspace/drv/nic/ar9271/htc.c@ 961a5ee

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 961a5ee was 5a6cc679, checked in by Jenda <jenda.jzqk73@…>, 8 years ago

Merge commit '50f19b7ee8e94570b5c63896736c4eb49cfa18db' into forwardport

Not all ints are converted to errno_t in xhci tree yet, however it compiles and works :)

  • Property mode set to 100644
File size: 15.4 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 htc.c
30 *
31 * Implementation of Atheros HTC communication.
32 *
33 */
34
35#include <usb/debug.h>
36#include <byteorder.h>
37#include <errno.h>
38#include <str_error.h>
39#include "wmi.h"
40#include "htc.h"
41#include "nic/nic.h"
42#include "ar9271.h"
43
44/** HTC download pipes mapping.
45 *
46 * @param service_id Identification of WMI service.
47 *
48 * @return Number of pipe used for this service.
49 *
50 */
51static inline uint8_t wmi_service_to_download_pipe(wmi_services_t service_id)
52{
53 return (service_id == WMI_CONTROL_SERVICE) ? 3 : 2;
54}
55
56/** HTC upload pipes mapping.
57 *
58 * @param service_id Identification of WMI service.
59 *
60 * @return Number of pipe used for this service.
61 *
62 */
63static inline uint8_t wmi_service_to_upload_pipe(wmi_services_t service_id)
64{
65 return (service_id == WMI_CONTROL_SERVICE) ? 4 : 1;
66}
67
68errno_t htc_init_new_vif(htc_device_t *htc_device)
69{
70 htc_vif_msg_t vif_msg;
71 htc_sta_msg_t sta_msg;
72
73 memset(&vif_msg, 0, sizeof(htc_vif_msg_t));
74 memset(&sta_msg, 0, sizeof(htc_sta_msg_t));
75
76 nic_address_t addr;
77 nic_t *nic =
78 nic_get_from_ddf_dev(ieee80211_get_ddf_dev(htc_device->ieee80211_dev));
79 nic_query_address(nic, &addr);
80
81 memcpy(&vif_msg.addr, &addr.address, ETH_ADDR);
82 memcpy(&sta_msg.addr, &addr.address, ETH_ADDR);
83
84 ieee80211_operating_mode_t op_mode =
85 ieee80211_query_current_op_mode(htc_device->ieee80211_dev);
86
87 switch (op_mode) {
88 case IEEE80211_OPMODE_ADHOC:
89 vif_msg.op_mode = HTC_OPMODE_ADHOC;
90 break;
91 case IEEE80211_OPMODE_AP:
92 vif_msg.op_mode = HTC_OPMODE_AP;
93 break;
94 case IEEE80211_OPMODE_MESH:
95 vif_msg.op_mode = HTC_OPMODE_MESH;
96 break;
97 case IEEE80211_OPMODE_STATION:
98 vif_msg.op_mode = HTC_OPMODE_STATION;
99 break;
100 }
101
102 vif_msg.index = 0;
103 vif_msg.rts_thres = host2uint16_t_be(HTC_RTS_THRESHOLD);
104
105 wmi_send_command(htc_device, WMI_VAP_CREATE, (uint8_t *) &vif_msg,
106 sizeof(vif_msg), NULL);
107
108 sta_msg.is_vif_sta = 1;
109 sta_msg.max_ampdu = host2uint16_t_be(0xFFFF);
110 sta_msg.sta_index = 0;
111 sta_msg.vif_index = 0;
112
113 wmi_send_command(htc_device, WMI_NODE_CREATE, (uint8_t *) &sta_msg,
114 sizeof(sta_msg), NULL);
115
116 /* Write first 4 bytes of MAC address. */
117 uint32_t id0;
118 memcpy(&id0, &addr.address, 4);
119 id0 = host2uint32_t_le(id0);
120 wmi_reg_write(htc_device, AR9271_STATION_ID0, id0);
121
122 /* Write last 2 bytes of MAC address (and preserve existing data). */
123 uint32_t id1;
124 wmi_reg_read(htc_device, AR9271_STATION_ID1, &id1);
125
126 uint16_t id1_addr;
127 memcpy(&id1_addr, &addr.address[4], 2);
128 id1 = (id1 & ~AR9271_STATION_ID1_MASK) | host2uint16_t_le(id1_addr);
129 wmi_reg_write(htc_device, AR9271_STATION_ID1, id1);
130
131 return EOK;
132}
133
134static void htc_config_frame_header(htc_frame_header_t *header,
135 size_t buffer_size, uint8_t endpoint_id)
136{
137 memset(header, 0, sizeof(htc_frame_header_t));
138
139 header->endpoint_id = endpoint_id;
140 header->payload_length =
141 host2uint16_t_be(buffer_size - sizeof(htc_frame_header_t));
142}
143
144/** Send control HTC message to USB device.
145 *
146 * @param htc_device HTC device structure.
147 * @param buffer Buffer with data to be sent to USB device
148 * (without HTC frame header).
149 * @param buffer_size Size of buffer (including HTC frame header).
150 * @param endpoint_id Destination endpoint.
151 *
152 * @return EOK if succeed, error code otherwise.
153 *
154 */
155errno_t htc_send_control_message(htc_device_t *htc_device, void *buffer,
156 size_t buffer_size, uint8_t endpoint_id)
157{
158 htc_config_frame_header((htc_frame_header_t *) buffer, buffer_size,
159 endpoint_id);
160
161 ath_t *ath_device = htc_device->ath_device;
162
163 return ath_device->ops->send_ctrl_message(ath_device, buffer,
164 buffer_size);
165}
166
167/** Send data HTC message to USB device.
168 *
169 * @param htc_device HTC device structure.
170 * @param buffer Buffer with data to be sent to USB device
171 * (without HTC frame header).
172 * @param buffer_size Size of buffer (including HTC frame header).
173 * @param endpoint_id Destination endpoint.
174 *
175 * @return EOK if succeed, error code otherwise.
176 *
177 */
178errno_t htc_send_data_message(htc_device_t *htc_device, void *buffer,
179 size_t buffer_size, uint8_t endpoint_id)
180{
181 htc_config_frame_header((htc_frame_header_t *) buffer, buffer_size,
182 endpoint_id);
183
184 ath_t *ath_device = htc_device->ath_device;
185
186 return ath_device->ops->send_data_message(ath_device, buffer,
187 buffer_size);
188}
189
190/** Read HTC data message from USB device.
191 *
192 * @param htc_device HTC device structure.
193 * @param buffer Buffer where data from USB device
194 * will be stored.
195 * @param buffer_size Size of buffer.
196 * @param transferred_size Real size of read data.
197 *
198 * @return EOK if succeed, error code otherwise.
199 *
200 */
201errno_t htc_read_data_message(htc_device_t *htc_device, void *buffer,
202 size_t buffer_size, size_t *transferred_size)
203{
204 ath_t *ath_device = htc_device->ath_device;
205
206 return ath_device->ops->read_data_message(ath_device, buffer,
207 buffer_size, transferred_size);
208}
209
210/** Read HTC control message from USB device.
211 *
212 * @param htc_device HTC device structure.
213 * @param buffer Buffer where data from USB device
214 * will be stored.
215 * @param buffer_size Size of buffer.
216 * @param transferred_size Real size of read data.
217 *
218 * @return EOK if succeed, error code otherwise.
219 *
220 */
221errno_t htc_read_control_message(htc_device_t *htc_device, void *buffer,
222 size_t buffer_size, size_t *transferred_size)
223{
224 ath_t *ath_device = htc_device->ath_device;
225
226 return ath_device->ops->read_ctrl_message(ath_device, buffer,
227 buffer_size, transferred_size);
228}
229
230/** Initialize HTC service.
231 *
232 * @param htc_device HTC device structure.
233 * @param service_id Identification of WMI service.
234 * @param response_endpoint_no HTC endpoint to be used for
235 * this service.
236 *
237 * @return EOK if succeed, EINVAL when failed to connect service,
238 * error code otherwise.
239 *
240 */
241static errno_t htc_connect_service(htc_device_t *htc_device,
242 wmi_services_t service_id, int *response_endpoint_no)
243{
244 size_t buffer_size = sizeof(htc_frame_header_t) +
245 sizeof(htc_service_msg_t);
246 void *buffer = malloc(buffer_size);
247 memset(buffer, 0, buffer_size);
248
249 /* Fill service message structure. */
250 htc_service_msg_t *service_message = (htc_service_msg_t *)
251 ((void *) buffer + sizeof(htc_frame_header_t));
252 service_message->service_id =
253 host2uint16_t_be(service_id);
254 service_message->message_id =
255 host2uint16_t_be(HTC_MESSAGE_CONNECT_SERVICE);
256 service_message->download_pipe_id =
257 wmi_service_to_download_pipe(service_id);
258 service_message->upload_pipe_id =
259 wmi_service_to_upload_pipe(service_id);
260 service_message->connection_flags = 0;
261
262 /* Send HTC message. */
263 errno_t rc = htc_send_control_message(htc_device, buffer, buffer_size,
264 htc_device->endpoints.ctrl_endpoint);
265 if (rc != EOK) {
266 free(buffer);
267 usb_log_error("Failed to send HTC message. Error: %s\n", str_error_name(rc));
268 return rc;
269 }
270
271 free(buffer);
272
273 buffer_size = htc_device->ath_device->ctrl_response_length;
274 buffer = malloc(buffer_size);
275
276 /* Read response from device. */
277 rc = htc_read_control_message(htc_device, buffer, buffer_size, NULL);
278 if (rc != EOK) {
279 free(buffer);
280 usb_log_error("Failed to receive HTC service connect response. "
281 "Error: %s\n", str_error_name(rc));
282 return rc;
283 }
284
285 htc_service_resp_msg_t *response_message = (htc_service_resp_msg_t *)
286 ((void *) buffer + sizeof(htc_frame_header_t));
287
288 /*
289 * If service was successfully connected,
290 * write down HTC endpoint number that will
291 * be used for communication.
292 */
293 if (response_message->status == HTC_SERVICE_SUCCESS) {
294 *response_endpoint_no = response_message->endpoint_id;
295 rc = EOK;
296 } else {
297 usb_log_error("Failed to connect HTC service. "
298 "Message status: %d\n", response_message->status);
299 rc = EINVAL;
300 }
301
302 free(buffer);
303
304 return rc;
305}
306
307/** HTC credits initialization message.
308 *
309 * @param htc_device HTC device structure.
310 *
311 * @return EOK if succeed, error code otherwise.
312 *
313 */
314static errno_t htc_config_credits(htc_device_t *htc_device)
315{
316 size_t buffer_size = sizeof(htc_frame_header_t) +
317 sizeof(htc_config_msg_t);
318 void *buffer = malloc(buffer_size);
319 htc_config_msg_t *config_message = (htc_config_msg_t *)
320 ((void *) buffer + sizeof(htc_frame_header_t));
321
322 config_message->message_id =
323 host2uint16_t_be(HTC_MESSAGE_CONFIG);
324 /* Magic number to initialize device. */
325 config_message->credits = 33;
326 config_message->pipe_id = 1;
327
328 /* Send HTC message. */
329 errno_t rc = htc_send_control_message(htc_device, buffer, buffer_size,
330 htc_device->endpoints.ctrl_endpoint);
331 if (rc != EOK) {
332 free(buffer);
333 usb_log_error("Failed to send HTC config message. "
334 "Error: %s\n", str_error_name(rc));
335 return rc;
336 }
337
338 free(buffer);
339
340 buffer_size = htc_device->ath_device->ctrl_response_length;
341 buffer = malloc(buffer_size);
342
343 /* Check response from device. */
344 rc = htc_read_control_message(htc_device, buffer, buffer_size, NULL);
345 if (rc != EOK) {
346 usb_log_error("Failed to receive HTC config response message. "
347 "Error: %s\n", str_error_name(rc));
348 }
349
350 free(buffer);
351
352 return rc;
353}
354
355/** HTC setup complete confirmation message.
356 *
357 * @param htc_device HTC device structure.
358 *
359 * @return EOK if succeed, error code otherwise.
360 *
361 */
362static errno_t htc_complete_setup(htc_device_t *htc_device)
363{
364 size_t buffer_size = sizeof(htc_frame_header_t) +
365 sizeof(htc_setup_complete_msg_t);
366 void *buffer = malloc(buffer_size);
367 htc_setup_complete_msg_t *complete_message =
368 (htc_setup_complete_msg_t *)
369 ((void *) buffer + sizeof(htc_frame_header_t));
370
371 complete_message->message_id =
372 host2uint16_t_be(HTC_MESSAGE_SETUP_COMPLETE);
373
374 /* Send HTC message. */
375 errno_t rc = htc_send_control_message(htc_device, buffer, buffer_size,
376 htc_device->endpoints.ctrl_endpoint);
377 if (rc != EOK)
378 usb_log_error("Failed to send HTC setup complete message. "
379 "Error: %s\n", str_error_name(rc));
380
381 free(buffer);
382
383 return rc;
384}
385
386/** Try to fetch ready message from device.
387 *
388 * Checks that firmware was successfully loaded on device side.
389 *
390 * @param htc_device HTC device structure.
391 *
392 * @return EOK if succeed, EINVAL if response error,
393 * error code otherwise.
394 *
395 */
396static errno_t htc_check_ready(htc_device_t *htc_device)
397{
398 size_t buffer_size = htc_device->ath_device->ctrl_response_length;
399 void *buffer = malloc(buffer_size);
400
401 /* Read response from device. */
402 errno_t rc = htc_read_control_message(htc_device, buffer, buffer_size,
403 NULL);
404 if (rc != EOK) {
405 free(buffer);
406 usb_log_error("Failed to receive HTC check ready message. "
407 "Error: %s\n", str_error_name(rc));
408 return rc;
409 }
410
411 uint16_t *message_id = (uint16_t *) ((void *) buffer +
412 sizeof(htc_frame_header_t));
413 if (uint16_t_be2host(*message_id) == HTC_MESSAGE_READY)
414 rc = EOK;
415 else
416 rc = EINVAL;
417
418 free(buffer);
419
420 return rc;
421}
422
423/** Initialize HTC device structure.
424 *
425 * @param ath_device Atheros WiFi device connected
426 * with this HTC device.
427 * @param htc_device HTC device structure to be initialized.
428 *
429 * @return EOK if succeed, error code otherwise.
430 *
431 */
432errno_t htc_device_init(ath_t *ath_device, ieee80211_dev_t *ieee80211_dev,
433 htc_device_t *htc_device)
434{
435 fibril_mutex_initialize(&htc_device->rx_lock);
436 fibril_mutex_initialize(&htc_device->tx_lock);
437
438 htc_device->endpoints.ctrl_endpoint = 0;
439
440 htc_device->ath_device = ath_device;
441 htc_device->ieee80211_dev = ieee80211_dev;
442
443 return EOK;
444}
445
446/** HTC communication initalization.
447 *
448 * @param htc_device HTC device structure.
449 *
450 * @return EOK if succeed, error code otherwise.
451 *
452 */
453errno_t htc_init(htc_device_t *htc_device)
454{
455 /* First check ready message in device. */
456 errno_t rc = htc_check_ready(htc_device);
457 if (rc != EOK) {
458 usb_log_error("Device is not in ready state after loading "
459 "firmware.\n");
460 return rc;
461 }
462
463 /*
464 * HTC services initialization start.
465 */
466 rc = htc_connect_service(htc_device, WMI_CONTROL_SERVICE,
467 &htc_device->endpoints.wmi_endpoint);
468 if (rc != EOK) {
469 usb_log_error("Error while initalizing WMI service.\n");
470 return rc;
471 }
472
473 rc = htc_connect_service(htc_device, WMI_BEACON_SERVICE,
474 &htc_device->endpoints.beacon_endpoint);
475 if (rc != EOK) {
476 usb_log_error("Error while initalizing beacon service.\n");
477 return rc;
478 }
479
480 rc = htc_connect_service(htc_device, WMI_CAB_SERVICE,
481 &htc_device->endpoints.cab_endpoint);
482 if (rc != EOK) {
483 usb_log_error("Error while initalizing CAB service.\n");
484 return rc;
485 }
486
487 rc = htc_connect_service(htc_device, WMI_UAPSD_SERVICE,
488 &htc_device->endpoints.uapsd_endpoint);
489 if (rc != EOK) {
490 usb_log_error("Error while initalizing UAPSD service.\n");
491 return rc;
492 }
493
494 rc = htc_connect_service(htc_device, WMI_MGMT_SERVICE,
495 &htc_device->endpoints.mgmt_endpoint);
496 if (rc != EOK) {
497 usb_log_error("Error while initalizing MGMT service.\n");
498 return rc;
499 }
500
501 rc = htc_connect_service(htc_device, WMI_DATA_BE_SERVICE,
502 &htc_device->endpoints.data_be_endpoint);
503 if (rc != EOK) {
504 usb_log_error("Error while initalizing data best effort "
505 "service.\n");
506 return rc;
507 }
508
509 rc = htc_connect_service(htc_device, WMI_DATA_BK_SERVICE,
510 &htc_device->endpoints.data_bk_endpoint);
511 if (rc != EOK) {
512 usb_log_error("Error while initalizing data background "
513 "service.\n");
514 return rc;
515 }
516
517 rc = htc_connect_service(htc_device, WMI_DATA_VIDEO_SERVICE,
518 &htc_device->endpoints.data_video_endpoint);
519 if (rc != EOK) {
520 usb_log_error("Error while initalizing data video service.\n");
521 return rc;
522 }
523
524 rc = htc_connect_service(htc_device, WMI_DATA_VOICE_SERVICE,
525 &htc_device->endpoints.data_voice_endpoint);
526 if (rc != EOK) {
527 usb_log_error("Error while initalizing data voice service.\n");
528 return rc;
529 }
530
531 /*
532 * HTC services initialization end.
533 */
534
535 /* Credits initialization message. */
536 rc = htc_config_credits(htc_device);
537 if (rc != EOK) {
538 usb_log_error("Failed to send HTC config message.\n");
539 return rc;
540 }
541
542 /* HTC setup complete confirmation message. */
543 rc = htc_complete_setup(htc_device);
544 if (rc != EOK) {
545 usb_log_error("Failed to send HTC complete setup message.\n");
546 return rc;
547 }
548
549 usb_log_info("HTC services initialization finished successfully.\n");
550
551 return EOK;
552}
Note: See TracBrowser for help on using the repository browser.