Index: uspace/drv/bus/usb/xhci/commands.c
===================================================================
--- uspace/drv/bus/usb/xhci/commands.c	(revision ab5a083027fa93e97b9f6f3e865cc78400ad198f)
+++ uspace/drv/bus/usb/xhci/commands.c	(revision 548c1238cba73184d31834477064377b71bc546c)
@@ -55,5 +55,5 @@
  */
 #define TRB_SET_DEQUEUE_PTR(trb, dptr) (trb).parameter |= host2xhci(64, (dptr))
-#define TRB_SET_ICTX(trb, phys) (trb).parameter |= host2xhci(32, phys_addr & (~0xF))
+#define TRB_SET_ICTX(trb, phys) (trb).parameter |= host2xhci(64, phys_addr & (~0xF))
 
 #define TRB_GET_CODE(trb) XHCI_DWORD_EXTRACT((trb).status, 31, 24)
@@ -108,5 +108,4 @@
 	 */
 	cmd->has_owner = true;
-	cmd->owns_trb = false;
 
 	return cmd;
@@ -119,6 +118,4 @@
 	if (cmd->ictx)
 		free32(cmd->ictx);
-	if (cmd->owns_trb && cmd->trb)
-		free32(cmd->trb);
 
 	free32(cmd);
@@ -128,9 +125,12 @@
 {
 	link_t *cmd_link = list_first(&hc->commands);
+
+
+	usb_log_debug2("Searching TRB %lu...", phys);
 
 	while (cmd_link != NULL) {
 		xhci_cmd_t *cmd = list_get_instance(cmd_link, xhci_cmd_t, link);
 
-		if (addr_to_phys(cmd->trb) == phys)
+		if (cmd->trb_phys == phys)
 			break;
 
@@ -155,25 +155,18 @@
 }
 
-static inline int enqueue_trb(xhci_hc_t *hc, xhci_trb_t *trb,
-			      unsigned doorbell, unsigned target)
-{
-	assert(hc);
-	assert(trb);
-
-	xhci_trb_ring_enqueue(&hc->command_ring, trb);
+static inline int enqueue_command(xhci_hc_t *hc, xhci_cmd_t *cmd, unsigned doorbell, unsigned target)
+{
+	assert(hc);
+	assert(cmd);
+
+	list_append(&cmd->link, &hc->commands);
+
+	xhci_trb_ring_enqueue(&hc->command_ring, &cmd->trb, &cmd->trb_phys);
 	ring_doorbell(hc, doorbell, target);
 
-	xhci_dump_trb(trb);
-	usb_log_debug2("HC(%p): Sent TRB", hc);
+	usb_log_debug2("HC(%p): Sent command:", hc);
+	xhci_dump_trb(&cmd->trb);
 
 	return EOK;
-}
-
-static inline void add_cmd(xhci_hc_t *hc, xhci_cmd_t *cmd)
-{
-	assert(cmd);
-
-	list_append(&cmd->link, &hc->commands);
-	cmd->trb = hc->command_ring.enqueue_trb;
 }
 
@@ -263,12 +256,9 @@
 	assert(hc);
 
-	xhci_trb_t trb;
-	memset(&trb, 0, sizeof(trb));
-
-	TRB_SET_TYPE(trb, XHCI_TRB_TYPE_NO_OP_CMD);
-
-	add_cmd(hc, cmd);
-
-	return enqueue_trb(hc, &trb, 0, 0);
+	xhci_trb_clean(&cmd->trb);
+
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_NO_OP_CMD);
+
+	return enqueue_command(hc, cmd, 0, 0);
 }
 
@@ -277,13 +267,10 @@
 	assert(hc);
 
-	xhci_trb_t trb;
-	memset(&trb, 0, sizeof(trb));
-
-	TRB_SET_TYPE(trb, XHCI_TRB_TYPE_ENABLE_SLOT_CMD);
-	trb.control |= host2xhci(32, XHCI_REG_RD(hc->xecp, XHCI_EC_SP_SLOT_TYPE) << 16);
-
-	add_cmd(hc, cmd);
-
-	return enqueue_trb(hc, &trb, 0, 0);
+	xhci_trb_clean(&cmd->trb);
+
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_ENABLE_SLOT_CMD);
+	cmd->trb.control |= host2xhci(32, XHCI_REG_RD(hc->xecp, XHCI_EC_SP_SLOT_TYPE) << 16);
+
+	return enqueue_command(hc, cmd, 0, 0);
 }
 
