Index: boot/Makefile
===================================================================
--- boot/Makefile	(revision 8c7d5adf6864144540bbcdd88ca84f925dab4e02)
+++ boot/Makefile	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -115,4 +115,9 @@
 		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$file_dir/$$file_name/$$file_name.dev" "$(DIST_PATH)/$(DRVS_PATH)/$$file_name/" ; \
 	done
+	for file in $(RD_DRV_FW) ; do \
+		file_dir="`dirname "$$file"`" ; \
+		file_name="`basename "$$file"`" ; \
+		cp "$(USPACE_PATH)/$(DRVS_PATH)/$$file_dir/$$file_name/$$file_name.fw" "$(DIST_PATH)/$(DRVS_PATH)/$$file_name/" ; \
+	done
 	if ls $(DIST_OVERLAY_PATH)/* >/dev/null; then \
 		cp -r -L $(DIST_OVERLAY_PATH)/* "$(DIST_PATH)"; \
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision 8c7d5adf6864144540bbcdd88ca84f925dab4e02)
+++ boot/arch/amd64/Makefile.inc	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -57,8 +57,12 @@
 	bus/usb/usbmast \
 	bus/usb/usbmid \
-	bus/usb/vhc
+	bus/usb/vhc \
+	bus/usb/ar9271
 
 RD_DRV_CFG += \
 	bus/isa
+	
+RD_DRV_FW += \
+    bus/usb/ar9271
 
 RD_APPS_ESSENTIAL += \
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 8c7d5adf6864144540bbcdd88ca84f925dab4e02)
+++ uspace/Makefile	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -159,4 +159,5 @@
 	drv/bus/usb/usbmid \
 	drv/bus/usb/vhc \
+	drv/bus/usb/ar9271 \
 	drv/nic/ne2k \
 	drv/nic/e1k \
Index: uspace/Makefile.common
===================================================================
--- uspace/Makefile.common	(revision 8c7d5adf6864144540bbcdd88ca84f925dab4e02)
+++ uspace/Makefile.common	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -258,5 +258,5 @@
 
 ifeq ($(CONFIG_DEBUG),y)
-	GCC_CFLAGS += -Werror
+#	GCC_CFLAGS += -Werror
 	ICC_CFLAGS += -Werror
 endif
Index: uspace/drv/bus/usb/ar9271/Makefile
===================================================================
--- uspace/drv/bus/usb/ar9271/Makefile	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/Makefile	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,53 @@
+#
+# Copyright (c) 2014 Jan Kolarik
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../../..
+
+LIBS = \
+	$(LIBUSBDEV_PREFIX)/libusbdev.a \
+	$(LIBUSB_PREFIX)/libusb.a \
+	$(LIBDRV_PREFIX)/libdrv.a \
+	$(LIBNIC_PREFIX)/libnic.a
+	
+EXTRA_CFLAGS += \
+	-I. \
+	-I$(LIBUSB_PREFIX)/include \
+	-I$(LIBUSBDEV_PREFIX)/include \
+	-I$(LIBDRV_PREFIX)/include \
+	-I$(LIBNIC_PREFIX)/include
+	
+BINARY = ar9271
+
+SOURCES = \
+	ath_usb.c \
+	hw.c \
+	wmi.c \
+	htc.c \
+	ar9271.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/ar9271/ar9271.c
===================================================================
--- uspace/drv/bus/usb/ar9271/ar9271.c	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/ar9271.c	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 2014 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file ar9271.c
+ *
+ * Driver for AR9271 USB WiFi dongle.
+ *
+ */
+
+#include <usb/classes/classes.h>
+#include <usb/dev/request.h>
+#include <usb/dev/poll.h>
+#include <usb/debug.h>
+#include <stdio.h>
+#include <ddf/interrupt.h>
+#include <nic.h>
+#include <macros.h>
+
+#include "ath_usb.h"
+#include "wmi.h"
+#include "hw.h"
+#include "ar9271.h"
+
+#define NAME "ar9271"
+#define FIRMWARE_FILENAME "/drv/ar9271/ar9271.fw"
+
+const usb_endpoint_description_t usb_ar9271_out_bulk_endpoint_description = {
+	.transfer_type = USB_TRANSFER_BULK,
+	.direction = USB_DIRECTION_OUT,
+	.interface_class = USB_CLASS_VENDOR_SPECIFIC,
+	.interface_subclass = 0x0,
+	.interface_protocol = 0x0,
+	.flags = 0
+};
+
+const usb_endpoint_description_t usb_ar9271_in_bulk_endpoint_description = {
+	.transfer_type = USB_TRANSFER_BULK,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_VENDOR_SPECIFIC,
+	.interface_subclass = 0x0,
+	.interface_protocol = 0x0,
+	.flags = 0
+};
+
+const usb_endpoint_description_t usb_ar9271_in_int_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_VENDOR_SPECIFIC,
+	.interface_subclass = 0x0,
+	.interface_protocol = 0x0,
+	.flags = 0
+};
+
+const usb_endpoint_description_t usb_ar9271_out_int_endpoint_description = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_OUT,
+	.interface_class = USB_CLASS_VENDOR_SPECIFIC,
+	.interface_subclass = 0x0,
+	.interface_protocol = 0x0,
+	.flags = 0
+};
+
+/* Array of endpoints expected on the device, NULL terminated. */
+const usb_endpoint_description_t *endpoints[] = {
+	&usb_ar9271_out_bulk_endpoint_description,
+	&usb_ar9271_in_bulk_endpoint_description,
+        &usb_ar9271_in_int_endpoint_description,
+        &usb_ar9271_out_int_endpoint_description,
+	NULL
+};
+
+/** Network interface options for AR9271 driver. */
+static nic_iface_t ar9271_nic_iface;
+
+/** Basic device operations for AR9271 NIC driver. */
+static ddf_dev_ops_t ar9271_nic_dev_ops;
+
+/** Basic driver operations for AR9271 NIC driver. */
+static driver_ops_t ar9271_nic_driver_ops;
+
+/* Callback when new device is to be controlled by this driver. */
+static int ar9271_add_device(ddf_dev_t *);
+
+static driver_ops_t ar9271_driver_ops = {
+	.dev_add = ar9271_add_device
+};
+
+static driver_t ar9271_driver = {
+	.name = NAME,
+	.driver_ops = &ar9271_driver_ops
+};
+
+/* The default implementation callbacks */
+static int ar9271_on_activating(nic_t *);
+static int ar9271_on_stopping(nic_t *);
+static void ar9271_send_frame(nic_t *, void *, size_t);
+
+static int ar9271_init(ar9271_t *ar9271, usb_device_t *usb_device)
+{
+	ar9271->usb_device = usb_device;
+	
+	ath_t *ath_device = malloc(sizeof(ath_t));
+	if (!ath_device) {
+		usb_log_error("Failed to allocate memory for ath device "
+		    "structure.\n");
+		return ENOMEM;
+	}
+	
+	int rc = ath_usb_init(ath_device, usb_device);
+	if(rc != EOK) {
+		free(ath_device);
+		usb_log_error("Failed to initialize ath device.\n");
+		return EINVAL;
+	}
+		
+	/* HTC device structure initialization. */
+	ar9271->htc_device = malloc(sizeof(htc_device_t));
+	if(!ar9271->htc_device) {
+		free(ath_device);
+		usb_log_error("Failed to allocate memory for HTC device "
+		    "structure.\n");
+		return ENOMEM;
+	}
+	
+	memset(ar9271->htc_device, 0, sizeof(htc_device_t));
+        
+	rc = htc_device_init(ath_device, ar9271->htc_device);
+	if(rc != EOK) {
+		free(ar9271->htc_device);
+		free(ath_device);
+		usb_log_error("Failed to initialize HTC device.\n");
+		return EINVAL;
+	}
+	
+	return EOK;
+}
+
+/**
+ * Upload firmware to WiFi device.
+ * 
+ * @param ar9271 AR9271 device structure
+ * 
+ * @return EOK if succeed, negative error code otherwise
+ */
+static int ar9271_upload_fw(ar9271_t *ar9271)
+{
+	int rc;
+	
+	usb_device_t *usb_device = ar9271->usb_device;
+        
+        /* TODO: Set by maximum packet size in pipe. */
+	static const size_t MAX_TRANSFER_SIZE = 512;
+	
+	/* Load FW from file. */
+	FILE *fw_file = fopen(FIRMWARE_FILENAME, "rb");
+	if (fw_file == NULL) {
+		usb_log_error("Failed opening file with firmware.\n");
+		return ENOENT;
+	}
+	
+	fseek(fw_file, 0, SEEK_END);
+	uint64_t file_size = ftell(fw_file);
+	fseek(fw_file, 0, SEEK_SET);
+	
+	void *fw_data = malloc(file_size);
+	if(fw_data == NULL) {
+		fclose(fw_file);
+		usb_log_error("Failed allocating memory for firmware.\n");
+		return ENOMEM;
+	}
+
+	fread(fw_data, file_size, 1, fw_file);
+	fclose(fw_file);
+	
+	usb_log_info("Firmware loaded successfully.\n");
+	
+	/* Upload FW to device. */
+	uint64_t remain_size = file_size;
+	uint32_t current_addr = AR9271_FW_ADDRESS;
+	uint8_t *current_data = fw_data;
+	uint8_t *buffer = malloc(MAX_TRANSFER_SIZE);
+	while(remain_size > 0) {
+		size_t chunk_size = min(remain_size, MAX_TRANSFER_SIZE);
+		memcpy(buffer, current_data, chunk_size);
+		rc = usb_control_request_set(&usb_device->ctrl_pipe,
+		    USB_REQUEST_TYPE_VENDOR,
+		    USB_REQUEST_RECIPIENT_DEVICE,
+		    AR9271_FW_DOWNLOAD,
+		    uint16_host2usb(current_addr >> 8),
+		    0, buffer, chunk_size);
+		if(rc != EOK) {
+			free(fw_data);
+			free(buffer);
+			usb_log_error("Error while uploading firmware. "
+			    "Error: %d\n", rc);
+			return rc;
+		}
+		
+		remain_size -= chunk_size;
+		current_addr += chunk_size;
+		current_data += chunk_size;
+	}
+	
+	free(fw_data);
+	free(buffer);
+	
+	/* Send command that firmware is successfully uploaded. 
+         * This should initiate creating confirmation message in
+         * device side buffer which we will check in htc_check_ready function.
+         */
+	rc = usb_control_request_set(&usb_device->ctrl_pipe,
+	    USB_REQUEST_TYPE_VENDOR,
+	    USB_REQUEST_RECIPIENT_DEVICE,
+	    AR9271_FW_DOWNLOAD_COMP,
+	    uint16_host2usb(AR9271_FW_OFFSET >> 8),
+	    0, NULL, 0);
+	
+	if(rc != EOK) {
+		usb_log_error("IO error when sending fw upload confirmation "
+                        "message.\n");
+		return rc;
+	}
+	
+	usb_log_info("Firmware uploaded successfully.\n");
+	
+	/* Wait until firmware is ready - wait for 1 second to be sure. */
+	sleep(1);
+	
+	return rc;
+}
+
+/** Get MAC address of the AR9271 adapter
+ *
+ *  @param ar9271 The AR9271 device
+ *  @param address The place to store the address
+ *
+ *  @return EOK if succeed, negative error code otherwise
+ */
+inline static void ar9271_hw_get_addr(ar9271_t *ar9271, nic_address_t *addr)
+{
+	assert(ar9271);
+	assert(addr);
+	
+	fibril_mutex_lock(&ar9271->htc_device->rx_lock);
+	
+	uint32_t *mac0_dest = (uint32_t *)(addr->address);
+	uint16_t *mac4_dest = (uint16_t *)(addr->address + 4);
+	
+	void *ar9271_mac_addr = 0;
+
+	/* Read MAC address from the i/o (4byte + 2byte reads) */
+	// TODO: Now just testing register address
+	/*
+	usb_log_info("Trying to get some testing register from device.\n");
+	
+	uint32_t result;
+	int rc = wmi_reg_read(ar9271->usb_device, 
+	    0x50040,
+	    //AR9271_MAC_REG_OFFSET | AR9271_MAC_PCU_STA_ADDR_L32, 
+	    &result);
+	if(rc != EOK) {
+		usb_log_info("Failed to read registry value. Error: %d\n", rc);
+		return rc;
+	}
+	
+	usb_log_info("Registry value: %x\n", result);
+	 */
+	
+	fibril_mutex_unlock(&ar9271->htc_device->rx_lock);
+}
+
+/** Force receiving all frames in the receive buffer
+ *
+ * @param nic NIC data
+ */
+static void ar9271_poll(nic_t *nic)
+{
+	assert(nic);
+}
+
+/** Set polling mode
+ *
+ * @param device  Device to set
+ * @param mode    Mode to set
+ * @param period  Period for NIC_POLL_PERIODIC
+ *
+ * @return EOK if succeed, ENOTSUP if the mode is not supported
+ */
+static int ar9271_poll_mode_change(nic_t *nic, nic_poll_mode_t mode,
+    const struct timeval *period)
+{
+	assert(nic);
+	return EOK;
+}
+
+/** Set multicast frames acceptance mode
+ *
+ * @param nic      NIC device to update
+ * @param mode     Mode to set
+ * @param addr     Address list (used in mode = NIC_MULTICAST_LIST)
+ * @param addr_cnt Length of address list (used in mode = NIC_MULTICAST_LIST)
+ *
+ * @return EOK if succeed, negative error code otherwise
+ */
+static int ar9271_on_multicast_mode_change(nic_t *nic, 
+    nic_multicast_mode_t mode, const nic_address_t *addr, size_t addr_cnt)
+{
+	assert(nic);
+	return EOK;
+}
+
+/** Set unicast frames acceptance mode
+ *
+ * @param nic      NIC device to update
+ * @param mode     Mode to set
+ * @param addr     Address list (used in mode = NIC_MULTICAST_LIST)
+ * @param addr_cnt Length of address list (used in mode = NIC_MULTICAST_LIST)
+ *
+ * @return EOK if succeed, negative error code otherwise
+ */
+static int ar9271_on_unicast_mode_change(nic_t *nic, nic_unicast_mode_t mode,
+    const nic_address_t *addr, size_t addr_cnt)
+{
+	assert(nic);
+	return EOK;
+}
+
+/** Set broadcast frames acceptance mode
+ *
+ * @param nic  NIC device to update
+ * @param mode Mode to set
+ *
+ * @return EOK if succeed, negative error code otherwise
+ */
+static int ar9271_on_broadcast_mode_change(nic_t *nic, 
+    nic_broadcast_mode_t mode)
+{
+	assert(nic);
+	return EOK;
+}
+
+/** Activate the device to receive and transmit frames
+ *
+ * @param nic NIC driver data
+ *
+ * @return EOK if activated successfully, negative error code otherwise
+ */
+static int ar9271_on_activating(nic_t *nic)
+{
+	assert(nic);
+	return EOK;
+}
+
+/** Callback for NIC_STATE_STOPPED change
+ *
+ * @param nic NIC driver data
+ *
+ * @return EOK if succeed, negative error code otherwise
+ */
+static int ar9271_on_stopping(nic_t *nic)
+{
+	assert(nic);
+	return EOK;
+}
+
+/** Send frame
+ *
+ * @param nic    NIC driver data structure
+ * @param data   Frame data
+ * @param size   Frame size in bytes
+ */
+static void ar9271_send_frame(nic_t *nic, void *data, size_t size)
+{
+	assert(nic);
+}
+
+/** Create driver data structure.
+ * 
+ *  @param dev The device structure
+ * 
+ *  @return Intialized device data structure or NULL if error occured
+ */
+static ar9271_t *ar9271_create_dev_data(ddf_dev_t *dev)
+{
+	/* USB framework initialization. */
+	usb_device_t *usb_device = calloc(1, sizeof(usb_device_t));
+	if (usb_device == NULL) {
+		usb_log_error("USB device structure allocation failed.\n");
+		return NULL;
+	}
+	
+	const char *err_msg = NULL;
+	int rc = usb_device_init(usb_device, dev, endpoints, &err_msg);
+	if(rc != EOK) {
+		free(usb_device);
+		usb_log_error("Failed to create USB device: %s, "
+		    "ERR_NUM = %d\n", err_msg, rc);
+		return NULL;
+	}
+	
+	/* AR9271 structure initialization. */
+	ar9271_t *ar9271 = malloc(sizeof(ar9271_t));
+	if (!ar9271) {
+		free(usb_device);
+		usb_log_error("Failed to allocate memory for device "
+		    "structure.\n");
+		return NULL;
+	}
+	
+	memset(ar9271, 0, sizeof(ar9271_t));
+	
+	rc = ar9271_init(ar9271, usb_device);
+	if(rc != EOK) {
+		free(ar9271);
+		free(usb_device);
+		usb_log_error("Failed to initialize AR9271 structure: %d\n", 
+			rc);
+		return NULL;
+	}
+	
+	/* NIC framework initialization. */
+	nic_t *nic = nic_create_and_bind(dev);
+	if (!nic) {
+		free(ar9271);
+		free(usb_device);
+		usb_log_error("Failed to create and bind NIC data.\n");
+		return NULL;
+	}
+	
+	nic_set_specific(nic, ar9271);
+	nic_set_send_frame_handler(nic, ar9271_send_frame);
+	nic_set_state_change_handlers(nic, ar9271_on_activating,
+	    NULL, ar9271_on_stopping);
+	nic_set_filtering_change_handlers(nic,
+	    ar9271_on_unicast_mode_change, ar9271_on_multicast_mode_change,
+	    ar9271_on_broadcast_mode_change, NULL, NULL);
+	nic_set_poll_handlers(nic, ar9271_poll_mode_change, ar9271_poll);
+	
+	return ar9271;
+}
+
+/** Clean up the ar9271 device structure.
+ *
+ * @param dev  The device structure.
+ */
+static void ar9271_delete_dev_data(ar9271_t *ar9271)
+{
+	assert(ar9271);
+	
+	// TODO
+}
+
+/** Probe and initialize the newly added device.
+ *
+ * @param dev The device structure.
+ *
+ * @return EOK if succeed, negative error code otherwise
+ */
+static int ar9271_add_device(ddf_dev_t *dev)
+{
+	assert(dev);
+	ddf_fun_t *fun;
+	
+	/* Allocate driver data for the device. */
+	ar9271_t *ar9271 = ar9271_create_dev_data(dev);
+	if (ar9271 == NULL) {
+		usb_log_error("Unable to allocate device softstate.\n");
+		return ENOMEM;
+	}
+	
+	usb_log_info("HelenOS AR9271 device initialized.\n");
+	
+	/* Upload AR9271 firmware. */
+	ar9271_upload_fw(ar9271);
+	
+	/* Initialize AR9271 HTC services. */
+	int rc = htc_init(ar9271->htc_device);
+	if(rc != EOK) {
+		ar9271_delete_dev_data(ar9271);
+		usb_log_error("HTC initialization failed.\n");
+		return rc;
+	}
+	
+	/* Initialize AR9271 HW. */
+	rc = hw_init(ar9271);
+	if(rc != EOK) {
+		ar9271_delete_dev_data(ar9271);
+		usb_log_error("HW initialization failed.\n");
+		return rc;
+	}
+	
+	nic_t *nic = nic_get_from_ddf_dev(dev);
+	
+	/*
+	nic_address_t addr;
+	ar9271_hw_get_addr(ar9271, &addr);
+	rc = nic_report_address(nic, &addr);
+	
+	usb_log_info("Reported address.\n");
+	*/
+	
+	/* Create AR9271 function.*/
+	fun = ddf_fun_create(nic_get_ddf_dev(nic), fun_exposed, "port0");
+	if (fun == NULL) {
+		ar9271_delete_dev_data(ar9271);
+		usb_log_error("Failed creating device function.\n");
+	}
+	
+	nic_set_ddf_fun(nic, fun);
+	ddf_fun_set_ops(fun, &ar9271_nic_dev_ops);
+	
+	rc = ddf_fun_bind(fun);
+	if (rc != EOK) {
+		ddf_fun_destroy(fun);
+		ar9271_delete_dev_data(ar9271);
+		usb_log_error("Failed binding device function.\n");
+		return rc;
+	}
+	rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC);
+	if (rc != EOK) {
+		ddf_fun_unbind(fun);
+		ar9271_delete_dev_data(ar9271);
+		usb_log_error("Failed adding function to category.\n");
+		return rc;
+	}
+	
+	usb_log_info("HelenOS AR9271 added device.\n");
+	
+	return EOK;
+}
+
+int main(void)
+{
+	log_init(NAME);
+	
+	if (nic_driver_init(NAME) != EOK)
+		return 1;
+	
+	nic_driver_implement(&ar9271_nic_driver_ops, &ar9271_nic_dev_ops,
+	    &ar9271_nic_iface);
+
+	usb_log_info("HelenOS AR9271 driver started.\n");
+
+	return ddf_driver_main(&ar9271_driver);
+}
Index: uspace/drv/bus/usb/ar9271/ar9271.h
===================================================================
--- uspace/drv/bus/usb/ar9271/ar9271.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/ar9271.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file ar9271.h
+ *
+ * Header file for AR9271 USB WiFi dongle.
+ *
+ */
+
+#ifndef AR9271_H_
+#define AR9271_H_
+
+#include <usb/dev/driver.h>
+
+#include "htc.h"
+
+/** AR9271 Registers */
+typedef enum {
+	/* Reset MAC interface */
+	AR9271_RC = 0x4000,
+	AR9271_RC_AHB = 0x00000001,
+    
+	/* Wakeup related registers */
+	AR9271_RTC_RESET = 0x7040,
+	AR9271_RTC_STATUS = 0x7044,
+	AR9271_RTC_STATUS_MASK = 0x0000000F,
+	AR9271_RTC_STATUS_ON = 0x00000002,
+	AR9271_RTC_FORCE_WAKE = 0x704C,
+	AR9271_RTC_FORCE_WAKE_ENABLE = 0x00000001,
+	AR9271_RTC_FORCE_WAKE_ON_INT = 0x00000002,
+    
+	/* FW Addresses */
+	AR9271_FW_ADDRESS =	0x501000,
+	AR9271_FW_OFFSET =	0x903000,
+	
+	/* MAC Registers */
+	AR9271_MAC_REG_OFFSET = 0x10000000, /**< MAC Registers offset */
+			
+	AR9271_MAC_PCU_STA_ADDR_L32 = 0x8000, /**< STA Address Lower 32 Bits */
+	AR9271_MAC_PCU_STA_ADDR_U16 = 0x8004, /**< STA Address Upper 16 Bits */
+	AR9271_MAC_PCU_BSSID_L32 = 0x8008, /**< BSSID Lower 32 Bits */
+	AR9271_MAC_PCU_BSSID_U16 = 0x800C, /**< BSSID Upper 16 Bits */
+} ar9271_registers_t;
+
+/** AR9271 Requests */
+typedef enum {
+	AR9271_FW_DOWNLOAD = 0x30,
+	AR9271_FW_DOWNLOAD_COMP = 0x31,
+} ar9271_requests_t;
+
+/** AR9271 device data */
+typedef struct {
+	/** USB device data */
+	usb_device_t *usb_device;
+	
+	/** HTC device data */
+	htc_device_t *htc_device;
+} ar9271_t;
+
+#endif
Index: uspace/drv/bus/usb/ar9271/ar9271.ma
===================================================================
--- uspace/drv/bus/usb/ar9271/ar9271.ma	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/ar9271.ma	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,1 @@
+90 usb&vendor=0x0cf3&product=0x9271
Index: uspace/drv/bus/usb/ar9271/ath.h
===================================================================
--- uspace/drv/bus/usb/ar9271/ath.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/ath.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file ath.h
+ *
+ * Atheros generic wifi device functions definitions.
+ *
+ */
+
+#ifndef ATHEROS_ATH_H
+#define	ATHEROS_ATH_H
+
+struct ath;
+
+/** Atheros wifi operations. */
+typedef struct {
+	int (*send_ctrl_message)(struct ath *, void *, size_t);
+	int (*read_ctrl_message)(struct ath *, void *, size_t, size_t *);
+	int (*send_data_message)(struct ath *, void *, size_t);
+	int (*read_data_message)(struct ath *, void *, size_t, size_t *);
+} ath_ops_t;
+
+/** Atheros wifi device structure */
+typedef struct ath {
+	/** Implementation specific data. */
+	void *specific_data;
+	
+	/** Generic Atheros wifi operations. */
+	const ath_ops_t *ops;
+} ath_t;
+
+#endif	/* ATHEROS_ATH_H */
Index: uspace/drv/bus/usb/ar9271/ath_usb.c
===================================================================
--- uspace/drv/bus/usb/ar9271/ath_usb.c	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/ath_usb.c	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2015 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file ath_usb.c
+ *
+ * Implementation of Atheros USB wifi device functions.
+ *
+ */
+
+#include <usb/dev/pipes.h>
+#include <usb/debug.h>
+#include <malloc.h>
+
+#include "ath_usb.h"
+
+static int ath_usb_send_ctrl_message(ath_t *ath, void *buffer, 
+	size_t buffer_size);
+
+static int ath_usb_read_ctrl_message(ath_t *ath, void *buffer, 
+	size_t buffer_size, size_t *transferred_size);
+
+static int ath_usb_send_data_message(ath_t *ath, void *buffer, 
+	size_t buffer_size);
+
+static int ath_usb_read_data_message(ath_t *ath, void *buffer, 
+	size_t buffer_size, size_t *transferred_size);
+
+static ath_ops_t ath_usb_ops = {
+	.send_ctrl_message = ath_usb_send_ctrl_message,
+	.read_ctrl_message = ath_usb_read_ctrl_message,
+	.send_data_message = ath_usb_send_data_message,
+	.read_data_message = ath_usb_read_data_message
+};
+
+/**
+ * Initialize Atheros WiFi USB device.
+ * 
+ * @param ath Generic Atheros WiFi device structure.
+ * @param usb_device Connected USB device.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int ath_usb_init(ath_t *ath, usb_device_t *usb_device)
+{
+	ath_usb_t *ath_usb = malloc(sizeof(ath_usb_t));
+	if (!ath_usb) {
+		usb_log_error("Failed to allocate memory for ath usb device "
+		    "structure.\n");
+		return ENOMEM;
+	}
+	
+	ath_usb->usb_device = usb_device;
+	
+	/* TODO: Assign by iterating over pipes. */
+	ath_usb->output_data_pipe_number = 0;
+	ath_usb->input_data_pipe_number = 1;
+	ath_usb->input_ctrl_pipe_number = 2;
+	ath_usb->output_ctrl_pipe_number = 3;
+	
+	ath->specific_data = ath_usb;
+	ath->ops = &ath_usb_ops;
+	
+	return EOK;
+}
+
+/**
+ * Send control message.
+ * 
+ * @param ath Generic Atheros WiFi device structure. 
+ * @param buffer Buffer with data to send.
+ * @param buffer_size Buffer size.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+static int ath_usb_send_ctrl_message(ath_t *ath, void *buffer, 
+	size_t buffer_size)
+{
+	ath_usb_t *ath_usb = (ath_usb_t *) ath->specific_data;
+	usb_pipe_t *pipe = 
+		&ath_usb->usb_device->pipes[ath_usb->output_ctrl_pipe_number].
+		pipe;
+	
+	return usb_pipe_write(pipe, buffer, buffer_size);
+}
+
+/**
+ * Read control message.
+ * 
+ * @param ath Generic Atheros WiFi device structure. 
+ * @param buffer Buffer with data to send.
+ * @param buffer_size Buffer size.
+ * @param transferred_size Real size of read data.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+static int ath_usb_read_ctrl_message(ath_t *ath, void *buffer, 
+	size_t buffer_size, size_t *transferred_size)
+{
+	ath_usb_t *ath_usb = (ath_usb_t *) ath->specific_data;
+	usb_pipe_t *pipe = 
+		&ath_usb->usb_device->pipes[ath_usb->input_ctrl_pipe_number].
+		pipe;
+	
+	return usb_pipe_read(pipe, buffer, buffer_size, transferred_size);
+}
+
+/**
+ * Send data message.
+ * 
+ * @param ath Generic Atheros WiFi device structure. 
+ * @param buffer Buffer with data to send.
+ * @param buffer_size Buffer size.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+static int ath_usb_send_data_message(ath_t *ath, void *buffer, 
+	size_t buffer_size)
+{
+	ath_usb_t *ath_usb = (ath_usb_t *) ath->specific_data;
+	usb_pipe_t *pipe = 
+		&ath_usb->usb_device->pipes[ath_usb->output_data_pipe_number].
+		pipe;
+	
+	return usb_pipe_write(pipe, buffer, buffer_size);
+}
+
+/**
+ * Read data message.
+ * 
+ * @param ath Generic Atheros WiFi device structure. 
+ * @param buffer Buffer with data to send.
+ * @param buffer_size Buffer size.
+ * @param transferred_size Real size of read data.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+static int ath_usb_read_data_message(ath_t *ath, void *buffer, 
+	size_t buffer_size, size_t *transferred_size)
+{
+	ath_usb_t *ath_usb = (ath_usb_t *) ath->specific_data;
+	usb_pipe_t *pipe = 
+		&ath_usb->usb_device->pipes[ath_usb->input_data_pipe_number].
+		pipe;
+	
+	return usb_pipe_read(pipe, buffer, buffer_size, transferred_size);
+}
Index: uspace/drv/bus/usb/ar9271/ath_usb.h
===================================================================
--- uspace/drv/bus/usb/ar9271/ath_usb.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/ath_usb.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file ath_usb.h
+ *
+ * Definitions of Atheros USB wifi device functions.
+ *
+ */
+
+#ifndef ATHEROS_ATH_USB_H
+#define	ATHEROS_ATH_USB_H
+
+#include <usb/dev/driver.h>
+
+#include "ath.h"
+
+/** Atheros USB wifi device structure */
+typedef struct {
+	/** USB pipes indexes */
+	int input_ctrl_pipe_number;
+	int output_ctrl_pipe_number;
+	int input_data_pipe_number;
+	int output_data_pipe_number;
+	
+	/** Pointer to connected USB device. */
+	usb_device_t *usb_device;
+} ath_usb_t;
+
+extern int ath_usb_init(ath_t *ath, usb_device_t *usb_device);
+
+#endif	/* ATHEROS_ATH_USB_H */
Index: uspace/drv/bus/usb/ar9271/htc.c
===================================================================
--- uspace/drv/bus/usb/ar9271/htc.c	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/htc.c	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2014 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file htc.c
+ *
+ * Implementation of Atheros HTC communication.
+ *
+ */
+
+#include <usb/debug.h>
+#include <byteorder.h>
+
+#include "wmi.h"
+#include "htc.h"
+
+#define MAX_RESP_LEN 64
+
+/**
+ * HTC download pipes mapping.
+ * 
+ * @param service_id Identification of WMI service.
+ * 
+ * @return Number of pipe used for this service.
+ */
+static inline uint8_t wmi_service_to_download_pipe(wmi_services_t service_id)
+{
+	switch(service_id) {
+		case WMI_CONTROL_SERVICE:
+			return 3;
+		default:
+			return 2;
+	}
+}
+
+/**
+ * HTC upload pipes mapping.
+ * 
+ * @param service_id Identification of WMI service.
+ * 
+ * @return Number of pipe used for this service.
+ */
+static inline uint8_t wmi_service_to_upload_pipe(wmi_services_t service_id)
+{
+	switch(service_id) {
+		case WMI_CONTROL_SERVICE:
+			return 4;
+		default:
+                        return 1;
+	}
+}
+
+/**
+ * Send HTC message to USB device.
+ * 
+ * @param htc_device HTC device structure.
+ * @param buffer Buffer with data to be sent to USB device (without HTC frame
+ *              header).
+ * @param buffer_size Size of buffer (including HTC frame header).
+ * @param endpoint_id Destination endpoint.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int htc_send_message(htc_device_t *htc_device, void *buffer, 
+	size_t buffer_size, uint8_t endpoint_id)
+{
+	htc_frame_header_t *htc_header = (htc_frame_header_t *) buffer;
+	htc_header->endpoint_id = endpoint_id;
+	htc_header->flags = 0;
+	htc_header->payload_length = host2uint16_t_be(buffer_size);
+	
+	ath_t *ath_device = htc_device->ath_device;
+	
+	return ath_device->ops->send_ctrl_message(ath_device, buffer, 
+		buffer_size);
+}
+
+/**
+ * Read HTC message from USB device.
+ * 
+ * @param htc_device HTC device structure.
+ * @param buffer Buffer where data from USB device will be stored.
+ * @param buffer_size Size of buffer.
+ * @param transferred_size Real size of read data.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int htc_read_message(htc_device_t *htc_device, void *buffer, 
+	size_t buffer_size, size_t *transferred_size)
+{
+	ath_t *ath_device = htc_device->ath_device;
+	
+	return ath_device->ops->read_ctrl_message(ath_device, buffer, 
+		buffer_size, transferred_size);
+}
+
+/**
+ * Initialize HTC service.
+ * 
+ * @param htc_device HTC device structure.
+ * @param service_id Identification of WMI service.
+ * @param response_endpoint_no HTC endpoint to be used for this service.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+static int htc_connect_service(htc_device_t *htc_device, 
+    wmi_services_t service_id, int *response_endpoint_no)
+{
+	size_t buffer_size = sizeof(htc_frame_header_t) + 
+		sizeof(htc_service_msg_t);
+	void *buffer = malloc(buffer_size);
+	
+	/* Fill service message structure. */
+	htc_service_msg_t *service_message = (htc_service_msg_t *)
+		((void *) buffer + sizeof(htc_frame_header_t));
+	service_message->service_id = 
+		host2uint16_t_be(service_id);
+	service_message->message_id = 
+		host2uint16_t_be(HTC_MESSAGE_CONNECT_SERVICE);
+	service_message->download_pipe_id = 
+		wmi_service_to_download_pipe(service_id);
+	service_message->upload_pipe_id = 
+		wmi_service_to_upload_pipe(service_id);
+	service_message->connection_flags = 0;
+	
+	/* Send HTC message. */
+	int rc = htc_send_message(htc_device, buffer, buffer_size,
+		htc_device->endpoints.ctrl_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Failed to send HTC message. Error: %d\n", rc);
+		return rc;
+	}
+	
+	free(buffer);
+	
+	buffer_size = MAX_RESP_LEN;
+	buffer = malloc(buffer_size);
+	
+	/* Read response from device. */
+	rc = htc_read_message(htc_device, buffer, buffer_size, NULL);
+	if(rc != EOK) {
+		usb_log_error("Failed to receive HTC service connect response. "
+			"Error: %d\n", rc);
+		return rc;
+	}
+	
+	htc_service_resp_msg_t *response_message = (htc_service_resp_msg_t *)
+		((void *) buffer + sizeof(htc_frame_header_t));
+
+	/* If service was successfully connected, write down HTC endpoint number
+	 * that will be used for communication. */
+	if(response_message->status == HTC_SERVICE_SUCCESS) {
+		*response_endpoint_no = response_message->endpoint_id;
+		return EOK;
+	} else {
+		usb_log_error("Failed to connect HTC service. "
+			"Message status: %d\n", response_message->status);
+		return rc;
+        }
+}
+
+/**
+ * HTC credits initialization message.
+ * 
+ * @param htc_device HTC device structure.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+static int htc_config_credits(htc_device_t *htc_device)
+{
+	size_t buffer_size = sizeof(htc_frame_header_t) + 50;
+	void *buffer = malloc(buffer_size);
+	htc_config_msg_t *config_message = (htc_config_msg_t *)
+		((void *) buffer + sizeof(htc_frame_header_t));
+	
+	config_message->message_id = 
+		host2uint16_t_be(HTC_MESSAGE_CONFIG);
+	/* Magic number to initialize device. */
+	config_message->credits = 33;
+	config_message->pipe_id = 1;
+
+	int rc = htc_send_message(htc_device, buffer, buffer_size,
+		htc_device->endpoints.ctrl_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Failed to send HTC config message. "
+			"Error: %d\n", rc);
+		return rc;
+	}
+	
+	free(buffer);
+	
+	buffer_size = MAX_RESP_LEN;
+	buffer = malloc(buffer_size);
+
+	/* Check response from device. */
+	rc = htc_read_message(htc_device, buffer, buffer_size, NULL);
+	if(rc != EOK) {
+		usb_log_error("Failed to receive HTC config response message. "
+			"Error: %d\n", rc);
+		return rc;
+	}
+
+	return rc;
+}
+
+/**
+ * HTC setup complete confirmation message.
+ * 
+ * @param htc_device HTC device structure.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+static int htc_complete_setup(htc_device_t *htc_device)
+{
+	size_t buffer_size = sizeof(htc_frame_header_t) + 50;
+	void *buffer = malloc(buffer_size);
+	htc_setup_complete_msg_t *complete_message = 
+		(htc_setup_complete_msg_t *)
+		((void *) buffer + sizeof(htc_frame_header_t));
+	
+	complete_message->message_id = 
+		host2uint16_t_be(HTC_MESSAGE_SETUP_COMPLETE);
+
+	int rc = htc_send_message(htc_device, buffer, buffer_size, 
+		htc_device->endpoints.ctrl_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Failed to send HTC setup complete message. "
+			"Error: %d\n", rc);
+		return rc;
+	}
+
+	return rc;
+}
+
+/**
+ * Try to fetch ready message from device.
+ * Checks that firmware was successfully loaded on device side.
+ * 
+ * @param htc_device HTC device structure.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+static int htc_check_ready(htc_device_t *htc_device)
+{
+	size_t buffer_size = MAX_RESP_LEN;
+	void *buffer = malloc(buffer_size);
+
+	int rc = htc_read_message(htc_device, buffer, buffer_size, NULL);
+	if(rc != EOK) {
+		usb_log_error("Failed to receive HTC check ready message. "
+			"Error: %d\n", rc);
+		return rc;
+	}
+
+	uint16_t *message_id = (uint16_t *) ((void *) buffer + 
+		sizeof(htc_frame_header_t));
+	if(uint16_t_be2host(*message_id) == HTC_MESSAGE_READY) {
+		return EOK;
+	} else {
+		return EINVAL;
+	}
+}
+
+/**
+ * Initialize HTC device structure.
+ * 
+ * @param ath_device Atheros WiFi device connected with this HTC device.
+ * @param htc_device HTC device structure to be initialized.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int htc_device_init(ath_t *ath_device, htc_device_t *htc_device)
+{
+	if(ath_device == NULL || htc_device == NULL) {
+		return EINVAL;
+	}
+	
+	fibril_mutex_initialize(&htc_device->rx_lock);
+	fibril_mutex_initialize(&htc_device->tx_lock);
+	
+	htc_device->endpoints.ctrl_endpoint = 0;
+	
+	htc_device->ath_device = ath_device;
+	
+	return EOK;
+}
+
+/**
+ * HTC communication initalization.
+ * 
+ * @param htc_device HTC device structure.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int htc_init(htc_device_t *htc_device)
+{
+	/* First check ready message in device. */
+	int rc = htc_check_ready(htc_device);
+	if(rc != EOK) {
+		usb_log_error("Device is not in ready state after loading "
+			"firmware.\n");
+		return rc;
+	}
+
+	/* 
+	 * HTC services initialization start.
+	 * 
+	 */
+	
+	rc = htc_connect_service(htc_device, WMI_CONTROL_SERVICE,
+	    &htc_device->endpoints.wmi_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Error while initalizing WMI service.\n");
+		return rc;
+	}
+
+	rc = htc_connect_service(htc_device, WMI_BEACON_SERVICE,
+	    &htc_device->endpoints.beacon_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Error while initalizing beacon service.\n");
+		return rc;
+	}
+
+	rc = htc_connect_service(htc_device, WMI_CAB_SERVICE,
+	    &htc_device->endpoints.cab_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Error while initalizing CAB service.\n");
+		return rc;
+	}
+
+	rc = htc_connect_service(htc_device, WMI_UAPSD_SERVICE,
+	    &htc_device->endpoints.uapsd_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Error while initalizing UAPSD service.\n");
+		return rc;
+	}
+
+	rc = htc_connect_service(htc_device, WMI_MGMT_SERVICE,
+	    &htc_device->endpoints.mgmt_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Error while initalizing MGMT service.\n");
+		return rc;
+	}
+	
+	rc = htc_connect_service(htc_device, WMI_DATA_BE_SERVICE,
+	    &htc_device->endpoints.data_be_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Error while initalizing data best effort "
+		    "service.\n");
+		return rc;
+	}
+
+	rc = htc_connect_service(htc_device, WMI_DATA_BK_SERVICE,
+	    &htc_device->endpoints.data_bk_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Error while initalizing data background "
+		    "service.\n");
+		return rc;
+	}
+
+	rc = htc_connect_service(htc_device, WMI_DATA_VIDEO_SERVICE,
+	    &htc_device->endpoints.data_video_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Error while initalizing data video service.\n");
+		return rc;
+	}
+	
+	rc = htc_connect_service(htc_device, WMI_DATA_VOICE_SERVICE,
+	    &htc_device->endpoints.data_voice_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Error while initalizing data voice service.\n");
+		return rc;
+	}
+
+	/* 
+	 * HTC services initialization end.
+	 * 
+	 */
+
+	/* Credits initialization message. */
+	rc = htc_config_credits(htc_device);
+	if(rc != EOK) {
+		usb_log_error("Failed to send HTC config message.\n");
+		return rc;
+	}
+
+	/* HTC setup complete confirmation message. */
+	rc = htc_complete_setup(htc_device);
+	if(rc != EOK) {
+		usb_log_error("Failed to send HTC complete setup message.\n");
+		return rc;
+	}
+
+	usb_log_info("HTC services initialization finished successfully.\n");
+	
+	return EOK;
+}
Index: uspace/drv/bus/usb/ar9271/htc.h
===================================================================
--- uspace/drv/bus/usb/ar9271/htc.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/htc.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2014 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file htc.h
+ *
+ * Definitions of the Atheros HTC (Host Target Communication) technology 
+ * for communication between host (PC) and target (device firmware).
+ *
+ */
+
+#ifndef ATHEROS_HTC_H
+#define	ATHEROS_HTC_H
+
+#include <usb/dev/driver.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include "ath.h"
+
+/**
+ * HTC message IDs
+ */
+typedef enum {
+	HTC_MESSAGE_READY = 1,
+	HTC_MESSAGE_CONNECT_SERVICE,
+        HTC_MESSAGE_CONNECT_SERVICE_RESPONSE,
+        HTC_MESSAGE_SETUP_COMPLETE,
+        HTC_MESSAGE_CONFIG
+} htc_message_id_t;
+
+/**
+ * HTC response message status codes
+ */
+typedef enum {
+        HTC_SERVICE_SUCCESS = 0,
+        HTC_SERVICE_NOT_FOUND,
+        HTC_SERVICE_FAILED,
+        HTC_SERVICE_NO_RESOURCES,
+        HTC_SERVICE_NO_MORE_EP
+} htc_response_status_code_t;
+
+/**
+ * HTC endpoint numbers
+ */
+typedef struct {
+        int ctrl_endpoint;
+	int wmi_endpoint;
+	int beacon_endpoint;
+	int cab_endpoint;
+	int uapsd_endpoint;
+	int mgmt_endpoint;
+	int data_be_endpoint;
+	int data_bk_endpoint;
+	int data_video_endpoint;
+	int data_voice_endpoint;
+} htc_pipes_t;
+
+/**
+ * HTC device data
+ */
+typedef struct {
+        /** WMI message sequence number */
+        uint16_t sequence_number;
+    
+	/** HTC endpoints numbers */
+	htc_pipes_t endpoints;
+	
+	/** Lock for receiver */
+	fibril_mutex_t rx_lock;
+	
+	/** Lock for transmitter */
+	fibril_mutex_t tx_lock;
+	
+	/** Pointer to Atheros WiFi device structure */
+	ath_t *ath_device;
+} htc_device_t;
+
+/** 
+ * HTC frame header structure 
+ */
+typedef struct {
+	uint8_t   endpoint_id;
+	uint8_t   flags;
+	uint16_t  payload_length;	/**< Big Endian value! */
+	uint8_t   control_bytes[4];
+    
+	/* Message payload starts after the header. */
+} __attribute__((packed)) htc_frame_header_t;
+
+/** 
+ * HTC ready message structure 
+ */
+typedef struct {
+        uint16_t message_id;		/**< Big Endian value! */
+        uint16_t credits;		/**< Big Endian value! */
+        uint16_t credit_size;		/**< Big Endian value! */
+        
+        uint8_t max_endpoints;
+	uint8_t pad;
+} __attribute__((packed)) htc_ready_msg_t;
+
+/** 
+ * HTC service message structure 
+ */
+typedef struct {
+	uint16_t message_id;		/**< Big Endian value! */
+	uint16_t service_id;		/**< Big Endian value! */
+	uint16_t connection_flags;	/**< Big Endian value! */
+	
+	uint8_t download_pipe_id;
+	uint8_t upload_pipe_id;
+	uint8_t service_meta_length;
+	uint8_t pad;
+} __attribute__((packed)) htc_service_msg_t;
+
+/** 
+ * HTC service response message structure 
+ */
+typedef struct {
+        uint16_t message_id;            /**< Big Endian value! */
+        uint16_t service_id;            /**< Big Endian value! */
+        uint8_t status;
+        uint8_t endpoint_id;
+        uint16_t max_message_length;    /**< Big Endian value! */
+        uint8_t service_meta_length;
+        uint8_t pad;
+} __attribute__((packed)) htc_service_resp_msg_t;
+
+/**
+ * HTC credits config message structure
+ */
+typedef struct {
+        uint16_t message_id;            /**< Big Endian value! */
+        uint8_t pipe_id;
+        uint8_t credits;
+} __attribute__((packed)) htc_config_msg_t;
+
+/**
+ * HTC setup complete message structure
+ */
+typedef struct {
+        uint16_t message_id;            /**< Big Endian value! */
+} __attribute__((packed)) htc_setup_complete_msg_t;
+
+extern int htc_device_init(ath_t *ath_device, htc_device_t *htc_device);
+extern int htc_init(htc_device_t* htc_device);
+extern int htc_read_message(htc_device_t *htc_device, void *buffer, 
+	size_t buffer_size, size_t *transferred_size);
+extern int htc_send_message(htc_device_t *htc_device, void *buffer, 
+	size_t buffer_size, uint8_t endpoint_id);
+
+#endif	/* HTC_H */
+
Index: uspace/drv/bus/usb/ar9271/hw.c
===================================================================
--- uspace/drv/bus/usb/ar9271/hw.c	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/hw.c	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2015 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file hw.c
+ *
+ * AR9271 hardware related functions implementation.
+ *
+ */
+
+#include <usb/debug.h>
+#include <unistd.h>
+
+#include "hw.h"
+#include "wmi.h"
+
+/**
+ * Try to wait for register value repeatedly until timeout defined by device 
+ * is reached.
+ * 
+ * @param ar9271 Device structure.
+ * @param offset Registry offset (address) to be read.
+ * @param mask Mask to apply on read result.
+ * @param value Required value we are waiting for.
+ * 
+ * @return EOK if succeed, ETIMEOUT on timeout, negative error code otherwise.
+ */
+static int hw_read_wait(ar9271_t *ar9271, uint32_t offset, uint32_t mask,
+	uint32_t value)
+{
+	uint32_t result;
+	
+	for(size_t i = 0; i < HW_WAIT_LOOPS; i++) {
+		udelay(HW_WAIT_TIME_US);
+
+		int rc = wmi_reg_read(ar9271->htc_device, offset, &result);
+		if(rc != EOK) {
+			usb_log_debug("Failed to read register. Error %d\n",
+				rc);
+			continue;
+		}
+
+		if((result & mask) == value) {
+			return EOK;
+		}
+	}
+	
+	return ETIMEOUT;
+}
+
+/**
+ * Hardware reset of AR9271 device.
+ * 
+ * @param ar9271 Device structure.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int hw_reset(ar9271_t *ar9271)
+{
+	reg_buffer_t buffer[] = {
+		{
+			.offset = AR9271_RTC_FORCE_WAKE,
+			.value = AR9271_RTC_FORCE_WAKE_ENABLE | 
+				AR9271_RTC_FORCE_WAKE_ON_INT
+		},
+		{
+			.offset = AR9271_RC,
+			.value = AR9271_RC_AHB
+		},
+		{
+			.offset = AR9271_RTC_RESET,
+			.value = 0
+		}
+	};
+	
+	int rc = wmi_reg_buffer_write(ar9271->htc_device, buffer,
+		sizeof(buffer) / sizeof(reg_buffer_t));
+	if(rc != EOK) {
+		usb_log_error("Failed to set RT FORCE WAKE register.\n");
+		return rc;
+	}
+	
+	udelay(2);
+	
+	rc = wmi_reg_write(ar9271->htc_device, AR9271_RC, 0);
+	if(rc != EOK) {
+		usb_log_error("Failed to reset MAC AHB register.\n");
+		return rc;
+	}
+	
+	rc = wmi_reg_write(ar9271->htc_device, AR9271_RTC_RESET, 1);
+	if(rc != EOK) {
+		usb_log_error("Failed to bring up RTC register.\n");
+		return rc;
+	}
+	
+	rc = hw_read_wait(ar9271, 
+		AR9271_RTC_STATUS, 
+		AR9271_RTC_STATUS_MASK, 
+		AR9271_RTC_STATUS_ON);
+	if(rc != EOK) {
+		usb_log_error("Failed to read wake up RTC register.\n");
+		return rc;
+	}
+	
+	return EOK;
+}
+
+/**
+ * Initialize hardware of AR9271 device.
+ * 
+ * @param ar9271 Device structure.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int hw_init(ar9271_t *ar9271)
+{
+	int rc = hw_reset(ar9271);
+	if(rc != EOK) {
+		usb_log_error("Failed to HW reset device.\n");
+		return rc;
+	}
+	
+	usb_log_info("HW initialization finished successfully.\n");
+	
+	return EOK;
+}
Index: uspace/drv/bus/usb/ar9271/hw.h
===================================================================
--- uspace/drv/bus/usb/ar9271/hw.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/hw.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file hw.h
+ *
+ * Definitions of AR9271 hardware related functions.
+ *
+ */
+
+#ifndef ATHEROS_HW_H
+#define	ATHEROS_HW_H
+
+#include "ar9271.h"
+
+#define HW_WAIT_LOOPS 10000
+#define HW_WAIT_TIME_US 10
+
+extern int hw_init(ar9271_t *ar9271);
+extern int hw_reset(ar9271_t *ar9271);
+
+#endif	/* ATHEROS_HW_H */
Index: uspace/drv/bus/usb/ar9271/wmi.c
===================================================================
--- uspace/drv/bus/usb/ar9271/wmi.c	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/wmi.c	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2014 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file wmi.c
+ *
+ * Implementation of Atheros WMI communication.
+ *
+ */
+
+#include <usb/debug.h>
+
+#include <malloc.h>
+#include <mem.h>
+#include <byteorder.h>
+
+#include "wmi.h"
+
+/**
+ * WMI registry read.
+ * 
+ * @param htc_device HTC device structure.
+ * @param reg_offset Registry offset (address) to be read.
+ * @param res Stored result.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int wmi_reg_read(htc_device_t *htc_device, uint32_t reg_offset, uint32_t *res)
+{
+	uint32_t resp_value;
+	uint32_t cmd_value = host2uint32_t_be(reg_offset);
+	
+	int rc = wmi_send_command(htc_device, WMI_REG_READ, 
+		(uint8_t *) &cmd_value, sizeof(cmd_value),
+		(uint8_t *) &resp_value, sizeof(resp_value));
+	
+	if(rc != EOK) {
+		usb_log_error("Failed to read registry value.\n");
+		return rc;
+	}
+	
+	*res = uint32_t_be2host(resp_value);
+	
+	return rc;
+}
+
+/**
+ * WMI registry write.
+ * 
+ * @param htc_device HTC device structure.
+ * @param reg_offset Registry offset (address) to be written.
+ * @param val Value to be written
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int wmi_reg_write(htc_device_t *htc_device, uint32_t reg_offset, uint32_t val)
+{
+	uint32_t resp_value = host2uint32_t_be(val);	
+	uint32_t cmd_buffer[] = {
+	    host2uint32_t_be(reg_offset),
+	    resp_value
+	};
+	
+	int rc = wmi_send_command(htc_device, WMI_REG_WRITE, 
+		(uint8_t *) &cmd_buffer, sizeof(cmd_buffer),
+		(uint8_t *) &resp_value, sizeof(resp_value));
+	
+	if(rc != EOK) {
+		usb_log_error("Failed to write registry value.\n");
+		return rc;
+	}
+	
+	return rc;
+}
+
+/**
+ * WMI multi registry write.
+ * 
+ * @param htc_device HTC device structure.
+ * @param reg_buffer Array of registry values to be written.
+ * @param elements Number of elements in array.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int wmi_reg_buffer_write(htc_device_t *htc_device, reg_buffer_t *reg_buffer,
+	size_t elements)
+{
+	uint32_t resp_value;
+	
+	/* Convert values to correct endianness. */
+	for(size_t i = 0; i < elements; i++) {
+		reg_buffer_t *buffer_element = &reg_buffer[i];
+		buffer_element->offset = 
+			host2uint32_t_be(buffer_element->offset);
+		buffer_element->value =
+			host2uint32_t_be(buffer_element->value);
+	}
+	
+	int rc = wmi_send_command(htc_device, WMI_REG_WRITE, 
+		(uint8_t *) &reg_buffer, sizeof(reg_buffer_t)*elements,
+		(uint8_t *) &resp_value, sizeof(resp_value));
+	
+	if(rc != EOK) {
+		usb_log_error("Failed to write multi registry value.\n");
+		return rc;
+	}
+	
+	return rc;
+}
+
+/**
+ * Send WMI message to HTC device.
+ * 
+ * @param htc_device HTC device structure.
+ * @param command_id Command identification.
+ * @param command_buffer Buffer with command data.
+ * @param command_length Length of command data.
+ * @param response_buffer Buffer with response data.
+ * @param response_length Length of response data.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int wmi_send_command(htc_device_t *htc_device, wmi_command_t command_id, 
+    uint8_t *command_buffer, uint32_t command_length, 
+    uint8_t *response_buffer, uint32_t response_length) 
+{
+	size_t header_size = sizeof(wmi_command_header_t) + 
+		sizeof(htc_frame_header_t);
+	size_t buffer_size = header_size + command_length;
+	void *buffer = malloc(buffer_size);
+	memcpy(buffer+header_size, command_buffer, command_length);
+	
+	/* Set up WMI header */
+	wmi_command_header_t *wmi_header = (wmi_command_header_t *)
+		((void *) buffer + sizeof(htc_frame_header_t));
+	wmi_header->command_id = 
+		host2uint16_t_be(command_id);
+	wmi_header->sequence_number = 
+		host2uint16_t_be(++htc_device->sequence_number);
+	
+	int rc = htc_send_message(htc_device, buffer, buffer_size,
+		htc_device->endpoints.wmi_endpoint);
+	if(rc != EOK) {
+		usb_log_error("Failed to send WMI message. Error: %d\n", rc);
+	}
+	
+	free(buffer);
+	
+	buffer_size = header_size + response_length;
+	buffer = malloc(buffer_size);
+	
+	rc = htc_read_message(htc_device, buffer, buffer_size, NULL);
+	if(rc != EOK) {
+		free(buffer);
+		usb_log_error("Failed to receive WMI message response. "
+		    "Error: %d\n", rc);
+		return rc;
+	}
+	
+	memcpy(response_buffer, 
+		buffer + sizeof(wmi_command_header_t), 
+		response_length);
+	
+	free(buffer);
+	
+	return rc;
+}
Index: uspace/drv/bus/usb/ar9271/wmi.h
===================================================================
--- uspace/drv/bus/usb/ar9271/wmi.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
+++ uspace/drv/bus/usb/ar9271/wmi.h	(revision 66b3e0b36868909183dfb5c533a019cfef82440d)
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2014 Jan Kolarik
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file wmi.h
+ *
+ * Definitions of the Atheros WMI protocol specified in the 
+ * Wireless Module Interface (WMI).
+ *
+ */
+
+#ifndef ATHEROS_WMI_H
+#define	ATHEROS_WMI_H
+
+#include "htc.h"
+
+/* Macros for creating service identificators. */
+#define WMI_SERVICE_GROUP 1
+#define CREATE_SERVICE_ID(group, i) (int) (((int) group << 8) | (int) (i))
+
+/**
+ * WMI header structure.
+ */
+typedef struct {
+    uint16_t command_id;		/**< Big Endian value! */
+    uint16_t sequence_number;           /**< Big Endian value! */
+} __attribute__((packed)) wmi_command_header_t; 
+
+/**
+ * WMI services IDs
+ */
+typedef enum {
+	WMI_CONTROL_SERVICE = CREATE_SERVICE_ID(WMI_SERVICE_GROUP, 0),
+	WMI_BEACON_SERVICE = CREATE_SERVICE_ID(WMI_SERVICE_GROUP, 1),
+	WMI_CAB_SERVICE = CREATE_SERVICE_ID(WMI_SERVICE_GROUP, 2),
+	WMI_UAPSD_SERVICE = CREATE_SERVICE_ID(WMI_SERVICE_GROUP, 3),
+	WMI_MGMT_SERVICE = CREATE_SERVICE_ID(WMI_SERVICE_GROUP, 4),
+	WMI_DATA_VOICE_SERVICE = CREATE_SERVICE_ID(WMI_SERVICE_GROUP, 5),
+	WMI_DATA_VIDEO_SERVICE = CREATE_SERVICE_ID(WMI_SERVICE_GROUP, 6),
+	WMI_DATA_BE_SERVICE = CREATE_SERVICE_ID(WMI_SERVICE_GROUP, 7),
+	WMI_DATA_BK_SERVICE = CREATE_SERVICE_ID(WMI_SERVICE_GROUP, 8)
+} wmi_services_t;
+
+/**
+ * List of WMI commands
+ */
+typedef enum {
+	WMI_ECHO = 0x0001,
+	WMI_ACCESS_MEMORY,
+
+	/* Commands used for HOST -> DEVICE communication */
+	WMI_GET_FW_VERSION,
+	WMI_DISABLE_INTR,
+	WMI_ENABLE_INTR,
+	WMI_ATH_INIT,
+	WMI_ABORT_TXQ,
+	WMI_STOP_TX_DMA,
+	WMI_ABORT_TX_DMA,
+	WMI_DRAIN_TXQ,
+	WMI_DRAIN_TXQ_ALL,
+	WMI_START_RECV,
+	WMI_STOP_RECV,
+	WMI_FLUSH_RECV,
+	WMI_SET_MODE,
+	WMI_NODE_CREATE,
+	WMI_NODE_REMOVE,
+	WMI_VAP_REMOVE,
+	WMI_VAP_CREATE,
+	WMI_REG_READ,
+	WMI_REG_WRITE,
+	WMI_RC_STATE_CHANGE,
+	WMI_RC_RATE_UPDATE,
+	WMI_TARGET_IC_UPDATE,
+	WMI_TX_AGGR_ENABLE,
+	WMI_TGT_DETACH,
+	WMI_NODE_UPDATE,
+	WMI_INT_STATS,
+	WMI_TX_STATS,
+	WMI_RX_STATS,
+	WMI_BITRATE_MASK,
+	WMI_REG_RMW,
+} wmi_command_t;
+
+typedef struct {
+	uint32_t offset;		/**< Big Endian value! */
+	uint32_t value;			/**< Big Endian value! */
+} reg_buffer_t;
+
+extern int wmi_reg_read(htc_device_t *htc_device, uint32_t reg_offset, 
+	uint32_t *res);
+extern int wmi_reg_write(htc_device_t *htc_device, uint32_t reg_offset, 
+	uint32_t val);
+extern int wmi_reg_buffer_write(htc_device_t *htc_device, 
+	reg_buffer_t *reg_buffer, size_t elements);
+extern int wmi_send_command(htc_device_t *htc_device, 
+	wmi_command_t command_id, 
+	uint8_t *command_buffer, uint32_t command_length, 
+	uint8_t *response_buffer, uint32_t response_length);
+
+#endif	/* ATHEROS_WMI_H */
+
