Index: uspace/lib/usb/src/dma_buffer.c
===================================================================
--- uspace/lib/usb/src/dma_buffer.c	(revision 98893ede399d6eed12edddf404da1f101f415345)
+++ uspace/lib/usb/src/dma_buffer.c	(revision 98b1d301e61446aa87b9e47da002832a97df3f07)
@@ -40,6 +40,5 @@
 
 const dma_policy_t dma_policy_default = {
-	.use64 = false,
-	.alignment = PAGE_SIZE,
+	.flags = DMA_POLICY_F_4GiB | DMA_POLICY_F_CONTIGUOUS,
 };
 
@@ -47,4 +46,6 @@
  * The routine of allocating a DMA buffer. Inlined to force optimization for the
  * default policy.
+ *
+ * FIXME: We ignore the non-presence of contiguous flag, for now.
  */
 static inline int dma_buffer_alloc_internal(dma_buffer_t *db,
@@ -53,10 +54,8 @@
 	assert(db);
 
-	if (policy->alignment > PAGE_SIZE)
-		return EINVAL;
+	const size_t real_size = ALIGN_UP(size, PAGE_SIZE);
+	const bool need_4gib = !!(policy->flags & DMA_POLICY_F_4GiB);
 
-	const size_t aligned_size = ALIGN_UP(size, policy->alignment);
-	const size_t real_size = ALIGN_UP(aligned_size, PAGE_SIZE);
-	const uintptr_t flags = policy->use64 ? 0 : DMAMEM_4GiB;
+	const uintptr_t flags = need_4gib ? DMAMEM_4GiB : 0;
 
 	uintptr_t phys;
@@ -127,4 +126,60 @@
 
 /**
+ * Check whether a memory area is compatible with a policy.
+ *
+ * Useful to skip copying, if the buffer is already ready to be given to
+ * hardware.
+ */
+bool dma_buffer_check_policy(const void *buffer, size_t size, dma_policy_t *policy)
+{
+	/* Buffer must be always page aligned */
+	if (((uintptr_t) buffer) % PAGE_SIZE)
+		goto violated;
+
+	const bool check_4gib = !!(policy->flags & DMA_POLICY_F_4GiB);
+	const bool check_contiguous = !!(policy->flags & DMA_POLICY_F_CONTIGUOUS);
+
+	/*
+	 * For these conditions, we need to walk through pages and check
+	 * physical address of each one
+	 */
+	if (check_contiguous || check_4gib) {
+		const void * virt = buffer;
+		uintptr_t phys;
+
+		/* Get the mapping of the first page */
+		if (as_get_physical_mapping(virt, &phys))
+			goto error;
+
+		/* First page can already break 4GiB condition */
+		if (check_4gib && (phys & DMAMEM_4GiB) != 0)
+			goto violated;
+
+		while (size <= PAGE_SIZE) {
+			/* Move to the next page */
+			virt += PAGE_SIZE;
+			size -= PAGE_SIZE;
+
+			uintptr_t last_phys = phys;
+			if (as_get_physical_mapping(virt, &phys))
+				goto error;
+
+			if (check_contiguous && (phys - last_phys) != PAGE_SIZE)
+				goto violated;
+
+			if (check_4gib && (phys & DMAMEM_4GiB) != 0)
+				goto violated;
+		}
+	}
+
+	/* All checks passed */
+	return true;
+
+violated:
+error:
+	return false;
+}
+
+/**
  * @}
  */
