Index: uspace/drv/bus/usb/xhci/bus.c
===================================================================
--- uspace/drv/bus/usb/xhci/bus.c	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/bus.c	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -33,5 +33,4 @@
  */
 
-#include <usb/host/utils/malloc32.h>
 #include <usb/host/ddf_helpers.h>
 #include <usb/host/endpoint.h>
Index: uspace/drv/bus/usb/xhci/commands.c
===================================================================
--- uspace/drv/bus/usb/xhci/commands.c	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/commands.c	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -37,5 +37,4 @@
 #include <str_error.h>
 #include <usb/debug.h>
-#include <usb/host/utils/malloc32.h>
 #include "commands.h"
 #include "debug.h"
@@ -57,5 +56,5 @@
  */
 #define TRB_SET_DEQUEUE_PTR(trb, dptr) (trb).parameter |= host2xhci(64, (dptr))
-#define TRB_SET_ICTX(trb, phys) (trb).parameter |= host2xhci(64, phys_addr & (~0xF))
+#define TRB_SET_ICTX(trb, phys) (trb).parameter |= host2xhci(64, (phys) & (~0xF))
 
 #define TRB_GET_CODE(trb) XHCI_DWORD_EXTRACT((trb).status, 31, 24)
@@ -99,11 +98,6 @@
 	list_remove(&cmd->_header.link);
 
-	if (cmd->input_ctx) {
-		free32(cmd->input_ctx);
-	};
-
-	if (cmd->bandwidth_ctx) {
-		free32(cmd->bandwidth_ctx);
-	}
+	dma_buffer_free(&cmd->input_ctx);
+	dma_buffer_free(&cmd->bandwidth_ctx);
 
 	if (cmd->_header.async) {
@@ -360,5 +354,5 @@
 	assert(hc);
 	assert(cmd);
-	assert(cmd->input_ctx);
+	assert(dma_buffer_is_set(&cmd->input_ctx));
 
 	/**
@@ -371,6 +365,5 @@
 	xhci_trb_clean(&cmd->_header.trb);
 
-	uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->input_ctx);
-	TRB_SET_ICTX(cmd->_header.trb, phys_addr);
+	TRB_SET_ICTX(cmd->_header.trb, cmd->input_ctx.phys);
 
 	/**
@@ -396,8 +389,7 @@
 	if (!cmd->deconfigure) {
 		/* If the DC flag is on, input context is not evaluated. */
-		assert(cmd->input_ctx);
-
-		uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->input_ctx);
-		TRB_SET_ICTX(cmd->_header.trb, phys_addr);
+		assert(dma_buffer_is_set(&cmd->input_ctx));
+
+		TRB_SET_ICTX(cmd->_header.trb, cmd->input_ctx.phys);
 	}
 
@@ -413,5 +405,5 @@
 	assert(hc);
 	assert(cmd);
-	assert(cmd->input_ctx);
+	assert(dma_buffer_is_set(&cmd->input_ctx));
 
 	/**
@@ -423,6 +415,5 @@
 	xhci_trb_clean(&cmd->_header.trb);
 
-	uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->input_ctx);
-	TRB_SET_ICTX(cmd->_header.trb, phys_addr);
+	TRB_SET_ICTX(cmd->_header.trb, cmd->input_ctx.phys);
 
 	TRB_SET_TYPE(cmd->_header.trb, XHCI_TRB_TYPE_EVALUATE_CONTEXT_CMD);
@@ -506,6 +497,5 @@
 	xhci_trb_clean(&cmd->_header.trb);
 
-	uint64_t phys_addr = (uint64_t) addr_to_phys(cmd->bandwidth_ctx);
-	TRB_SET_ICTX(cmd->_header.trb, phys_addr);
+	TRB_SET_ICTX(cmd->_header.trb, cmd->bandwidth_ctx.phys);
 
 	TRB_SET_TYPE(cmd->_header.trb, XHCI_TRB_TYPE_GET_PORT_BANDWIDTH_CMD);
Index: uspace/drv/bus/usb/xhci/commands.h
===================================================================
--- uspace/drv/bus/usb/xhci/commands.h	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/commands.h	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -40,4 +40,5 @@
 #include <stdbool.h>
 #include <fibril_synch.h>
+#include <usb/host/dma_buffer.h>
 #include "hw_struct/trb.h"
 
@@ -93,6 +94,5 @@
 	uint16_t stream_id;
 
-	xhci_input_ctx_t *input_ctx;
-	xhci_port_bandwidth_ctx_t *bandwidth_ctx;
+	dma_buffer_t input_ctx, bandwidth_ctx;
 	uintptr_t dequeue_ptr;
 
Index: uspace/drv/bus/usb/xhci/endpoint.c
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.c	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/endpoint.c	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -34,5 +34,4 @@
  */
 
