Index: uspace/lib/usb/include/usb/dma_buffer.h
===================================================================
--- uspace/lib/usb/include/usb/dma_buffer.h	(revision cc63815c45bec69f85b3455ff1f4c5dcc15c228c)
+++ uspace/lib/usb/include/usb/dma_buffer.h	(revision 1d758fc6d12dfedeea03efca816537794a056af2)
@@ -37,45 +37,73 @@
  * shared through IPC).
  *
- * Note that although allocated memory is always page-aligned, the buffer itself
- * may be only a part of it, justifying the existence of page-alignment and
- * page-crossing flags.
+ * Currently, it is possible to allocate either completely contiguous buffers
+ * (with dma_map_anonymous) or arbitrary memory (with as_area_create). Shall the
+ * kernel be updated, this is a subject of major optimization of memory usage.
+ * The other way to do it without the kernel is building an userspace IO vector
+ * in a similar way how QEMU does it.
  *
- * Also, currently the buffers that are allocated are always contiguous and
- * page-aligned, regardless of whether the policy requires it. We blindly
- * believe this fact in dma_buffer_phys, which will yield wrong results if the
- * buffer is not contiguous.
+ * The structures themselves are defined in usbhc_iface, because they need to be
+ * passed through IPC.
  */
 #ifndef LIB_USB_DMA_BUFFER
 #define LIB_USB_DMA_BUFFER
 
+#include <as.h>
+#include <bitops.h>
+#include <errno.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <usbhc_iface.h>
-#include <errno.h>
 
-#define DMA_POLICY_4GiB		(1<<0)	/**< Must use only 32-bit addresses */
-#define DMA_POLICY_PAGE_ALIGNED	(1<<1)	/**< The first pointer must be page-aligned */
-#define DMA_POLICY_CONTIGUOUS	(1<<2)	/**< Pages must follow each other physically */
-#define DMA_POLICY_NOT_CROSSING	(1<<3)	/**< Buffer must not cross page boundary. (Implies buffer is no larger than page).  */
+/**
+ * The DMA policy describes properties of the buffer. It is used in two
+ * different contexts. Either it represents requirements, which shall be
+ * satisfied to avoid copying the buffer to a more strict one. Or, it is the
+ * actual property of the buffer, which can be more strict than requested. It
+ * always holds that more bits set means more restrictive policy, and that by
+ * computing a bitwise OR one gets the restriction that holds for both.
+ *
+ * The high bits of a DMA policy represent a physical contiguity. If bit i is
+ * set, it means that chunks of a size 2^(i+1) are contiguous in memory. It
+ * shall never happen that bit i > j is set when j is not.
+ *
+ * The previous applies for i >= PAGE_WIDTH. Lower bits are used as bit flags.
+ */
+#define DMA_POLICY_FLAGS_MASK		(PAGE_SIZE - 1)
+#define DMA_POLICY_CHUNK_SIZE_MASK	(~DMA_POLICY_FLAGS_MASK)
 
-#define DMA_POLICY_STRICT	(-1U)
-#define DMA_POLICY_DEFAULT	DMA_POLICY_STRICT
+#define DMA_POLICY_4GiB	(1<<0)		/**< Must use only 32-bit addresses */
 
-typedef struct dma_buffer {
-	void *virt;
-	uintptr_t phys;
-} dma_buffer_t;
+#define DMA_POLICY_STRICT		(-1UL)
+#define DMA_POLICY_DEFAULT		DMA_POLICY_STRICT
+
+extern dma_policy_t dma_policy_create(unsigned, size_t);
+
+/**
+ * Get mask which defines bits of offset in chunk.
+ */
+static inline size_t dma_policy_chunk_mask(const dma_policy_t policy)
+{
+	return policy | DMA_POLICY_FLAGS_MASK;
+}
 
 extern errno_t dma_buffer_alloc(dma_buffer_t *db, size_t size);
 extern errno_t dma_buffer_alloc_policy(dma_buffer_t *, size_t, dma_policy_t);
 extern void dma_buffer_free(dma_buffer_t *);
-extern uintptr_t dma_buffer_phys(const dma_buffer_t *, void *);
 
-extern bool dma_buffer_check_policy(const void *, size_t, const dma_policy_t);
+extern uintptr_t dma_buffer_phys(const dma_buffer_t *, const void *);
+
+static inline uintptr_t dma_buffer_phys_base(const dma_buffer_t *db)
+{
+	return dma_buffer_phys(db, db->virt);
+}
 
 extern errno_t dma_buffer_lock(dma_buffer_t *, void *, size_t);
 extern void dma_buffer_unlock(dma_buffer_t *, size_t);
 
-static inline int dma_buffer_is_set(dma_buffer_t *db)
+extern void dma_buffer_acquire(dma_buffer_t *);
+extern void dma_buffer_release(dma_buffer_t *);
+
+static inline bool dma_buffer_is_set(const dma_buffer_t *db)
 {
 	return !!db->virt;