@@ -293,13 +280,10 @@
 	assert(cmd);
 
-	xhci_trb_t trb;
-	memset(&trb, 0, sizeof(trb));
-
-	TRB_SET_TYPE(trb, XHCI_TRB_TYPE_DISABLE_SLOT_CMD);
-	TRB_SET_SLOT(trb, cmd->slot_id);
-
-	add_cmd(hc, cmd);
-
-	return enqueue_trb(hc, &trb, 0, 0);
+	xhci_trb_clean(&cmd->trb);
+
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_DISABLE_SLOT_CMD);
+	TRB_SET_SLOT(cmd->trb, cmd->slot_id);
+
+	return enqueue_command(hc, cmd, 0, 0);
 }
 
@@ -316,9 +300,8 @@
 	 *           other should be ignored at this point (see section 4.6.5).
 	 */
-	xhci_trb_t trb;
-	memset(&trb, 0, sizeof(trb));
+	xhci_trb_clean(&cmd->trb);
 
 	uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx);
-	TRB_SET_ICTX(trb, phys_addr);
+	TRB_SET_ICTX(cmd->trb, phys_addr);
 
 	/**
@@ -329,10 +312,8 @@
 	 *       that require their device descriptor to be read before such request.
 	 */
-	TRB_SET_TYPE(trb, XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD);
-	TRB_SET_SLOT(trb, cmd->slot_id);
-
-	add_cmd(hc, cmd);
-
-	return enqueue_trb(hc, &trb, 0, 0);
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD);
+	TRB_SET_SLOT(cmd->trb, cmd->slot_id);
+
+	return enqueue_command(hc, cmd, 0, 0);
 }
 
@@ -343,16 +324,13 @@
 	assert(cmd->ictx);
 
-	xhci_trb_t trb;
-	memset(&trb, 0, sizeof(trb));
+	xhci_trb_clean(&cmd->trb);
 
 	uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx);
-	TRB_SET_ICTX(trb, phys_addr);
-
-	TRB_SET_TYPE(trb, XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD);
-	TRB_SET_SLOT(trb, cmd->slot_id);
-
-	add_cmd(hc, cmd);
-
-	return enqueue_trb(hc, &trb, 0, 0);
+	TRB_SET_ICTX(cmd->trb, phys_addr);
+
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD);
+	TRB_SET_SLOT(cmd->trb, cmd->slot_id);
+
+	return enqueue_command(hc, cmd, 0, 0);
 }
 
@@ -369,16 +347,13 @@
 	 *       Refer to sections 6.2.2.3 and 6.3.3.3 for further info.
 	 */
-	xhci_trb_t trb;
-	memset(&trb, 0, sizeof(trb));
+	xhci_trb_clean(&cmd->trb);
 
 	uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->ictx);
-	TRB_SET_ICTX(trb, phys_addr);
-
-	TRB_SET_TYPE(trb, XHCI_TRB_TYPE_EVALUATE_CONTEXT_CMD);
-	TRB_SET_SLOT(trb, cmd->slot_id);
-
-	add_cmd(hc, cmd);
-
-	return enqueue_trb(hc, &trb, 0, 0);
+	TRB_SET_ICTX(cmd->trb, phys_addr);
+
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_EVALUATE_CONTEXT_CMD);
+	TRB_SET_SLOT(cmd->trb, cmd->slot_id);
+
+	return enqueue_command(hc, cmd, 0, 0);
 }
 
@@ -392,15 +367,12 @@
 	 *       information about this flag.
 	 */
-	xhci_trb_t trb;
-	memset(&trb, 0, sizeof(trb));
-
-	TRB_SET_TYPE(trb, XHCI_TRB_TYPE_RESET_ENDPOINT_CMD);
-	TRB_SET_TCS(trb, tcs);
-	TRB_SET_EP(trb, ep_id);
-	TRB_SET_SLOT(trb, cmd->slot_id);
-
-	add_cmd(hc, cmd);
-
-	return enqueue_trb(hc, &trb, 0, 0);
+	xhci_trb_clean(&cmd->trb);
+
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_RESET_ENDPOINT_CMD);
+	TRB_SET_TCS(cmd->trb, tcs);
+	TRB_SET_EP(cmd->trb, ep_id);
+	TRB_SET_SLOT(cmd->trb, cmd->slot_id);
+
+	return enqueue_command(hc, cmd, 0, 0);
 }
 
@@ -410,15 +382,12 @@
 	assert(cmd);
 