-#include <usb/host/utils/malloc32.h>
 #include <usb/host/endpoint.h>
 #include <usb/descriptor.h>
@@ -135,5 +134,5 @@
 
 	XHCI_EP_MAX_P_STREAMS_SET(*ctx, pstreams);
-	XHCI_EP_TR_DPTR_SET(*ctx, addr_to_phys(xhci_ep->primary_stream_ctx_array));
+	XHCI_EP_TR_DPTR_SET(*ctx, xhci_ep->primary_stream_ctx_dma.phys);
 	// TODO: set HID?
 	XHCI_EP_LSA_SET(*ctx, 1);
@@ -167,12 +166,11 @@
 		usb_log_debug2("Allocating primary stream context array of size %u for endpoint " XHCI_EP_FMT,
 			count, XHCI_EP_ARGS(*xhci_ep));
-		xhci_ep->primary_stream_ctx_array = malloc32(count * sizeof(xhci_stream_ctx_t));
-		if (!xhci_ep->primary_stream_ctx_array) {
+		if ((dma_buffer_alloc(&xhci_ep->primary_stream_ctx_dma, count * sizeof(xhci_stream_ctx_t))))
 			return ENOMEM;
-		}
+		xhci_ep->primary_stream_ctx_array = xhci_ep->primary_stream_ctx_dma.virt;
 
 		xhci_ep->primary_stream_rings = calloc(count, sizeof(xhci_trb_ring_t));
 		if (!xhci_ep->primary_stream_rings) {
-			free32(xhci_ep->primary_stream_ctx_array);
+			dma_buffer_free(&xhci_ep->primary_stream_ctx_dma);
 			return ENOMEM;
 		}
@@ -227,5 +225,5 @@
 			// FIXME: Get the trb ring associated with stream [index] and fini it
 		}
-		free32(xhci_ep->primary_stream_ctx_array);
+		dma_buffer_free(&xhci_ep->primary_stream_ctx_dma);
 	} else {
 		usb_log_debug2("Freeing main transfer ring of endpoint " XHCI_EP_FMT, XHCI_EP_ARGS(*xhci_ep));
Index: uspace/drv/bus/usb/xhci/endpoint.h
===================================================================
--- uspace/drv/bus/usb/xhci/endpoint.h	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/endpoint.h	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -40,4 +40,5 @@
 
 #include <usb/debug.h>
+#include <usb/host/dma_buffer.h>
 #include <usb/host/endpoint.h>
 #include <usb/host/hcd.h>
@@ -72,4 +73,5 @@
 	/** Primary stream context array (or NULL if endpoint doesn't use streams). */
 	xhci_stream_ctx_t *primary_stream_ctx_array;
+	dma_buffer_t primary_stream_ctx_dma;
 
 	/** Primary stream ring array (or NULL if endpoint doesn't use streams). */
@@ -111,6 +113,6 @@
 	uint32_t route_str;
 
-	/** Place to store virtual address for allocated context */
-	xhci_device_ctx_t *dev_ctx;
+	/** Place to store the allocated context */
+	dma_buffer_t dev_ctx;
 
 	/** All endpoints of the device. Dropped ones are NULL */
Index: uspace/drv/bus/usb/xhci/hc.c
===================================================================
--- uspace/drv/bus/usb/xhci/hc.c	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/hc.c	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -38,5 +38,4 @@
 #include <usb/debug.h>
 #include <usb/host/endpoint.h>
-#include <usb/host/utils/malloc32.h>
 #include "debug.h"
 #include "hc.h"
@@ -201,7 +200,7 @@
 	int err;
 
-	hc->dcbaa = malloc32((1 + hc->max_slots) * sizeof(uint64_t));
-	if (!hc->dcbaa)
+	if (dma_buffer_alloc(&hc->dcbaa_dma, (1 + hc->max_slots) * sizeof(uint64_t)))
 		return ENOMEM;
+	hc->dcbaa = hc->dcbaa_dma.virt;
 
 	if ((err = xhci_trb_ring_init(&hc->command_ring)))
@@ -237,5 +236,6 @@
 	xhci_trb_ring_fini(&hc->command_ring);
 err_dcbaa:
-	free32(hc->dcbaa);
+	hc->dcbaa = NULL;
+	dma_buffer_free(&hc->dcbaa_dma);
 	return err;
 }
