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