source: mainline/uspace/drv/nic/ar9271/ar9271.c@ 132ab5d1

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

Merge commit '6a5d05bd2551e64111bea4f9332dd7448c26ce84' into forwardport

Separate return value from error code in gen_irq_code*().

  • Property mode set to 100644
File size: 24.9 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 ar9271.c
30 *
31 * Driver for AR9271 USB WiFi dongle.
32 *
33 */
34
35#include <async.h>
36#include <ieee80211.h>
37#include <usb/classes/classes.h>
38#include <usb/dev/request.h>
39#include <usb/dev/poll.h>
40#include <usb/debug.h>
41#include <stdio.h>
42#include <ddf/interrupt.h>
43#include <errno.h>
44#include <str_error.h>
45#include <nic.h>
46#include <macros.h>
47#include "ath_usb.h"
48#include "wmi.h"
49#include "hw.h"
50#include "ar9271.h"
51
52#define NAME "ar9271"
53#define FIRMWARE_FILENAME "/drv/ar9271/ar9271.fw"
54
55const usb_endpoint_description_t usb_ar9271_out_bulk_endpoint_description = {
56 .transfer_type = USB_TRANSFER_BULK,
57 .direction = USB_DIRECTION_OUT,
58 .interface_class = USB_CLASS_VENDOR_SPECIFIC,
59 .interface_subclass = 0x0,
60 .interface_protocol = 0x0,
61 .flags = 0
62};
63
64const usb_endpoint_description_t usb_ar9271_in_bulk_endpoint_description = {
65 .transfer_type = USB_TRANSFER_BULK,
66 .direction = USB_DIRECTION_IN,
67 .interface_class = USB_CLASS_VENDOR_SPECIFIC,
68 .interface_subclass = 0x0,
69 .interface_protocol = 0x0,
70 .flags = 0
71};
72
73const usb_endpoint_description_t usb_ar9271_in_int_endpoint_description = {
74 .transfer_type = USB_TRANSFER_INTERRUPT,
75 .direction = USB_DIRECTION_IN,
76 .interface_class = USB_CLASS_VENDOR_SPECIFIC,
77 .interface_subclass = 0x0,
78 .interface_protocol = 0x0,
79 .flags = 0
80};
81
82const usb_endpoint_description_t usb_ar9271_out_int_endpoint_description = {
83 .transfer_type = USB_TRANSFER_INTERRUPT,
84 .direction = USB_DIRECTION_OUT,
85 .interface_class = USB_CLASS_VENDOR_SPECIFIC,
86 .interface_subclass = 0x0,
87 .interface_protocol = 0x0,
88 .flags = 0
89};
90
91/* Array of endpoints expected on the device, NULL terminated. */
92const usb_endpoint_description_t *endpoints[] = {
93 &usb_ar9271_out_bulk_endpoint_description,
94 &usb_ar9271_in_bulk_endpoint_description,
95 &usb_ar9271_in_int_endpoint_description,
96 &usb_ar9271_out_int_endpoint_description,
97 NULL
98};
99
100/* Callback when new device is to be controlled by this driver. */
101static int ar9271_add_device(ddf_dev_t *);
102
103/* IEEE 802.11 callbacks */
104static int ar9271_ieee80211_start(ieee80211_dev_t *);
105static int ar9271_ieee80211_tx_handler(ieee80211_dev_t *, void *, size_t);
106static int ar9271_ieee80211_set_freq(ieee80211_dev_t *, uint16_t);
107static int ar9271_ieee80211_bssid_change(ieee80211_dev_t *, bool);
108static int ar9271_ieee80211_key_config(ieee80211_dev_t *, ieee80211_key_config_t *,
109 bool);
110
111static driver_ops_t ar9271_driver_ops = {
112 .dev_add = ar9271_add_device
113};
114
115static driver_t ar9271_driver = {
116 .name = NAME,
117 .driver_ops = &ar9271_driver_ops
118};
119
120static ieee80211_ops_t ar9271_ieee80211_ops = {
121 .start = ar9271_ieee80211_start,
122 .tx_handler = ar9271_ieee80211_tx_handler,
123 .set_freq = ar9271_ieee80211_set_freq,
124 .bssid_change = ar9271_ieee80211_bssid_change,
125 .key_config = ar9271_ieee80211_key_config
126};
127
128static ieee80211_iface_t ar9271_ieee80211_iface;
129
130static int ar9271_get_device_info(ddf_fun_t *, nic_device_info_t *);
131static int ar9271_get_cable_state(ddf_fun_t *, nic_cable_state_t *);
132static int ar9271_get_operation_mode(ddf_fun_t *, int *, nic_channel_mode_t *,
133 nic_role_t *);
134
135static nic_iface_t ar9271_ieee80211_nic_iface = {
136 .get_device_info = &ar9271_get_device_info,
137 .get_cable_state = &ar9271_get_cable_state,
138 .get_operation_mode = &ar9271_get_operation_mode
139};
140
141static ddf_dev_ops_t ar9271_ieee80211_dev_ops;
142
143/** Get device information.
144 *
145 */
146static int ar9271_get_device_info(ddf_fun_t *dev, nic_device_info_t *info)
147{
148 assert(dev);
149 assert(info);
150
151 memset(info, 0, sizeof(nic_device_info_t));
152
153 info->vendor_id = 0x0cf3;
154 info->device_id = 0x9271;
155 str_cpy(info->vendor_name, NIC_VENDOR_MAX_LENGTH,
156 "Atheros Communications, Inc.");
157 str_cpy(info->model_name, NIC_MODEL_MAX_LENGTH,
158 "AR9271");
159
160 return EOK;
161}
162
163/** Get cable state.
164 *
165 */
166static int ar9271_get_cable_state(ddf_fun_t *fun, nic_cable_state_t *state)
167{
168 *state = NIC_CS_PLUGGED;
169
170 return EOK;
171}
172
173/** Get operation mode of the device.
174 *
175 */
176static int ar9271_get_operation_mode(ddf_fun_t *fun, int *speed,
177 nic_channel_mode_t *duplex, nic_role_t *role)
178{
179 *duplex = NIC_CM_FULL_DUPLEX;
180 *speed = 10;
181 *role = NIC_ROLE_UNKNOWN;
182
183 return EOK;
184}
185
186/** Set multicast frames acceptance mode.
187 *
188 */
189static int ar9271_on_multicast_mode_change(nic_t *nic,
190 nic_multicast_mode_t mode, const nic_address_t *addr, size_t addr_cnt)
191{
192 switch (mode) {
193 case NIC_MULTICAST_BLOCKED:
194 /* TODO */
195 break;
196 case NIC_MULTICAST_LIST:
197 /* TODO */
198 break;
199 case NIC_MULTICAST_PROMISC:
200 /* TODO */
201 break;
202 default:
203 return ENOTSUP;
204 }
205
206 return EOK;
207}
208
209/** Set unicast frames acceptance mode.
210 *
211 */
212static int ar9271_on_unicast_mode_change(nic_t *nic, nic_unicast_mode_t mode,
213 const nic_address_t *addr, size_t addr_cnt)
214{
215 switch (mode) {
216 case NIC_UNICAST_BLOCKED:
217 /* TODO */
218 break;
219 case NIC_UNICAST_DEFAULT:
220 /* TODO */
221 break;
222 case NIC_UNICAST_LIST:
223 /* TODO */
224 break;
225 case NIC_UNICAST_PROMISC:
226 /* TODO */
227 break;
228 default:
229 return ENOTSUP;
230 }
231
232 return EOK;
233}
234
235/** Set broadcast frames acceptance mode.
236 *
237 */
238static int ar9271_on_broadcast_mode_change(nic_t *nic,
239 nic_broadcast_mode_t mode)
240{
241 switch (mode) {
242 case NIC_BROADCAST_BLOCKED:
243 /* TODO */
244 break;
245 case NIC_BROADCAST_ACCEPTED:
246 /* TODO */
247 break;
248 default:
249 return ENOTSUP;
250 }
251
252 return EOK;
253}
254
255static bool ar9271_rx_status_error(uint8_t status)
256{
257 return (status & AR9271_RX_ERROR_PHY) || (status & AR9271_RX_ERROR_CRC);
258}
259
260static int ar9271_data_polling(void *arg)
261{
262 assert(arg);
263
264 ar9271_t *ar9271 = (ar9271_t *) arg;
265
266 size_t buffer_size = ar9271->ath_device->data_response_length;
267 void *buffer = malloc(buffer_size);
268
269 while (true) {
270 size_t transferred_size;
271 if (htc_read_data_message(ar9271->htc_device,
272 buffer, buffer_size, &transferred_size) == EOK) {
273 size_t strip_length =
274 sizeof(ath_usb_data_header_t) +
275 sizeof(htc_frame_header_t) +
276 sizeof(htc_rx_status_t);
277
278 if (transferred_size < strip_length)
279 continue;
280
281 ath_usb_data_header_t *data_header =
282 (ath_usb_data_header_t *) buffer;
283
284 /* Invalid packet. */
285 if (data_header->tag != uint16_t_le2host(RX_TAG))
286 continue;
287
288 htc_rx_status_t *rx_status =
289 (htc_rx_status_t *) ((void *) buffer +
290 sizeof(ath_usb_data_header_t) +
291 sizeof(htc_frame_header_t));
292
293 uint16_t data_length =
294 uint16_t_be2host(rx_status->data_length);
295
296 int16_t payload_length =
297 transferred_size - strip_length;
298
299 if (payload_length - data_length < 0)
300 continue;
301
302 if (ar9271_rx_status_error(rx_status->status))
303 continue;
304
305 void *strip_buffer = buffer + strip_length;
306
307 ieee80211_rx_handler(ar9271->ieee80211_dev,
308 strip_buffer,
309 payload_length);
310 }
311 }
312
313 free(buffer);
314
315 return EOK;
316}
317
318/** IEEE 802.11 handlers.
319 *
320 */
321static int ar9271_ieee80211_set_freq(ieee80211_dev_t *ieee80211_dev,
322 uint16_t freq)
323{
324 assert(ieee80211_dev);
325
326 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
327
328 wmi_send_command(ar9271->htc_device, WMI_DISABLE_INTR, NULL, 0, NULL);
329 wmi_send_command(ar9271->htc_device, WMI_DRAIN_TXQ_ALL, NULL, 0, NULL);
330 wmi_send_command(ar9271->htc_device, WMI_STOP_RECV, NULL, 0, NULL);
331
332 int rc = hw_freq_switch(ar9271, freq);
333 if (rc != EOK) {
334 usb_log_error("Failed to HW switch frequency.\n");
335 return rc;
336 }
337
338 wmi_send_command(ar9271->htc_device, WMI_START_RECV, NULL, 0, NULL);
339
340 rc = hw_rx_init(ar9271);
341 if (rc != EOK) {
342 usb_log_error("Failed to initialize RX.\n");
343 return rc;
344 }
345
346 uint16_t htc_mode = host2uint16_t_be(1);
347 wmi_send_command(ar9271->htc_device, WMI_SET_MODE,
348 (uint8_t *) &htc_mode, sizeof(htc_mode), NULL);
349 wmi_send_command(ar9271->htc_device, WMI_ENABLE_INTR, NULL, 0, NULL);
350
351 return EOK;
352}
353
354static int ar9271_ieee80211_bssid_change(ieee80211_dev_t *ieee80211_dev,
355 bool connected)
356{
357 assert(ieee80211_dev);
358
359 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
360
361 if (connected) {
362 nic_address_t bssid;
363 ieee80211_query_bssid(ieee80211_dev, &bssid);
364
365 htc_sta_msg_t sta_msg;
366 memset(&sta_msg, 0, sizeof(htc_sta_msg_t));
367 sta_msg.is_vif_sta = 0;
368 sta_msg.max_ampdu =
369 host2uint16_t_be(1 << IEEE80211_MAX_AMPDU_FACTOR);
370 sta_msg.sta_index = 1;
371 sta_msg.vif_index = 0;
372 memcpy(&sta_msg.addr, bssid.address, ETH_ADDR);
373
374 wmi_send_command(ar9271->htc_device, WMI_NODE_CREATE,
375 (uint8_t *) &sta_msg, sizeof(sta_msg), NULL);
376
377 htc_rate_msg_t rate_msg;
378 memset(&rate_msg, 0, sizeof(htc_rate_msg_t));
379 rate_msg.sta_index = 1;
380 rate_msg.is_new = 1;
381 rate_msg.legacy_rates_count = ARRAY_SIZE(ieee80211bg_data_rates);
382 memcpy(&rate_msg.legacy_rates,
383 ieee80211bg_data_rates,
384 ARRAY_SIZE(ieee80211bg_data_rates));
385
386 wmi_send_command(ar9271->htc_device, WMI_RC_RATE_UPDATE,
387 (uint8_t *) &rate_msg, sizeof(rate_msg), NULL);
388
389 hw_set_rx_filter(ar9271, true);
390 } else {
391 uint8_t station_id = 1;
392 wmi_send_command(ar9271->htc_device, WMI_NODE_REMOVE,
393 &station_id, sizeof(station_id), NULL);
394
395 hw_set_rx_filter(ar9271, false);
396 }
397
398 hw_set_bssid(ar9271);
399
400 return EOK;
401}
402
403static int ar9271_ieee80211_key_config(ieee80211_dev_t *ieee80211_dev,
404 ieee80211_key_config_t *key_conf, bool insert)
405{
406 assert(ieee80211_dev);
407
408 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
409
410 if(insert) {
411 assert(key_conf);
412
413 uint32_t key[5];
414 uint32_t key_type;
415 uint32_t reg_ptr, mic_reg_ptr;
416 void *data_start;
417
418 nic_address_t bssid;
419 ieee80211_query_bssid(ieee80211_dev, &bssid);
420
421 switch (key_conf->suite) {
422 case IEEE80211_SECURITY_SUITE_WEP40:
423 key_type = AR9271_KEY_TABLE_TYPE_WEP40;
424 break;
425 case IEEE80211_SECURITY_SUITE_WEP104:
426 key_type = AR9271_KEY_TABLE_TYPE_WEP104;
427 break;
428 case IEEE80211_SECURITY_SUITE_TKIP:
429 key_type = AR9271_KEY_TABLE_TYPE_TKIP;
430 break;
431 case IEEE80211_SECURITY_SUITE_CCMP:
432 key_type = AR9271_KEY_TABLE_TYPE_CCMP;
433 break;
434 default:
435 key_type = -1;
436 }
437
438 uint8_t key_id =
439 (key_conf->flags & IEEE80211_KEY_FLAG_TYPE_PAIRWISE) ?
440 AR9271_STA_KEY_INDEX : key_conf->id;
441
442 reg_ptr = AR9271_KEY_TABLE(key_id);
443 mic_reg_ptr = AR9271_KEY_TABLE(key_id + 64);
444 data_start = (void *) key_conf->data;
445
446 key[0] = uint32_t_le2host(*((uint32_t *) data_start));
447 key[1] = uint16_t_le2host(*((uint16_t *) (data_start + 4)));
448 key[2] = uint32_t_le2host(*((uint32_t *) (data_start + 6)));
449 key[3] = uint16_t_le2host(*((uint16_t *) (data_start + 10)));
450 key[4] = uint32_t_le2host(*((uint32_t *) (data_start + 12)));
451
452 if ((key_conf->suite == IEEE80211_SECURITY_SUITE_WEP40) ||
453 (key_conf->suite == IEEE80211_SECURITY_SUITE_WEP104))
454 key[4] &= 0xFF;
455
456 wmi_reg_write(ar9271->htc_device, reg_ptr + 0, key[0]);
457 wmi_reg_write(ar9271->htc_device, reg_ptr + 4, key[1]);
458 wmi_reg_write(ar9271->htc_device, reg_ptr + 8, key[2]);
459 wmi_reg_write(ar9271->htc_device, reg_ptr + 12, key[3]);
460 wmi_reg_write(ar9271->htc_device, reg_ptr + 16, key[4]);
461 wmi_reg_write(ar9271->htc_device, reg_ptr + 20, key_type);
462
463 uint32_t macl;
464 uint32_t mach;
465 if (key_conf->flags & IEEE80211_KEY_FLAG_TYPE_PAIRWISE) {
466 data_start = (void *) bssid.address;
467 macl = uint32_t_le2host(*((uint32_t *) data_start));
468 mach = uint16_t_le2host(*((uint16_t *) (data_start + 4)));
469 } else {
470 macl = 0;
471 mach = 0;
472 }
473
474 macl >>= 1;
475 macl |= (mach & 1) << 31;
476 mach >>= 1;
477 mach |= 0x8000;
478
479 wmi_reg_write(ar9271->htc_device, reg_ptr + 24, macl);
480 wmi_reg_write(ar9271->htc_device, reg_ptr + 28, mach);
481
482 /* Setup MIC keys for TKIP. */
483 if (key_conf->suite == IEEE80211_SECURITY_SUITE_TKIP) {
484 uint32_t mic[5];
485 uint8_t *gen_mic = data_start + IEEE80211_TKIP_RX_MIC_OFFSET;
486 uint8_t *tx_mic;
487
488 if (key_conf->flags & IEEE80211_KEY_FLAG_TYPE_GROUP)
489 tx_mic = gen_mic;
490 else
491 tx_mic = data_start + IEEE80211_TKIP_TX_MIC_OFFSET;
492
493 mic[0] = uint32_t_le2host(*((uint32_t *) gen_mic));
494 mic[1] = uint16_t_le2host(*((uint16_t *) (tx_mic + 2))) & 0xFFFF;
495 mic[2] = uint32_t_le2host(*((uint32_t *) (gen_mic + 4)));
496 mic[3] = uint16_t_le2host(*((uint16_t *) tx_mic)) & 0xFFFF;
497 mic[4] = uint32_t_le2host(*((uint32_t *) (tx_mic + 4)));
498
499 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 0, mic[0]);
500 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 4, mic[1]);
501 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 8, mic[2]);
502 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 12, mic[3]);
503 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 16, mic[4]);
504 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 20,
505 AR9271_KEY_TABLE_TYPE_CLR);
506
507 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 24, 0);
508 wmi_reg_write(ar9271->htc_device, mic_reg_ptr + 28, 0);
509 }
510
511 if (key_conf->flags & IEEE80211_KEY_FLAG_TYPE_GROUP)
512 ieee80211_setup_key_confirm(ieee80211_dev, true);
513 } else {
514 /* TODO: Delete keys from device */
515 ieee80211_setup_key_confirm(ieee80211_dev, false);
516 }
517
518 return EOK;
519}
520
521static int ar9271_ieee80211_tx_handler(ieee80211_dev_t *ieee80211_dev,
522 void *buffer, size_t buffer_size)
523{
524 assert(ieee80211_dev);
525
526 size_t complete_size;
527 size_t offset;
528 void *complete_buffer;
529 int endpoint;
530
531 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
532
533 uint16_t frame_ctrl = *((uint16_t *) buffer);
534 if (ieee80211_is_data_frame(frame_ctrl)) {
535 offset = sizeof(htc_tx_data_header_t) +
536 sizeof(htc_frame_header_t);
537 complete_size = buffer_size + offset;
538 complete_buffer = malloc(complete_size);
539 memset(complete_buffer, 0, complete_size);
540
541 /*
542 * Because we handle just station mode yet, node ID and VIF ID
543 * are fixed.
544 */
545 htc_tx_data_header_t *data_header =
546 (htc_tx_data_header_t *)
547 (complete_buffer + sizeof(htc_frame_header_t));
548 data_header->data_type = HTC_DATA_NORMAL;
549 data_header->node_idx = 1;
550 data_header->vif_idx = 0;
551 data_header->cookie = 0;
552
553 if (ieee80211_query_using_key(ieee80211_dev)) {
554 data_header->keyix = AR9271_STA_KEY_INDEX;
555
556 int sec_suite =
557 ieee80211_get_pairwise_security(ieee80211_dev);
558
559 switch (sec_suite) {
560 case IEEE80211_SECURITY_SUITE_WEP40:
561 case IEEE80211_SECURITY_SUITE_WEP104:
562 data_header->key_type = AR9271_KEY_TYPE_WEP;
563 break;
564 case IEEE80211_SECURITY_SUITE_TKIP:
565 data_header->key_type = AR9271_KEY_TYPE_TKIP;
566 break;
567 case IEEE80211_SECURITY_SUITE_CCMP:
568 data_header->key_type = AR9271_KEY_TYPE_AES;
569 break;
570 }
571 } else {
572 data_header->key_type = 0;
573 data_header->keyix = 0xFF;
574 }
575
576 endpoint = ar9271->htc_device->endpoints.data_be_endpoint;
577 } else {
578 offset = sizeof(htc_tx_management_header_t) +
579 sizeof(htc_frame_header_t);
580 complete_size = buffer_size + offset;
581 complete_buffer = malloc(complete_size);
582 memset(complete_buffer, 0, complete_size);
583
584 /*
585 * Because we handle just station mode yet, node ID and VIF ID
586 * are fixed.
587 */
588 htc_tx_management_header_t *mgmt_header =
589 (htc_tx_management_header_t *)
590 (complete_buffer + sizeof(htc_frame_header_t));
591 mgmt_header->node_idx = 0;
592 mgmt_header->vif_idx = 0;
593 mgmt_header->cookie = 0;
594 mgmt_header->keyix = 0xFF;
595
596 endpoint = ar9271->htc_device->endpoints.mgmt_endpoint;
597 }
598
599 /* Copy IEEE802.11 data to new allocated buffer with HTC headers. */
600 memcpy(complete_buffer + offset, buffer, buffer_size);
601
602 htc_send_data_message(ar9271->htc_device, complete_buffer,
603 complete_size, endpoint);
604
605 free(complete_buffer);
606
607 return EOK;
608}
609
610static int ar9271_ieee80211_start(ieee80211_dev_t *ieee80211_dev)
611{
612 assert(ieee80211_dev);
613
614 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev);
615
616 wmi_send_command(ar9271->htc_device, WMI_FLUSH_RECV, NULL, 0, NULL);
617
618 int rc = hw_reset(ar9271);
619 if (rc != EOK) {
620 usb_log_error("Failed to do HW reset.\n");
621 return rc;
622 }
623
624 uint16_t htc_mode = host2uint16_t_be(1);
625 wmi_send_command(ar9271->htc_device, WMI_SET_MODE,
626 (uint8_t *) &htc_mode, sizeof(htc_mode), NULL);
627 wmi_send_command(ar9271->htc_device, WMI_ATH_INIT, NULL, 0, NULL);
628 wmi_send_command(ar9271->htc_device, WMI_START_RECV, NULL, 0, NULL);
629 wmi_send_command(ar9271->htc_device, WMI_ENABLE_INTR, NULL, 0, NULL);
630
631 rc = hw_rx_init(ar9271);
632 if (rc != EOK) {
633 usb_log_error("Failed to initialize RX.\n");
634 return rc;
635 }
636
637 /* Send capability message to target. */
638 htc_cap_msg_t cap_msg;
639 cap_msg.ampdu_limit = host2uint32_t_be(0xffff);
640 cap_msg.ampdu_subframes = 0xff;
641 cap_msg.enable_coex = 0;
642 cap_msg.tx_chainmask = 0x1;
643
644 wmi_send_command(ar9271->htc_device, WMI_TARGET_IC_UPDATE,
645 (uint8_t *) &cap_msg, sizeof(cap_msg), NULL);
646
647 rc = htc_init_new_vif(ar9271->htc_device);
648 if (rc != EOK) {
649 usb_log_error("Failed to initialize new VIF.\n");
650 return rc;
651 }
652
653 /* Add data polling fibril. */
654 fid_t fibril = fibril_create(ar9271_data_polling, ar9271);
655 if (fibril == 0)
656 return ENOMEM;
657
658 fibril_add_ready(fibril);
659
660 ar9271->starting_up = false;
661 ieee80211_set_ready(ieee80211_dev, true);
662
663 usb_log_info("Device fully initialized.\n");
664
665 return EOK;
666}
667
668static int ar9271_init(ar9271_t *ar9271, usb_device_t *usb_device, const usb_endpoint_description_t **endpoints)
669{
670 ar9271->starting_up = true;
671 ar9271->usb_device = usb_device;
672
673 fibril_mutex_initialize(&ar9271->ar9271_lock);
674
675 ar9271->ath_device = calloc(1, sizeof(ath_t));
676 if (!ar9271->ath_device) {
677 usb_log_error("Failed to allocate memory for ath device "
678 "structure.\n");
679 return ENOMEM;
680 }
681
682 int rc = ath_usb_init(ar9271->ath_device, usb_device, endpoints);
683 if (rc != EOK) {
684 free(ar9271->ath_device);
685 usb_log_error("Failed to initialize ath device.\n");
686 return rc;
687 }
688
689 /* IEEE 802.11 framework structure initialization. */
690 ar9271->ieee80211_dev = ieee80211_device_create();
691 if (!ar9271->ieee80211_dev) {
692 free(ar9271->ath_device);
693 usb_log_error("Failed to allocate memory for IEEE80211 device "
694 "structure.\n");
695 return ENOMEM;
696 }
697
698 rc = ieee80211_device_init(ar9271->ieee80211_dev, ar9271->ddf_dev);
699 if (rc != EOK) {
700 free(ar9271->ieee80211_dev);
701 free(ar9271->ath_device);
702 usb_log_error("Failed to initialize IEEE80211 device structure."
703 "\n");
704 return rc;
705 }
706
707 ieee80211_set_specific(ar9271->ieee80211_dev, ar9271);
708
709 /* HTC device structure initialization. */
710 ar9271->htc_device = calloc(1, sizeof(htc_device_t));
711 if (!ar9271->htc_device) {
712 free(ar9271->ieee80211_dev);
713 free(ar9271->ath_device);
714 usb_log_error("Failed to allocate memory for HTC device "
715 "structure.\n");
716 return ENOMEM;
717 }
718
719 rc = htc_device_init(ar9271->ath_device, ar9271->ieee80211_dev,
720 ar9271->htc_device);
721 if (rc != EOK) {
722 free(ar9271->htc_device);
723 free(ar9271->ieee80211_dev);
724 free(ar9271->ath_device);
725 usb_log_error("Failed to initialize HTC device structure.\n");
726 return rc;
727 }
728
729 return EOK;
730}
731
732/** Upload firmware to WiFi device.
733 *
734 * @param ar9271 AR9271 device structure
735 *
736 * @return EOK if succeed, error code otherwise
737 *
738 */
739static int ar9271_upload_fw(ar9271_t *ar9271)
740{
741 usb_device_t *usb_device = ar9271->usb_device;
742
743 /* TODO: Set by maximum packet size in pipe. */
744 static const size_t MAX_TRANSFER_SIZE = 512;
745
746 /* Load FW from file. */
747 FILE *fw_file = fopen(FIRMWARE_FILENAME, "rb");
748 if (fw_file == NULL) {
749 usb_log_error("Failed opening file with firmware.\n");
750 return ENOENT;
751 }
752
753 fseek(fw_file, 0, SEEK_END);
754 uint64_t file_size = ftell(fw_file);
755 fseek(fw_file, 0, SEEK_SET);
756
757 void *fw_data = malloc(file_size);
758 if (fw_data == NULL) {
759 fclose(fw_file);
760 usb_log_error("Failed allocating memory for firmware.\n");
761 return ENOMEM;
762 }
763
764 fread(fw_data, file_size, 1, fw_file);
765 fclose(fw_file);
766
767 /* Upload FW to device. */
768 uint64_t remain_size = file_size;
769 uint32_t current_addr = AR9271_FW_ADDRESS;
770 uint8_t *current_data = fw_data;
771 uint8_t *buffer = malloc(MAX_TRANSFER_SIZE);
772
773 while (remain_size > 0) {
774 size_t chunk_size = min(remain_size, MAX_TRANSFER_SIZE);
775 memcpy(buffer, current_data, chunk_size);
776 usb_pipe_t *ctrl_pipe = usb_device_get_default_pipe(usb_device);
777 int rc = usb_control_request_set(ctrl_pipe,
778 USB_REQUEST_TYPE_VENDOR,
779 USB_REQUEST_RECIPIENT_DEVICE,
780 AR9271_FW_DOWNLOAD,
781 uint16_host2usb(current_addr >> 8),
782 0, buffer, chunk_size);
783 if (rc != EOK) {
784 free(fw_data);
785 free(buffer);
786 usb_log_error("Error while uploading firmware. "
787 "Error: %s\n", str_error_name(rc));
788 return rc;
789 }
790
791 remain_size -= chunk_size;
792 current_addr += chunk_size;
793 current_data += chunk_size;
794 }
795
796 free(fw_data);
797 free(buffer);
798
799 /*
800 * Send command that firmware is successfully uploaded.
801 * This should initiate creating confirmation message in
802 * device side buffer which we will check in htc_check_ready function.
803 */
804 usb_pipe_t *ctrl_pipe = usb_device_get_default_pipe(usb_device);
805 int rc = usb_control_request_set(ctrl_pipe,
806 USB_REQUEST_TYPE_VENDOR,
807 USB_REQUEST_RECIPIENT_DEVICE,
808 AR9271_FW_DOWNLOAD_COMP,
809 uint16_host2usb(AR9271_FW_OFFSET >> 8),
810 0, NULL, 0);
811
812 if (rc != EOK) {
813 usb_log_error("IO error when sending fw upload confirmation "
814 "message.\n");
815 return rc;
816 }
817
818 usb_log_info("Firmware uploaded successfully.\n");
819
820 /* Wait until firmware is ready - wait for 1 second to be sure. */
821 async_sleep(1);
822
823 return rc;
824}
825
826/** Create driver data structure.
827 *
828 * @param dev The device structure
829 *
830 * @return Intialized device data structure or NULL if error occured
831 */
832static ar9271_t *ar9271_create_dev_data(ddf_dev_t *dev)
833{
834 /* USB framework initialization. */
835 const char *err_msg = NULL;
836 int rc = usb_device_create_ddf(dev, endpoints, &err_msg);
837 if (rc != EOK) {
838 usb_log_error("Failed to create USB device: %s, "
839 "ERR_NUM = %s\n", err_msg, str_error_name(rc));
840 return NULL;
841 }
842
843 /* AR9271 structure initialization. */
844 ar9271_t *ar9271 = calloc(1, sizeof(ar9271_t));
845 if (!ar9271) {
846 usb_log_error("Failed to allocate memory for device "
847 "structure.\n");
848 return NULL;
849 }
850
851 ar9271->ddf_dev = dev;
852
853 rc = ar9271_init(ar9271, usb_device_get(dev), endpoints);
854 if (rc != EOK) {
855 free(ar9271);
856 usb_log_error("Failed to initialize AR9271 structure: %s\n",
857 str_error_name(rc));
858 return NULL;
859 }
860
861 return ar9271;
862}
863
864/** Clean up the ar9271 device structure.
865 *
866 * @param dev The device structure.
867 */
868static void ar9271_delete_dev_data(ar9271_t *ar9271)
869{
870 assert(ar9271);
871
872 // TODO
873}
874
875/** Probe and initialize the newly added device.
876 *
877 * @param dev The device structure.
878 *
879 * @return EOK if succeed, error code otherwise
880 */
881static int ar9271_add_device(ddf_dev_t *dev)
882{
883 assert(dev);
884
885 /* Allocate driver data for the device. */
886 ar9271_t *ar9271 = ar9271_create_dev_data(dev);
887 if (ar9271 == NULL) {
888 usb_log_error("Unable to allocate device softstate.\n");
889 return ENOMEM;
890 }
891
892 usb_log_info("HelenOS AR9271 device initialized.\n");
893
894 /* Upload AR9271 firmware. */
895 ar9271_upload_fw(ar9271);
896
897 /* Initialize AR9271 HTC services. */
898 int rc = htc_init(ar9271->htc_device);
899 if (rc != EOK) {
900 ar9271_delete_dev_data(ar9271);
901 usb_log_error("HTC initialization failed.\n");
902 return rc;
903 }
904
905 /* Initialize AR9271 HW. */
906 rc = hw_init(ar9271);
907 if (rc != EOK) {
908 ar9271_delete_dev_data(ar9271);
909 usb_log_error("HW initialization failed.\n");
910 return rc;
911 }
912
913 /* Initialize AR9271 IEEE 802.11 framework. */
914 rc = ieee80211_init(ar9271->ieee80211_dev, &ar9271_ieee80211_ops,
915 &ar9271_ieee80211_iface, &ar9271_ieee80211_nic_iface,
916 &ar9271_ieee80211_dev_ops);
917 if (rc != EOK) {
918 ar9271_delete_dev_data(ar9271);
919 usb_log_error("Failed to initialize IEEE80211 framework.\n");
920 return rc;
921 }
922
923 nic_set_filtering_change_handlers(nic_get_from_ddf_dev(dev),
924 ar9271_on_unicast_mode_change, ar9271_on_multicast_mode_change,
925 ar9271_on_broadcast_mode_change, NULL, NULL);
926
927 usb_log_info("HelenOS AR9271 added device.\n");
928
929 return EOK;
930}
931
932int main(void)
933{
934 log_init(NAME);
935
936 if (nic_driver_init(NAME) != EOK)
937 return 1;
938
939 usb_log_info("HelenOS AR9271 driver started.\n");
940
941 return ddf_driver_main(&ar9271_driver);
942}
Note: See TracBrowser for help on using the repository browser.