@@ -402,5 +402,5 @@
 		async_usleep(1000);
 
-	uint64_t dcbaaptr = addr_to_phys(hc->dcbaa);
+	uint64_t dcbaaptr = hc->dcbaa_dma.phys;
 	XHCI_REG_WR(hc->op_regs, XHCI_OP_DCBAAP_LO, LOWER32(dcbaaptr));
 	XHCI_REG_WR(hc->op_regs, XHCI_OP_DCBAAP_HI, UPPER32(dcbaaptr));
@@ -411,10 +411,10 @@
 	XHCI_REG_WR(hc->op_regs, XHCI_OP_CRCR_HI, UPPER32(crptr));
 
-	uint64_t erstptr = addr_to_phys(hc->event_ring.erst);
-	uint64_t erdp = hc->event_ring.dequeue_ptr;
 	xhci_interrupter_regs_t *intr0 = &hc->rt_regs->ir[0];
 	XHCI_REG_WR(intr0, XHCI_INTR_ERSTSZ, hc->event_ring.segment_count);
+	uint64_t erdp = hc->event_ring.dequeue_ptr;
 	XHCI_REG_WR(intr0, XHCI_INTR_ERDP_LO, LOWER32(erdp));
 	XHCI_REG_WR(intr0, XHCI_INTR_ERDP_HI, UPPER32(erdp));
+	uint64_t erstptr = hc->event_ring.erst.phys;
 	XHCI_REG_WR(intr0, XHCI_INTR_ERSTBA_LO, LOWER32(erstptr));
 	XHCI_REG_WR(intr0, XHCI_INTR_ERSTBA_HI, UPPER32(erstptr));
@@ -572,5 +572,5 @@
 {
 	xhci_scratchpad_free(hc);
-	free32(hc->dcbaa);
+	dma_buffer_free(&hc->dcbaa_dma);
 }
 
@@ -628,8 +628,5 @@
 	/* Free the device context. */
 	hc->dcbaa[dev->slot_id] = 0;
-	if (dev->dev_ctx) {
-		free32(dev->dev_ctx);
-		dev->dev_ctx = NULL;
-	}
+	dma_buffer_free(&dev->dev_ctx);
 
 	/* Mark the slot as invalid. */
@@ -639,11 +636,11 @@
 }
 
-static int create_valid_input_ctx(xhci_input_ctx_t **out_ictx)
-{
-	xhci_input_ctx_t *ictx = malloc32(sizeof(xhci_input_ctx_t));
-	if (!ictx) {
-		return ENOMEM;
-	}
-
+static int create_valid_input_ctx(dma_buffer_t *dma_buf)
+{
+	const int err = dma_buffer_alloc(dma_buf, sizeof(xhci_input_ctx_t));
+	if (err)
+		return err;
+
+	xhci_input_ctx_t *ictx = dma_buf->virt;
 	memset(ictx, 0, sizeof(xhci_input_ctx_t));
 
@@ -654,8 +651,4 @@
 	XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, 0);
 
-	if (out_ictx) {
-		*out_ictx = ictx;
-	}
-
 	return EOK;
 }
@@ -675,16 +668,16 @@
 
 	/* Setup and register device context */
-	dev->dev_ctx = malloc32(sizeof(xhci_device_ctx_t));
-	if (!dev->dev_ctx)
+	if (dma_buffer_alloc(&dev->dev_ctx, sizeof(xhci_device_ctx_t)))
 		goto err;
