Index: uspace/drv/bus/usb/xhci/Makefile
===================================================================
--- uspace/drv/bus/usb/xhci/Makefile	(revision 5119d344096203503fefb679bf5917fe4631b2c0)
+++ uspace/drv/bus/usb/xhci/Makefile	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
@@ -40,4 +40,5 @@
 
 SOURCES = \
+	trb_ring.c \
 	main.c
 
Index: uspace/drv/bus/usb/xhci/hw_struct/README
===================================================================
--- uspace/drv/bus/usb/xhci/hw_struct/README	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
+++ uspace/drv/bus/usb/xhci/hw_struct/README	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
@@ -0,0 +1,3 @@
+This folder contains hardware communication structures and constants, as defined
+in chapter 6 of the xHCI specification. It shall not be modified, as it reflects
+the order hardware expects it.
Index: uspace/drv/bus/usb/xhci/hw_struct/context.h
===================================================================
--- uspace/drv/bus/usb/xhci/hw_struct/context.h	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
+++ uspace/drv/bus/usb/xhci/hw_struct/context.h	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017 Ondrej Hlavaty <aearsis@eideo.cz>
+ * 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.
+ */
+
+/** @addtogroup drvusbxhci
+ * @{
+ */
+/** @file
+ * Context data structures of the xHC.
+ *
+ * Most of them are to be initialized to zero and passed ownership to the HC,
+ * so they are mostly read-only.
+ *
+ * Feel free to write a setter when in need.
+ */
+
+#ifndef XHCI_CONTEXT_H
+#define XHCI_CONTEXT_H
+
+#include <stdint.h>
+#include <common.h>
+
+/**
+ * Endpoint context: section 6.2.3
+ */
+typedef struct xhci_endpoint_ctx {
+	xhci_dword_t data[5];
+	xhci_dword_t reserved[3];
+
+#define XHCI_EP_STATE(ctx)              XHCI_DWORD_EXTRACT((ctx).data[0],  2,  0)
+#define XHCI_EP_MULT(ctx)               XHCI_DWORD_EXTRACT((ctx).data[0],  9,  8)
+#define XHCI_EP_MAX_P_STREAMS(ctx)      XHCI_DWORD_EXTRACT((ctx).data[0], 14, 10)
+#define XHCI_EP_LSA(ctx)                XHCI_DWORD_EXTRACT((ctx).data[0], 15, 15)
+#define XHCI_EP_INTERVAL(ctx)           XHCI_DWORD_EXTRACT((ctx).data[0], 23, 16)
+
+#define XHCI_EP_ERROR_COUNT(ctx)        XHCI_DWORD_EXTRACT((ctx).data[1],  2,  1)
+#define XHCI_EP_TYPE(ctx)               XHCI_DWORD_EXTRACT((ctx).data[1],  5,  3)
+#define XHCI_EP_HID(ctx)                XHCI_DWORD_EXTRACT((ctx).data[1],  7,  7)
+#define XHCI_EP_MAX_BURST_SIZE(ctx)     XHCI_DWORD_EXTRACT((ctx).data[1], 15,  8)
+#define XHCI_EP_MAX_PACKET_SIZE(ctx)    XHCI_DWORD_EXTRACT((ctx).data[1], 31, 16)
+
+#define XHCI_EP_DCS(ctx)                XHCI_DWORD_EXTRACT((ctx).data[2],  0,  0)
+#define XHCI_EP_TR_DPTR(ctx)            XHCI_DWORD_EXTRACT((ctx).data[2], 63,  4)
+
+} ep_ctx_t;
+
+/**
+ * Slot context: section 6.2.2
+ */
+typedef struct xhci_slot_ctx {
+	xhci_dword_t data [4];
+	xhci_dword_t reserved [4];
+
+#define XHCI_SLOT_ROUTE_STRING(ctx)     XHCI_DWORD_EXTRACT((ctx).data[0], 19,  0)
+#define XHCI_SLOT_SPEED(ctx)            XHCI_DWORD_EXTRACT((ctx).data[0], 23, 20)
+#define XHCI_SLOT_MTT(ctx)              XHCI_DWORD_EXTRACT((ctx).data[0], 25, 25)
+#define XHCI_SLOT_CTX_ENTRIES(ctx)      XHCI_DWORD_EXTRACT((ctx).data[0], 31, 27)
+
+#define XHCI_SLOT_MAX_EXIT_LATENCY(ctx) XHCI_DWORD_EXTRACT((ctx).data[1], 15,  0)
+#define XHCI_SLOT_ROOT_HUB_PORT(ctx)    XHCI_DWORD_EXTRACT((ctx).data[1], 23, 16)
+#define XHCI_SLOT_NUM_OF_PORTS(ctx)     XHCI_DWORD_EXTRACT((ctx).data[1], 31, 24)
+
+#define XHCI_SLOT_TT_HUB_SLOT_ID(ctx)   XHCI_DWORD_EXTRACT((ctx).data[2],  7,  0)
+#define XHCI_SLOT_TT_PORT_NUM(ctx)      XHCI_DWORD_EXTRACT((ctx).data[2], 15,  8)
+#define XHCI_SLOT_TT_THINK_TIME(ctx)    XHCI_DWORD_EXTRACT((ctx).data[2], 17, 16)
+#define XHCI_SLOT_INTERRUPTER(ctx)      XHCI_DWORD_EXTRACT((ctx).data[2], 31, 22)
+
+#define XHCI_SLOT_DEVICE_ADDRESS(ctx)   XHCI_DWORD_EXTRACT((ctx).data[3],  7,  0)
+#define XHCI_SLOT_SLOT_STATE(ctx)       XHCI_DWORD_EXTRACT((ctx).data[3], 31, 27)
+
+} xhci_slot_ctx_t;
+
+/**
+ * Device context: section 6.2.1
+ */
+typedef struct xhci_device_ctx {
+	xhci_slot_ctx_t slot_ctx;
+	xhci_ep_ctx_t endpoint_ctx [31];
+} xhci_device_ctx_t;
+
+/**
+ * Stream context: section 6.2.4 {
+ */
+typedef struct xhci_stream_ctx {
+	uint64_t data [2];
+} xhci_stream_ctx_t;
+
+#endif
Index: uspace/drv/bus/usb/xhci/hw_struct/trb.h
===================================================================
--- uspace/drv/bus/usb/xhci/hw_struct/trb.h	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
+++ uspace/drv/bus/usb/xhci/hw_struct/trb.h	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2017 Ondrej Hlavaty
+ * 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.
+ */
+
+/** @addtogroup drvusbxhci
+ * @{
+ */
+/** @file
+ * TRB-related structures of the xHC.
+ *
+ * This file contains all the types of TRB and the TRB ring handling.
+ */
+
+#ifndef XHCI_TRB_H
+#define XHCI_TRB_H
+
+#include "common.h"
+
+/**
+ * TRB types: section 6.4.6, table 139
+ */
+enum xhci_trb_type {
+	XHCI_TRB_TYPE_RESERVED = 0,
+
+// Transfer ring:
+	XHCI_TRB_TYPE_NORMAL,
+	XHCI_TRB_TYPE_SETUP_STAGE,
+	XHCI_TRB_TYPE_DATA_STAGE,
+	XHCI_TRB_TYPE_STATUS_STAGE,
+	XHCI_TRB_TYPE_ISOCH,
+	XHCI_TRB_TYPE_LINK,
+	XHCI_TRB_TYPE_EVENT_DATA,
+	XHCI_TRB_TYPE_NO_OP,
+
+// Command ring:
+	XHCI_TRB_TYPE_ENABLE_SLOT_CMD,
+	XHCI_TRB_TYPE_DISABLE_SLOT_CMD,
+	XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD,
+	XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD,
+	XHCI_TRB_TYPE_EVALUATE_CONTEXT_CMD,
+	XHCI_TRB_TYPE_RESET_ENDPOINT_CMD,
+	XHCI_TRB_TYPE_STOP_ENDPOINT_CMD,
+	XHCI_TRB_TYPE_SET_TR_DEQUEUE_POINTER_CMD,
+	XHCI_TRB_TYPE_RESET_DEVICE_CMD,
+	XHCI_TRB_TYPE_FORCE_EVENT_CMD,
+	XHCI_TRB_TYPE_NEGOTIATE_BANDWIDTH_CMD,
+	XHCI_TRB_TYPE_SET_LATENCY_TOLERANCE_VALUE_CMD,
+	XHCI_TRB_TYPE_GET_PORT_BANDWIDTH_CMD,
+	XHCI_TRB_TYPE_FORCE_HEADER_CMD,
+	XHCI_TRB_TYPE_NO_OP_CMD,
+// Reserved: 24-31
+
+// Event ring:
+	XHCI_TRB_TYPE_TRANSFER_EVENT = 32,
+	XHCI_TRB_TYPE_COMMAND_COMPLETION_EVENT,
+	XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVENT,
+	XHCI_TRB_TYPE_BANDWIDTH_REQUEST_EVENT,
+	XHCI_TRB_TYPE_DOORBELL_EVENT,
+	XHCI_TRB_TYPE_HOST_CONTROLLER_EVENT,
+	XHCI_TRB_TYPE_DEVICE_NOTIFICATION_EVENT,
+	XHCI_TRB_TYPE_MFINDEX_WRAP_EVENT,
+};
+
+/**
+ * TRB template: section 4.11.1
+ */
+typedef struct xhci_trb {
+	xhci_qword_t parameter;
+	xhci_dword_t status;
+	xhci_dword_t control;
+} xhci_trb_t;
+
+#define TRB_TYPE(trb)           XHCI_DWORD_EXTRACT((trb).control, 15, 10)
+#define TRB_LINK_TC(trb)        XHCI_DWORD_EXTRACT((trb).control, 1, 1)
+
+/**
+ * The Chain bit is valid only in specific TRB types.
+ */
+static inline bool xhci_trb_is_chained(xhci_trb_t *trb) {
+	const int type = TRB_TYPE(*trb);
+	const bool chain_bit = XHCI_DWORD_EXTRACT(trb->control, 4, 4);
+
+	return chain_bit &&
+	    (type == XHCI_TRB_TYPE_NORMAL
+	    || type == XHCI_TRB_TYPE_DATA_STAGE
+	    || type == XHCI_TRB_TYPE_STATUS_STAGE
+	    || type == XHCI_TRB_TYPE_ISOCH);
+}
+
+static inline void xhci_trb_set_cycle(xhci_trb_t *trb, bool cycle)
+{
+	xhci_dword_set_bits(&trb->control, cycle, 1, 1);
+}
+
+static inline void xhci_trb_link_fill(xhci_trb_t *trb, uintptr_t next_phys)
+{
+	// TRBs require 16-byte alignment
+	assert((next_phys & 0xf) == 0);
+
+	xhci_dword_set_bits(&trb->control, XHCI_TRB_TYPE_LINK, 15, 10);
+	xhci_qword_set(&trb->parameter, next_phys);
+}
+
+static inline void xhci_trb_copy(xhci_trb_t *dst, xhci_trb_t *src)
+{
+    /*
+     * As we do not know, whether our architecture is capable of copying 16
+     * bytes atomically, let's copy the fields one by one.
+     */
+    dst->parameter = src->parameter;
+    dst->status = src->status;
+    dst->control = src->control;
+}
+
+
+/**
+ * Event Ring Segment Table: section 6.5
+ */
+typedef struct xhci_erst_entry {
+	xhci_qword_t rs_base_ptr;       // sans bits 0-6
+	xhci_dword_t size;              // only low 16 bits, the rest is reserved
+} xhci_erst_entry_t;
+
+#endif
Index: uspace/drv/bus/usb/xhci/trb_ring.c
===================================================================
--- uspace/drv/bus/usb/xhci/trb_ring.c	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
+++ uspace/drv/bus/usb/xhci/trb_ring.c	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2017 Ondrej Hlavaty
+ * 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.
+ */
+
+#include <errno.h>
+#include <assert.h>
+#include <ddi.h>
+#include <as.h>
+#include <align.h>
+#include "trb_ring.h"
+
+#define SEGMENT_HEADER_SIZE (sizeof(link_t) + sizeof(uintptr_t))
+
+/**
+ * Number of TRBs in a segment (with our header).
+ */
+#define SEGMENT_TRB_COUNT ((PAGE_SIZE - SEGMENT_HEADER_SIZE) / sizeof(xhci_trb_t))
+
+struct trb_segment {
+	xhci_trb_t trb_storage [SEGMENT_TRB_COUNT] __attribute__((packed));
+
+	link_t segments_link;
+	uintptr_t phys;
+} __attribute__((aligned(PAGE_SIZE)));
+
+
+static inline xhci_trb_t *segment_begin(trb_segment_t *segment)
+{
+	return segment->trb_storage;
+}
+
+static inline xhci_trb_t *segment_end(trb_segment_t *segment)
+{
+	return segment_begin(segment) + SEGMENT_TRB_COUNT;
+}
+
+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;
+	}
+
+	return err;
+}
+
+int trb_ring_init(xhci_trb_ring_t *ring)
+{
+	struct trb_segment *segment;
+	int err;
+
+	if ((err = trb_segment_allocate(&segment)) != EOK)
+		return err;
+
+	list_initialize(&ring->segments);
+	list_append(&segment->segments_link, &ring->segments);
+
+	xhci_trb_t *last = segment_end(segment) - 1;
+	xhci_trb_link_fill(last, segment->phys);
+	xhci_trb_set_cycle(last, true);
+
+	ring->enqueue_segment = segment;
+	ring->enqueue_trb = segment_begin(segment);
+	ring->dequeue = segment->phys;
+	ring->pcs = 1;
+
+	return EOK;
+}
+
+int trb_ring_fini(xhci_trb_ring_t *ring)
+{
+	return EOK;
+}
+
+/**
+ * When the enqueue pointer targets a Link TRB, resolve it.
+ *
+ * Relies on segments being in the segment list in linked order.
+ *
+ * According to section 4.9.2.2, figure 16, the link TRBs cannot be chained, so
+ * it shall not be called in cycle, nor have an inner cycle.
+ */
+static void trb_ring_resolve_link(xhci_trb_ring_t *ring)
+{
+	link_t *next_segment = list_next(&ring->enqueue_segment->segments_link, &ring->segments);
+	if (!next_segment)
+		next_segment = list_first(&ring->segments);
+
+	ring->enqueue_segment = list_get_instance(next_segment, trb_segment_t, segments_link);
+	ring->enqueue_trb = segment_begin(ring->enqueue_segment);
+}
+
+static uintptr_t xhci_trb_ring_enqueue_phys(xhci_trb_ring_t *ring)
+{
+	uintptr_t trb_id = ring->enqueue_trb - segment_begin(ring->enqueue_segment);
+	return ring->enqueue_segment->phys + trb_id * sizeof(xhci_trb_t);
+}
+
+int trb_ring_enqueue(xhci_trb_ring_t *ring, xhci_trb_t *td)
+{
+	xhci_trb_t * const saved_enqueue_trb = ring->enqueue_trb;
+	trb_segment_t * const saved_enqueue_segment = ring->enqueue_segment;
+
+	/*
+	 * First, dry run and advance the enqueue pointer to see if the ring would
+	 * be full anytime during the transaction.
+	 */
+	xhci_trb_t *trb = td;
+	do {
+		ring->enqueue_trb++;
+
+		if (TRB_TYPE(*ring->enqueue_trb) == XHCI_TRB_TYPE_LINK)
+			trb_ring_resolve_link(ring);
+
+		if (xhci_trb_ring_enqueue_phys(ring) == ring->dequeue)
+			goto err_again;
+	} while (xhci_trb_is_chained(trb++));
+
+	ring->enqueue_segment = saved_enqueue_segment;
+	ring->enqueue_trb = saved_enqueue_trb;
+
+	/*
+	 * Now, copy the TRBs without further checking.
+	 */
+	trb = td;
+	do {
+		xhci_trb_set_cycle(trb, ring->pcs);
+		xhci_trb_copy(ring->enqueue_trb, trb);
+
+		ring->enqueue_trb++;
+
+		if (TRB_TYPE(*ring->enqueue_trb) == XHCI_TRB_TYPE_LINK) {
+			// XXX: Check, whether the order here is correct (ambiguous instructions in 4.11.5.1)
+			xhci_trb_set_cycle(ring->enqueue_trb, ring->pcs);
+
+			if (TRB_LINK_TC(*ring->enqueue_trb))
+				ring->pcs = !ring->pcs;
+
+			trb_ring_resolve_link(ring);
+		}
+	} while (xhci_trb_is_chained(trb++));
+
+	return EOK;
+
+err_again:
+	ring->enqueue_segment = saved_enqueue_segment;
+	ring->enqueue_trb = saved_enqueue_trb;
+	return EAGAIN;
+}
Index: uspace/drv/bus/usb/xhci/trb_ring.h
===================================================================
--- uspace/drv/bus/usb/xhci/trb_ring.h	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
+++ uspace/drv/bus/usb/xhci/trb_ring.h	(revision f4eb6c93ea5a3c62c72e15223a8225f4496177dc)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 Ondrej Hlavaty
+ * 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.
+ */
+
+/** @addtogroup drvusbxhci
+ * @{
+ */
+/** @file
+ * TRB Ring is a data structure for communication between HC and software.
+ *
+ * Despite this description, it is not used as an hardware structure - all but
+ * the Event ring is used as buffer of the TRBs itself, linked by Link TRB to
+ * form a (possibly multi-segment) circular buffer.
+ *
+ * This data structure abstracts this behavior.
+ */
+
+#ifndef XHCI_TRB_RING_H
+#define XHCI_TRB_RING_H
+
+#include <adt/list.h>
+#include <libarch/config.h>
+#include "hw_struct/trb.h"
+
+typedef struct trb_segment trb_segment_t;
+
+/**
+ * A TRB ring of which the software is a producer - command / transfer.
+ */
+typedef struct xhci_trb_ring {
+	list_t segments;                /* List of assigned segments */
+
+	/*
+	 * As the link TRBs connect physical addresses, we need to keep track of
+	 * active segment in virtual memory. The enqueue ptr should always belong
+	 * to the enqueue segment.
+	 */
+	trb_segment_t *enqueue_segment;
+	xhci_trb_t *enqueue_trb;
+
+	uintptr_t dequeue;              /* Last reported position of the dequeue pointer */
+	bool pcs;                       /* Producer Cycle State: section 4.9.2 */
+} xhci_trb_ring_t;
+
+/**
+ * Initializes the ring.
+ * Allocates one page as the first segment.
+ */
+int trb_ring_init(xhci_trb_ring_t *ring);
+int trb_ring_fini(xhci_trb_ring_t *ring);
+
+/**
+ * Enqueue a TD composed of TRBs.
+ *
+ * This will copy all TRBs chained together into the ring. The cycle flag in
+ * TRBs may be changed.
+ *
+ * The chained TRBs must be contiguous in memory, and must not contain Link TRBs.
+ *
+ * We cannot avoid the copying, because the TRB in ring should be updated atomically.
+ *
+ * @param td the first TRB of TD
+ * @return EOK on success,
+ *         EAGAIN when the ring is too full to fit all TRBs (temporary)
+ */
+int trb_ring_enqueue(xhci_trb_ring_t *ring, xhci_trb_t *td);
+
+/**
+ * When an event is received by the upper layer, it needs to update the dequeue
+ * pointer inside the ring. Otherwise, the ring will soon show up as full.
+ */
+void trb_ring_update_dequeue(xhci_trb_ring_t *ring, uintptr_t dequeue);
+
+
+#endif