-	xhci_trb_t trb;
-	memset(&trb, 0, sizeof(trb));
-
-	TRB_SET_TYPE(trb, XHCI_TRB_TYPE_STOP_ENDPOINT_CMD);
-	TRB_SET_EP(trb, ep_id);
-	TRB_SET_SUSP(trb, susp);
-	TRB_SET_SLOT(trb, cmd->slot_id);
-
-	add_cmd(hc, cmd);
-
-	return enqueue_trb(hc, &trb, 0, 0);
+	xhci_trb_clean(&cmd->trb);
+
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_STOP_ENDPOINT_CMD);
+	TRB_SET_EP(cmd->trb, ep_id);
+	TRB_SET_SUSP(cmd->trb, susp);
+	TRB_SET_SLOT(cmd->trb, cmd->slot_id);
+
+	return enqueue_command(hc, cmd, 0, 0);
 }
 
@@ -430,12 +399,11 @@
 	assert(cmd);
 
-	xhci_trb_t trb;
-	memset(&trb, 0, sizeof(trb));
-
-	TRB_SET_TYPE(trb, XHCI_TRB_TYPE_SET_TR_DEQUEUE_POINTER_CMD);
-	TRB_SET_EP(trb, ep_id);
-	TRB_SET_STREAM(trb, stream_id);
-	TRB_SET_SLOT(trb, cmd->slot_id);
-	TRB_SET_DEQUEUE_PTR(trb, dequeue_ptr);
+	xhci_trb_clean(&cmd->trb);
+
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_SET_TR_DEQUEUE_POINTER_CMD);
+	TRB_SET_EP(cmd->trb, ep_id);
+	TRB_SET_STREAM(cmd->trb, stream_id);
+	TRB_SET_SLOT(cmd->trb, cmd->slot_id);
+	TRB_SET_DEQUEUE_PTR(cmd->trb, dequeue_ptr);
 
 	/**
@@ -443,7 +411,5 @@
 	 */
 
-	add_cmd(hc, cmd);
-
-	return enqueue_trb(hc, &trb, 0, 0);
+	return enqueue_command(hc, cmd, 0, 0);
 }
 
@@ -453,13 +419,10 @@
 	assert(cmd);
 
-	xhci_trb_t trb;
-	memset(&trb, 0, sizeof(trb));
-
-	TRB_SET_TYPE(trb, XHCI_TRB_TYPE_RESET_DEVICE_CMD);
-	TRB_SET_SLOT(trb, cmd->slot_id);
-
-	add_cmd(hc, cmd);
-
-	return enqueue_trb(hc, &trb, 0, 0);
+	xhci_trb_clean(&cmd->trb);
+
+	TRB_SET_TYPE(cmd->trb, XHCI_TRB_TYPE_RESET_DEVICE_CMD);
+	TRB_SET_SLOT(cmd->trb, cmd->slot_id);
+
+	return enqueue_command(hc, cmd, 0, 0);
 }
 
@@ -475,5 +438,4 @@
 	uint64_t phys;
 	xhci_cmd_t *command;
-	xhci_trb_t *command_trb;
 
 	code = TRB_GET_CODE(*trb);
@@ -490,17 +452,16 @@
 	}
 
-	command_trb = command->trb;
 	command->status = code;
 	command->slot_id = TRB_GET_SLOT(*trb);
 