-	memset(dev->dev_ctx, 0, sizeof(xhci_device_ctx_t));
-
-	hc->dcbaa[dev->slot_id] = addr_to_phys(dev->dev_ctx);
+	memset(dev->dev_ctx.virt, 0, sizeof(xhci_device_ctx_t));
+
+	hc->dcbaa[dev->slot_id] = host2xhci(64, dev->dev_ctx.phys);
 
 	/* Issue configure endpoint command (sec 4.3.5). */
-	xhci_input_ctx_t *ictx;
-	if ((err = create_valid_input_ctx(&ictx))) {
+	dma_buffer_t ictx_dma_buf;
+	if ((err = create_valid_input_ctx(&ictx_dma_buf))) {
 		goto err_dev_ctx;
 	}
+	xhci_input_ctx_t *ictx = ictx_dma_buf.virt;
 
 	/* Initialize slot_ctx according to section 4.3.3 point 3. */
@@ -705,9 +698,10 @@
 
 	/* Issue Address Device command. */
-	if ((err = xhci_cmd_sync_inline(hc, ADDRESS_DEVICE, .slot_id = dev->slot_id, .input_ctx = ictx))) {
+	if ((err = xhci_cmd_sync_inline(hc, ADDRESS_DEVICE, .slot_id = dev->slot_id, .input_ctx = ictx_dma_buf))) {
 		goto err_dev_ctx;
 	}
 
-	dev->base.address = XHCI_SLOT_DEVICE_ADDRESS(dev->dev_ctx->slot_ctx);
+	xhci_device_ctx_t *dev_ctx = dev->dev_ctx.virt;
+	dev->base.address = XHCI_SLOT_DEVICE_ADDRESS(dev_ctx->slot_ctx);
 	usb_log_debug2("Obtained USB address: %d.\n", dev->base.address);
 
@@ -720,6 +714,6 @@
 
 err_dev_ctx:
-	free32(dev->dev_ctx);
 	hc->dcbaa[dev->slot_id] = 0;
+	dma_buffer_free(&dev->dev_ctx);
 err:
 	return err;
@@ -729,6 +723,6 @@
 {
 	/* Issue configure endpoint command (sec 4.3.5). */
-	xhci_input_ctx_t *ictx;
-	const int err = create_valid_input_ctx(&ictx);
+	dma_buffer_t ictx_dma_buf;
+	const int err = create_valid_input_ctx(&ictx_dma_buf);
 	if (err)
 		return err;
@@ -736,5 +730,5 @@
 	// TODO: Set slot context and other flags. (probably forgot a lot of 'em)
 
-	return xhci_cmd_sync_inline(hc, CONFIGURE_ENDPOINT, .slot_id = slot_id, .input_ctx = ictx);
+	return xhci_cmd_sync_inline(hc, CONFIGURE_ENDPOINT, .slot_id = slot_id, .input_ctx = ictx_dma_buf);
 }
 
@@ -748,14 +742,15 @@
 {
 	/* Issue configure endpoint command (sec 4.3.5). */
-	xhci_input_ctx_t *ictx;
-	const int err = create_valid_input_ctx(&ictx);
+	dma_buffer_t ictx_dma_buf;
+	const int err = create_valid_input_ctx(&ictx_dma_buf);
 	if (err)
 		return err;
 
+	xhci_input_ctx_t *ictx = ictx_dma_buf.virt;
 	XHCI_INPUT_CTRL_CTX_ADD_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */
 	memcpy(&ictx->endpoint_ctx[ep_idx], ep_ctx, sizeof(xhci_ep_ctx_t));
 	// TODO: Set slot context and other flags. (probably forgot a lot of 'em)
 
-	return xhci_cmd_sync_inline(hc, CONFIGURE_ENDPOINT, .slot_id = slot_id, .input_ctx = ictx);
+	return xhci_cmd_sync_inline(hc, CONFIGURE_ENDPOINT, .slot_id = slot_id, .input_ctx = ictx_dma_buf);
 }
 
@@ -763,13 +758,14 @@
 {
 	/* Issue configure endpoint command (sec 4.3.5). */
-	xhci_input_ctx_t *ictx;
-	const int err = create_valid_input_ctx(&ictx);
+	dma_buffer_t ictx_dma_buf;
+	const int err = create_valid_input_ctx(&ictx_dma_buf);
 	if (err)
 		return err;
 
+	xhci_input_ctx_t *ictx = ictx_dma_buf.virt;
 	XHCI_INPUT_CTRL_CTX_DROP_SET(ictx->ctrl_ctx, ep_idx + 1); /* Preceded by slot ctx */
 	// TODO: Set slot context and other flags. (probably forgot a lot of 'em)
 
-	return xhci_cmd_sync_inline(hc, CONFIGURE_ENDPOINT, .slot_id = slot_id, .input_ctx = ictx);
+	return xhci_cmd_sync_inline(hc, CONFIGURE_ENDPOINT, .slot_id = slot_id, .input_ctx = ictx_dma_buf);
 }
 
Index: uspace/drv/bus/usb/xhci/hc.h
===================================================================
--- uspace/drv/bus/usb/xhci/hc.h	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/hc.h	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -64,5 +64,7 @@
 	xhci_event_ring_t event_ring;
 	uint64_t *dcbaa;
-	xhci_scratchpad_t *scratchpad;
+	dma_buffer_t dcbaa_dma;
+	dma_buffer_t scratchpad_array;
+	dma_buffer_t *scratchpad_buffers;
 
 	/* Root hub emulation */
Index: uspace/drv/bus/usb/xhci/rh.c
===================================================================
--- uspace/drv/bus/usb/xhci/rh.c	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/rh.c	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -38,7 +38,7 @@
 #include <usb/request.h>
 #include <usb/debug.h>
-#include <usb/host/utils/malloc32.h>
 #include <usb/host/bus.h>
 #include <usb/host/ddf_helpers.h>
+#include <usb/host/dma_buffer.h>
 #include <usb/host/hcd.h>
 
@@ -305,5 +305,8 @@
 }
 
-static inline int get_hub_available_bandwidth(xhci_hc_t *hc, xhci_device_t* dev, uint8_t speed, xhci_port_bandwidth_ctx_t *ctx) {
+static inline int get_hub_available_bandwidth(xhci_hc_t *hc, xhci_device_t* dev, uint8_t speed, xhci_port_bandwidth_ctx_t *ctx)
+{
+	int err = EOK;
+
 	// TODO: find a correct place for this function + API
 	// We need speed, because a root hub device has both USB 2 and USB 3 speeds
@@ -313,25 +316,20 @@
 	assert(ctx);
 
-	xhci_port_bandwidth_ctx_t *in_ctx = malloc32(sizeof(xhci_port_bandwidth_ctx_t));
-	if (!in_ctx) {
-		return ENOMEM;
-	}
-
 	xhci_cmd_t cmd;
 	xhci_cmd_init(&cmd, XHCI_CMD_GET_PORT_BANDWIDTH);
 
-	cmd.bandwidth_ctx = in_ctx;
+	if ((err = dma_buffer_alloc(&cmd.bandwidth_ctx, sizeof(xhci_port_bandwidth_ctx_t))))
+		goto end;
+
 	cmd.device_speed = speed;
 
-	int err;
-	if ((err = xhci_cmd_sync(hc, &cmd))) {
+	if ((err = xhci_cmd_sync(hc, &cmd)))
 		goto end;
-	}
-
-	memcpy(ctx, in_ctx, sizeof(xhci_port_bandwidth_ctx_t));
+
+	memcpy(ctx, cmd.bandwidth_ctx.virt, sizeof(xhci_port_bandwidth_ctx_t));
 
 end:
 	xhci_cmd_fini(&cmd);
-	return EOK;
+	return err;
 }
 
Index: uspace/drv/bus/usb/xhci/scratchpad.c
===================================================================
--- uspace/drv/bus/usb/xhci/scratchpad.c	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/scratchpad.c	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -36,5 +36,4 @@
 #include <errno.h>
 #include <usb/debug.h>
-#include <usb/host/utils/malloc32.h>
 #include "hc.h"
 #include "hw_struct/regs.h"
@@ -53,45 +52,28 @@
 int xhci_scratchpad_alloc(xhci_hc_t *hc)
 {
-	unsigned num_bufs, allocated;
-	xhci_scratchpad_t *bufs;
-
-	num_bufs = xhci_scratchpad_count(hc);
+	const unsigned num_bufs = xhci_scratchpad_count(hc);
 
 	if (!num_bufs)
 		return EOK;
 
-	bufs = malloc32(sizeof(xhci_scratchpad_t));
-	if (!bufs)
+	if (dma_buffer_alloc(&hc->scratchpad_array, num_bufs * sizeof(uint64_t)))
 		return ENOMEM;
+	uint64_t *phys_array = hc->scratchpad_array.virt;
 
-	allocated = 0;
+	hc->dcbaa[0] = host2xhci(64, hc->scratchpad_array.phys);
 
-	uint64_t *phys_array = malloc32(num_bufs * sizeof(uint64_t));
-	if (phys_array == NULL)
-		goto err_phys_array;
-
-	uint64_t *virt_array = malloc32(num_bufs * sizeof(uint64_t));
-	if (virt_array == NULL)
-		goto err_virt_array;
+	hc->scratchpad_buffers = calloc(num_bufs, sizeof(dma_buffer_t));
+	if (!hc->scratchpad_buffers)
+		goto err_dma;
 
 	for (unsigned i = 0; i < num_bufs; ++i) {
-		void *buf = malloc32(PAGE_SIZE);
-		phys_array[i] = host2xhci(64, (uint64_t) addr_to_phys(buf));
-		virt_array[i] = (uint64_t) buf;
+		dma_buffer_t *cur = &hc->scratchpad_buffers[i];
+		if (dma_buffer_alloc(cur, PAGE_SIZE))
+			goto err_buffers;
 
-		if (buf != NULL)
-			++allocated;
-		else
-			goto err_page_alloc;
-
-		memset(buf, 0, PAGE_SIZE);
+		memset(cur->virt, 0, PAGE_SIZE);
+		phys_array[i] = host2xhci(64, cur->phys);
 	}
 
-	bufs->phys_ptr = host2xhci(64, (uint64_t) addr_to_phys(phys_array));
-	bufs->virt_ptr = (uint64_t) virt_array;
-	bufs->phys_bck = (uint64_t) phys_array;
-
-	hc->dcbaa[0] = bufs->phys_ptr;
-	hc->scratchpad = bufs;
 
 	usb_log_debug2("Allocated %d scratchpad buffers.", num_bufs);
@@ -99,15 +81,11 @@
 	return EOK;
 
-err_page_alloc:
-	for (unsigned i = 0; i < allocated; ++i)
-		free32((void *) virt_array[i]);
-	free32(virt_array);
-
-err_virt_array:
-	free32(phys_array);
-
-err_phys_array:
-	free32(bufs);
-
+err_buffers:
+	for (unsigned i = 0; i < num_bufs; ++i)
+		dma_buffer_free(&hc->scratchpad_buffers[i]);
+	free(hc->scratchpad_buffers);
+err_dma:
+	hc->dcbaa[0] = 0;
+	dma_buffer_free(&hc->scratchpad_array);
 	return ENOMEM;
 }
@@ -115,22 +93,14 @@
 void xhci_scratchpad_free(xhci_hc_t *hc)
 {
-	unsigned num_bufs;
-	xhci_scratchpad_t *scratchpad;
-	uint64_t *virt_array;
+	const unsigned num_bufs = xhci_scratchpad_count(hc);
 
-	num_bufs = xhci_scratchpad_count(hc);
 	if (!num_bufs)
 		return;
 
-	scratchpad =  hc->scratchpad;
-	virt_array = (uint64_t *) scratchpad->virt_ptr;
-
+	hc->dcbaa[0] = 0;
+	dma_buffer_free(&hc->scratchpad_array);
 	for (unsigned i = 0; i < num_bufs; ++i)
-		free32((void *) virt_array[i]);
-	free32((void *) scratchpad->virt_ptr);
-	free32((void *) scratchpad->phys_bck);
-
-	hc->dcbaa[0] = 0;
-
+		dma_buffer_free(&hc->scratchpad_buffers[i]);
+	free(hc->scratchpad_buffers);
 	return;
 }
Index: uspace/drv/bus/usb/xhci/scratchpad.h
===================================================================
--- uspace/drv/bus/usb/xhci/scratchpad.h	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/scratchpad.h	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -41,14 +41,7 @@
 #define XHCI_SCRATCHPAD_H
 
+#include <usb/host/dma_buffer.h>
+
 typedef struct xhci_hc xhci_hc_t;
-
-typedef struct xhci_scratchpad {
-	/* Pointers to scratchpad buffers used by the xHC. */
-	uint64_t phys_ptr;
-	/* Pointers to scratchpad buffers used for deallocation. */
-	uint64_t virt_ptr;
-	/* Pointers to the scratchpad array used for deallocation. */
-	uint64_t phys_bck;
-} xhci_scratchpad_t;
 
 int xhci_scratchpad_alloc(xhci_hc_t *);
Index: uspace/drv/bus/usb/xhci/transfers.c
===================================================================
--- uspace/drv/bus/usb/xhci/transfers.c	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/transfers.c	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -34,5 +34,4 @@
  */
 
-#include <usb/host/utils/malloc32.h>
 #include <usb/debug.h>
 #include <usb/request.h>
@@ -113,6 +112,5 @@
 	assert(transfer);
 
-	if (transfer->hc_buffer)
-		free32(transfer->hc_buffer);
+	dma_buffer_free(&transfer->hc_buffer);
 }
 
@@ -156,5 +154,5 @@
 		xhci_trb_clean(trb_data);
 
-		trb_data->parameter = addr_to_phys(transfer->hc_buffer);
+		trb_data->parameter = host2xhci(64, transfer->hc_buffer.phys);
 
 		// data size (sent for OUT, or buffer size)
@@ -196,5 +194,5 @@
 	xhci_trb_t trb;
 	xhci_trb_clean(&trb);
-	trb.parameter = addr_to_phys(transfer->hc_buffer);
+	trb.parameter = host2xhci(64, transfer->hc_buffer.phys);
 
 	// data size (sent for OUT, or buffer size)
@@ -217,5 +215,5 @@
 	xhci_trb_t trb;
 	xhci_trb_clean(&trb);
-	trb.parameter = addr_to_phys(transfer->hc_buffer);
+	trb.parameter = host2xhci(64, transfer->hc_buffer.phys);
 
 	// data size (sent for OUT, or buffer size)
@@ -282,5 +280,5 @@
 		assert(batch->buffer);
 		assert(batch->transfered_size <= batch->buffer_size);
-		memcpy(batch->buffer, transfer->hc_buffer, batch->transfered_size);
+		memcpy(batch->buffer, transfer->hc_buffer.virt, batch->transfered_size);
 	}
 
