Index: uspace/drv/bus/usb/ar9271/ar9271.h
===================================================================
--- uspace/drv/bus/usb/ar9271/ar9271.h	(revision ef521d4091b277b23a8ea026424ce4b01e0677d9)
+++ uspace/drv/bus/usb/ar9271/ar9271.h	(revision 01784d20ebe77098db8f9fe743d50de2c8c9b646)
@@ -47,4 +47,6 @@
     
 	/* Wakeup related registers */
+	AR9271_RTC_RC = 0x7000,
+	AR9271_RTC_RC_MASK = 0x00000003,
 	AR9271_RTC_RESET = 0x7040,
 	AR9271_RTC_STATUS = 0x7044,
Index: uspace/drv/bus/usb/ar9271/htc.c
===================================================================
--- uspace/drv/bus/usb/ar9271/htc.c	(revision ef521d4091b277b23a8ea026424ce4b01e0677d9)
+++ uspace/drv/bus/usb/ar9271/htc.c	(revision 01784d20ebe77098db8f9fe743d50de2c8c9b646)
@@ -39,6 +39,4 @@
 #include "htc.h"
 
-#define MAX_RESP_LEN 64
-
 /**
  * HTC download pipes mapping.
@@ -82,5 +80,11 @@
 	htc_header->endpoint_id = endpoint_id;
 	htc_header->flags = 0;
-	htc_header->payload_length = host2uint16_t_be(buffer_size);
+	htc_header->payload_length = 
+		host2uint16_t_be(buffer_size - sizeof(htc_frame_header_t));
+	
+	htc_header->control_bytes[0] = 0x02;
+	htc_header->control_bytes[1] = 0x88;
+	htc_header->control_bytes[2] = 0xFF;
+	htc_header->control_bytes[3] = 0xFF;
 	
 	ath_t *ath_device = htc_device->ath_device;
@@ -150,5 +154,5 @@
 	free(buffer);
 	
-	buffer_size = MAX_RESP_LEN;
+	buffer_size = MAX_RESPONSE_LENGTH;
 	buffer = malloc(buffer_size);
 	
@@ -214,5 +218,5 @@
 	free(buffer);
 	
-	buffer_size = MAX_RESP_LEN;
+	buffer_size = MAX_RESPONSE_LENGTH;
 	buffer = malloc(buffer_size);
 
@@ -272,5 +276,5 @@
 static int htc_check_ready(htc_device_t *htc_device)
 {
-	size_t buffer_size = MAX_RESP_LEN;
+	size_t buffer_size = MAX_RESPONSE_LENGTH;
 	void *buffer = malloc(buffer_size);
 
Index: uspace/drv/bus/usb/ar9271/htc.h
===================================================================
--- uspace/drv/bus/usb/ar9271/htc.h	(revision ef521d4091b277b23a8ea026424ce4b01e0677d9)
+++ uspace/drv/bus/usb/ar9271/htc.h	(revision 01784d20ebe77098db8f9fe743d50de2c8c9b646)
@@ -42,4 +42,6 @@
 
 #include "ath.h"
+
+#define MAX_RESPONSE_LENGTH 64
 
 /**
Index: uspace/drv/bus/usb/ar9271/hw.c
===================================================================
--- uspace/drv/bus/usb/ar9271/hw.c	(revision ef521d4091b277b23a8ea026424ce4b01e0677d9)
+++ uspace/drv/bus/usb/ar9271/hw.c	(revision 01784d20ebe77098db8f9fe743d50de2c8c9b646)
@@ -64,5 +64,5 @@
 			continue;
 		}
-
+		
 		if((result & mask) == value) {
 			return EOK;
@@ -73,14 +73,14 @@
 }
 
-/**
- * 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[] = {
+static int hw_reset_power_on(ar9271_t *ar9271)
+{
+	int rc = wmi_reg_write(ar9271->htc_device, AR9271_RTC_FORCE_WAKE, 
+		AR9271_RTC_FORCE_WAKE_ENABLE | 	AR9271_RTC_FORCE_WAKE_ON_INT);
+	if(rc != EOK) {
+		usb_log_error("Failed to bring up RTC register.\n");
+		return rc;
+	}
+	
+	wmi_reg_t buffer[] = {
 		{
 			.offset = AR9271_RTC_FORCE_WAKE,
@@ -98,6 +98,6 @@
 	};
 	
-	int rc = wmi_reg_buffer_write(ar9271->htc_device, buffer,
-		sizeof(buffer) / sizeof(reg_buffer_t));
+	rc = wmi_reg_buffer_write(ar9271->htc_device, buffer,
+		sizeof(buffer) / sizeof(wmi_reg_t));
 	if(rc != EOK) {
 		usb_log_error("Failed to set RT FORCE WAKE register.\n");
@@ -128,5 +128,77 @@
 	}
 	
-	/* TODO: Finish HW init. */
+	return EOK;
+}
+
+static int hw_warm_reset(ar9271_t *ar9271)
+{
+	wmi_reg_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_RC,
+			.value = 1
+		}
+	};
+	
+	int rc = wmi_reg_buffer_write(ar9271->htc_device, buffer,
+		sizeof(buffer) / sizeof(wmi_reg_t));
+	if(rc != EOK) {
+		usb_log_error("Failed to set warm reset register.\n");
+		return rc;
+	}
+	
+	udelay(100);
+	
+	rc = wmi_reg_write(ar9271->htc_device, AR9271_RTC_RC, 0);
+	if(rc != EOK) {
+		usb_log_error("Failed to reset RTC RC register.\n");
+		return rc;
+	}
+	
+	rc = hw_read_wait(ar9271, AR9271_RTC_RC, AR9271_RTC_RC_MASK, 0);
+	if(rc != EOK) {
+		usb_log_error("Failed to read RTC RC register.\n");
+		return rc;
+	}
+	
+	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;
+	}
+	
+	return EOK;
+}
+
+/**
+ * Hardware reset of AR9271 device.
+ * 
+ * @param ar9271 Device structure.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int hw_reset(ar9271_t *ar9271)
+{
+	int rc = hw_reset_power_on(ar9271);
+	if(rc != EOK) {
+		usb_log_error("Failed to HW reset power on.\n");
+		return rc;
+	}
+	
+	rc = hw_warm_reset(ar9271);
+	if(rc != EOK) {
+		usb_log_error("Failed to HW warm reset.\n");
+		return rc;
+	}
+	
+	/* TODO: Finish HW init (EEPROM init, MAC ADDR init). */
 	
 	return EOK;