-	usb_log_debug2("Completed command trb: %s", xhci_trb_str_type(TRB_TYPE(*command_trb)));
-	if (TRB_TYPE(*command_trb) != XHCI_TRB_TYPE_NO_OP_CMD) {
+	usb_log_debug2("Completed command trb: %s", xhci_trb_str_type(TRB_TYPE(command->trb)));
+	if (TRB_TYPE(command->trb) != XHCI_TRB_TYPE_NO_OP_CMD) {
 		if (code != XHCI_TRBC_SUCCESS) {
 			report_error(code);
-			xhci_dump_trb(command_trb);
+			xhci_dump_trb(&command->trb);
 		}
 	}
 
-	switch (TRB_TYPE(*command_trb)) {
+	switch (TRB_TYPE(command->trb)) {
 	case XHCI_TRB_TYPE_NO_OP_CMD:
 		assert(code == XHCI_TRBC_TRB_ERROR);
@@ -526,5 +487,5 @@
 		break;
 	default:
-		usb_log_debug2("Unsupported command trb: %s", xhci_trb_str_type(TRB_TYPE(*command_trb)));
+		usb_log_debug2("Unsupported command trb: %s", xhci_trb_str_type(TRB_TYPE(command->trb)));
 
 		command->completed = true;
@@ -536,12 +497,7 @@
 	if (!command->has_owner) {
 		usb_log_debug2("Command has no owner, deallocating.");
-		command->trb = NULL; // It was statically allocated.
 		xhci_free_command(command);
 	} else {
 		usb_log_debug2("Command has owner, don't forget to deallocate!");
-		/* Copy the trb for later use so that we can free space on the cmd ring. */
-		command->trb = malloc32(sizeof(xhci_trb_t));
-		xhci_trb_copy(command->trb, command_trb);
-		command->owns_trb = true;
 	}
 
Index: uspace/drv/bus/usb/xhci/commands.h
===================================================================
--- uspace/drv/bus/usb/xhci/commands.h	(revision ab5a083027fa93e97b9f6f3e865cc78400ad198f)
+++ uspace/drv/bus/usb/xhci/commands.h	(revision 548c1238cba73184d31834477064377b71bc546c)
@@ -39,7 +39,7 @@
 #include <adt/list.h>
 #include <stdbool.h>
+#include "hw_struct/trb.h"
 
 typedef struct xhci_hc xhci_hc_t;
-typedef struct xhci_trb xhci_trb_t;
 typedef struct xhci_input_ctx xhci_input_ctx_t;
 
@@ -47,5 +47,6 @@
 	link_t link;
 
-	xhci_trb_t *trb;
+	xhci_trb_t trb;
+	uintptr_t trb_phys;
 	xhci_input_ctx_t *ictx;
 	uint32_t slot_id;
Index: uspace/drv/bus/usb/xhci/hw_struct/trb.h
===================================================================
--- uspace/drv/bus/usb/xhci/hw_struct/trb.h	(revision ab5a083027fa93e97b9f6f3e865cc78400ad198f)
+++ uspace/drv/bus/usb/xhci/hw_struct/trb.h	(revision 548c1238cba73184d31834477064377b71bc546c)
@@ -138,4 +138,9 @@
     dst->status = src->status;
     dst->control = src->control;
+}
+
+static inline void xhci_trb_clean(xhci_trb_t *trb)
+{
+	memset(trb, 0, sizeof(*trb));
 }
 
Index: uspace/drv/bus/usb/xhci/trb_ring.c
===================================================================
--- uspace/drv/bus/usb/xhci/trb_ring.c	(revision ab5a083027fa93e97b9f6f3e865cc78400ad198f)
+++ uspace/drv/bus/usb/xhci/trb_ring.c	(revision 548c1238cba73184d31834477064377b71bc546c)
@@ -164,11 +164,14 @@
  *
  * @param td the first TRB of TD
+ * @param phys returns address of the first TRB enqueued
  * @return EOK on success,
  *         EAGAIN when the ring is too full to fit all TRBs (temporary)
  */
-int xhci_trb_ring_enqueue(xhci_trb_ring_t *ring, xhci_trb_t *td)
+int xhci_trb_ring_enqueue(xhci_trb_ring_t *ring, xhci_trb_t *td, uintptr_t *phys)
 {
 	xhci_trb_t * const saved_enqueue_trb = ring->enqueue_trb;
 	trb_segment_t * const saved_enqueue_segment = ring->enqueue_segment;
+	if (phys)
+		*phys = NULL;
 
 	/*
@@ -189,4 +192,6 @@
 	ring->enqueue_segment = saved_enqueue_segment;
 	ring->enqueue_trb = saved_enqueue_trb;
+	if (phys)
+		*phys = trb_ring_enqueue_phys(ring);
 
 	/*
Index: uspace/drv/bus/usb/xhci/trb_ring.h
===================================================================
--- uspace/drv/bus/usb/xhci/trb_ring.h	(revision ab5a083027fa93e97b9f6f3e865cc78400ad198f)
+++ uspace/drv/bus/usb/xhci/trb_ring.h	(revision 548c1238cba73184d31834477064377b71bc546c)
@@ -72,5 +72,5 @@
 int xhci_trb_ring_init(xhci_trb_ring_t *, xhci_hc_t *);
 int xhci_trb_ring_fini(xhci_trb_ring_t *);
-int xhci_trb_ring_enqueue(xhci_trb_ring_t *, xhci_trb_t *);
+int xhci_trb_ring_enqueue(xhci_trb_ring_t *, xhci_trb_t *, uintptr_t *);
 
 /**