@@ -324,6 +322,5 @@
 
 	if (batch->buffer_size > 0) {
-		transfer->hc_buffer = malloc32(batch->buffer_size);
-		if (!transfer->hc_buffer)
+		if (dma_buffer_alloc(&transfer->hc_buffer, batch->buffer_size))
 			return ENOMEM;
 	}
@@ -331,5 +328,5 @@
 	if (batch->dir != USB_DIRECTION_IN) {
 		// Sending stuff from host to device, we need to copy the actual data.
-		memcpy(transfer->hc_buffer, batch->buffer, batch->buffer_size);
+		memcpy(transfer->hc_buffer.virt, batch->buffer, batch->buffer_size);
 	}
 
Index: uspace/drv/bus/usb/xhci/transfers.h
===================================================================
--- uspace/drv/bus/usb/xhci/transfers.h	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/transfers.h	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -50,6 +50,5 @@
 	uint8_t direction;
 
-	void* hc_buffer;                    /* Virtual address of the buffer start. */
-	uintptr_t hc_buffer_phys;
+	dma_buffer_t hc_buffer;
 
 	uintptr_t interrupt_trb_phys;
Index: uspace/drv/bus/usb/xhci/trb_ring.c
===================================================================
--- uspace/drv/bus/usb/xhci/trb_ring.c	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/trb_ring.c	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -33,5 +33,4 @@
 #include <align.h>
 #include <usb/debug.h>