Index: uspace/drv/bus/usb/ar9271/hw.h
===================================================================
--- uspace/drv/bus/usb/ar9271/hw.h	(revision ef521d4091b277b23a8ea026424ce4b01e0677d9)
+++ uspace/drv/bus/usb/ar9271/hw.h	(revision 01784d20ebe77098db8f9fe743d50de2c8c9b646)
@@ -38,5 +38,5 @@
 #include "ar9271.h"
 
-#define HW_WAIT_LOOPS 10000
+#define HW_WAIT_LOOPS 100
 #define HW_WAIT_TIME_US 10
 
Index: uspace/drv/bus/usb/ar9271/wmi.c
===================================================================
--- uspace/drv/bus/usb/ar9271/wmi.c	(revision ef521d4091b277b23a8ea026424ce4b01e0677d9)
+++ uspace/drv/bus/usb/ar9271/wmi.c	(revision 01784d20ebe77098db8f9fe743d50de2c8c9b646)
@@ -52,10 +52,11 @@
 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);
 	
+	size_t buffer_size = MAX_RESPONSE_LENGTH;
+	void *resp_buffer = malloc(buffer_size);
+	
 	int rc = wmi_send_command(htc_device, WMI_REG_READ, 
-		(uint8_t *) &cmd_value, sizeof(cmd_value),
-		(uint8_t *) &resp_value, sizeof(resp_value));
+		(uint8_t *) &cmd_value, sizeof(cmd_value), resp_buffer);
 	
 	if(rc != EOK) {
@@ -64,5 +65,9 @@
 	}
 	
-	*res = uint32_t_be2host(resp_value);
+	uint32_t *resp_value = (uint32_t *) ((void*) resp_buffer + 
+		sizeof(htc_frame_header_t) +
+		sizeof(wmi_command_header_t));
+	
+	*res = uint32_t_be2host(*resp_value);
 	
 	return rc;
@@ -80,13 +85,15 @@
 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
+	    host2uint32_t_be(val)
 	};
 	
+	void *resp_buffer = malloc(MAX_RESPONSE_LENGTH);
+	
 	int rc = wmi_send_command(htc_device, WMI_REG_WRITE, 
-		(uint8_t *) &cmd_buffer, sizeof(cmd_buffer),
-		(uint8_t *) &resp_value, sizeof(resp_value));
+		(uint8_t *) &cmd_buffer, sizeof(cmd_buffer), resp_buffer);
+	
+	free(resp_buffer);
 	
 	if(rc != EOK) {
@@ -96,4 +103,69 @@
 	
 	return rc;
+}
+
+/**
+ * WMI registry set or clear specified bits.
+ * 
+ * @param htc_device HTC device structure.
+ * @param reg_offset Registry offset (address) to be written.
+ * @param set_bit Bit to be set.
+ * @param clear_bit Bit to be cleared.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int wmi_reg_rmw(htc_device_t *htc_device, uint32_t reg_offset, 
+	uint32_t set_bit, uint32_t clear_bit)
+{
+	uint32_t value;
+	
+	int rc = wmi_reg_read(htc_device, reg_offset, &value);
+	if(rc != EOK) {
+		usb_log_error("Failed to read registry value in RMW "
+			"function.\n");
+		return rc;
+	}
+	
+	value |= set_bit;
+	value &= ~clear_bit;
+	
+	rc = wmi_reg_write(htc_device, reg_offset, value);
+	if(rc != EOK) {
+		usb_log_error("Failed to write registry value in RMW "
+			"function.\n");
+		return rc;
+	}
+	
+	return rc;
+}
+
+/**
+ * WMI registry set specified bit.
+ * 
+ * @param htc_device HTC device structure.
+ * @param reg_offset Registry offset (address) to be written.
+ * @param set_bit Bit to be set.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int wmi_reg_set_bit(htc_device_t *htc_device, uint32_t reg_offset, 
+	uint32_t set_bit)
+{
+	return wmi_reg_rmw(htc_device, reg_offset, set_bit, 0);
+}
+
+/**
+ * WMI registry clear specified bit.
+ * 
+ * @param htc_device HTC device structure.
+ * @param reg_offset Registry offset (address) to be written.
+ * @param clear_bit Bit to be cleared.
+ * 
+ * @return EOK if succeed, negative error code otherwise.
+ */
+int wmi_reg_clear_bit(htc_device_t *htc_device, uint32_t reg_offset, 
+	uint32_t clear_bit)
+{
+	return wmi_reg_rmw(htc_device, reg_offset, 0, clear_bit);
 }
 