-#include <usb/host/utils/malloc32.h>
 #include "hw_struct/trb.h"
 #include "trb_ring.h"
@@ -68,22 +67,23 @@
  * to DMAMEM_4GiB.
  */
-static int trb_segment_allocate(trb_segment_t **segment)
-{
-	uintptr_t phys;
-	int err;
-
-	*segment = AS_AREA_ANY;
-	err = dmamem_map_anonymous(PAGE_SIZE,
-	    DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0, &phys,
-	    (void *) segment);
-
-	if (err == EOK) {
-		memset(*segment, 0, PAGE_SIZE);
-		(*segment)->phys = phys;
-
-		usb_log_debug2("Allocated new ring segment.");
-	}
-
-	return err;
+static int trb_segment_alloc(trb_segment_t **segment)
+{
+	dma_buffer_t dbuf;
+
+	const int err = dma_buffer_alloc(&dbuf, PAGE_SIZE);
+	if (err)
+		return err;
+
+	*segment = dbuf.virt;
+	memset(*segment, 0, PAGE_SIZE);
+	(*segment)->phys = dbuf.phys;
+	usb_log_debug2("Allocated new ring segment.");
+	return EOK;
+}
+
+static void trb_segment_free(trb_segment_t *segment)
+{
+	dma_buffer_t dbuf = { .virt = segment, .phys = segment->phys };
+	dma_buffer_free(&dbuf);
 }
 
@@ -99,5 +99,5 @@
 	list_initialize(&ring->segments);
 
-	if ((err = trb_segment_allocate(&segment)) != EOK)
+	if ((err = trb_segment_alloc(&segment)) != EOK)
 		return err;
 
@@ -127,5 +127,5 @@
 	list_foreach_safe(ring->segments, cur, next) {
 		trb_segment_t *segment = list_get_instance(cur, trb_segment_t, segments_link);
-		dmamem_unmap_anonymous(segment);
+		trb_segment_free(segment);
 	}
 }