@@ -107,21 +179,27 @@
  * @return EOK if succeed, negative error code otherwise.
  */
-int wmi_reg_buffer_write(htc_device_t *htc_device, reg_buffer_t *reg_buffer,
+int wmi_reg_buffer_write(htc_device_t *htc_device, wmi_reg_t *reg_buffer,
 	size_t elements)
 {
-	uint32_t resp_value;
+	size_t buffer_size = sizeof(wmi_reg_t) * elements;
+	void *buffer = malloc(buffer_size);
+	void *resp_buffer = malloc(MAX_RESPONSE_LENGTH);
 	
 	/* Convert values to correct endianness. */
 	for(size_t i = 0; i < elements; i++) {
-		reg_buffer_t *buffer_element = &reg_buffer[i];
-		buffer_element->offset = 
+		wmi_reg_t *buffer_element = &reg_buffer[i];
+		wmi_reg_t *buffer_it = (wmi_reg_t *)
+			((void *) buffer + i*sizeof(wmi_reg_t));
+		buffer_it->offset = 
 			host2uint32_t_be(buffer_element->offset);
-		buffer_element->value =
+		buffer_it->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));
+		(uint8_t *) buffer, buffer_size, resp_buffer);
+	
+	free(buffer);
+	free(resp_buffer);
 	
 	if(rc != EOK) {
@@ -141,11 +219,9 @@
  * @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) 
+    uint8_t *command_buffer, uint32_t command_length, void *response_buffer) 
 {
 	size_t header_size = sizeof(wmi_command_header_t) + 
@@ -174,9 +250,7 @@
 	free(buffer);
 	
-	buffer_size = header_size + response_length;
-	buffer = malloc(buffer_size);
-	
 	/* Read response. */
-	rc = htc_read_message(htc_device, buffer, buffer_size, NULL);
+	rc = htc_read_message(htc_device, response_buffer, MAX_RESPONSE_LENGTH, 
+		NULL);
 	if(rc != EOK) {
 		free(buffer);
@@ -186,10 +260,4 @@
 	}
 	
-	memcpy(response_buffer, 
-		buffer + sizeof(wmi_command_header_t), 
-		response_length);
-	
-	free(buffer);
-	
-	return rc;
-}
+	return rc;
+}
Index: uspace/drv/bus/usb/ar9271/wmi.h
===================================================================
--- uspace/drv/bus/usb/ar9271/wmi.h	(revision ef521d4091b277b23a8ea026424ce4b01e0677d9)
+++ uspace/drv/bus/usb/ar9271/wmi.h	(revision 01784d20ebe77098db8f9fe743d50de2c8c9b646)
@@ -106,8 +106,11 @@
 } wmi_command_t;
 
+/**
+ * Structure used when sending registry buffer
+ */
 typedef struct {
 	uint32_t offset;		/**< Big Endian value! */
 	uint32_t value;			/**< Big Endian value! */
-} reg_buffer_t;
+} wmi_reg_t;
 
 extern int wmi_reg_read(htc_device_t *htc_device, uint32_t reg_offset, 
@@ -115,10 +118,16 @@
 extern int wmi_reg_write(htc_device_t *htc_device, uint32_t reg_offset, 
 	uint32_t val);
+extern int wmi_reg_rmw(htc_device_t *htc_device, uint32_t reg_offset, 
+	uint32_t set_bit, uint32_t clear_bit);
+extern int wmi_reg_set_bit(htc_device_t *htc_device, uint32_t reg_offset, 
+	uint32_t set_bit);
+extern int wmi_reg_clear_bit(htc_device_t *htc_device, uint32_t reg_offset, 
+	uint32_t clear_bit);
 extern int wmi_reg_buffer_write(htc_device_t *htc_device, 
-	reg_buffer_t *reg_buffer, size_t elements);
+	wmi_reg_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);
+	void *response_buffer);
 
 #endif	/* ATHEROS_WMI_H */