@@ -264,5 +264,5 @@
 	list_initialize(&ring->segments);
 
-	if ((err = trb_segment_allocate(&segment)) != EOK)
+	if ((err = trb_segment_alloc(&segment)) != EOK)
 		return err;
 
@@ -274,10 +274,10 @@
 	ring->dequeue_ptr = segment->phys;
 
-	ring->erst = malloc32(PAGE_SIZE);
-	if (ring->erst == NULL)
+	if (dma_buffer_alloc(&ring->erst, PAGE_SIZE))
 		return ENOMEM;
-	memset(ring->erst, 0, PAGE_SIZE);
-
-	xhci_fill_erst_entry(&ring->erst[0], segment->phys, SEGMENT_TRB_COUNT);
+	xhci_erst_entry_t *erst = ring->erst.virt;
+
+	memset(erst, 0, PAGE_SIZE);
+	xhci_fill_erst_entry(&erst[0], segment->phys, SEGMENT_TRB_COUNT);
 
 	ring->ccs = 1;
@@ -297,6 +297,5 @@
 	}
 
-	if (ring->erst)
-		free32(ring->erst);
+	dma_buffer_free(&ring->erst);
 }
 
Index: uspace/drv/bus/usb/xhci/trb_ring.h
===================================================================
--- uspace/drv/bus/usb/xhci/trb_ring.h	(revision cfe485248470eaa3e68e053d375e4c11a7b486e9)
+++ uspace/drv/bus/usb/xhci/trb_ring.h	(revision b80c1ab4fd7df617a684e9fc7af13b2626a47d6e)
@@ -46,4 +46,5 @@
 #include <fibril_synch.h>
 #include <libarch/config.h>
+#include <usb/host/dma_buffer.h>
 
 typedef struct trb_segment trb_segment_t;
@@ -104,5 +105,5 @@
 	uintptr_t dequeue_ptr;          /* Physical address of the ERDP to be reported to the HC */
 
-	xhci_erst_entry_t *erst;        /* ERST given to the HC */
+	dma_buffer_t erst;              /* ERST given to the HC */
 
 	bool ccs;                       /* Consumer Cycle State: section 4.9.2 */
