patch-2.3.45 linux/arch/arm/mm/consistent.c
Next file: linux/arch/arm/mm/proc-arm6,7.S
Previous file: linux/arch/arm/mm/Makefile
Back to the patch index
Back to the overall index
- Lines: 103
- Date:
Sun Feb 13 10:47:01 2000
- Orig file:
v2.3.44/linux/arch/arm/mm/consistent.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.44/linux/arch/arm/mm/consistent.c linux/arch/arm/mm/consistent.c
@@ -0,0 +1,102 @@
+/*
+ * Dynamic DMA mapping support.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+/* Pure 2^n version of get_order */
+extern __inline__ int __get_order(unsigned long size)
+{
+ int order;
+
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
+
+/*
+ * This allocates one page of cache-coherent memory space and returns
+ * both the virtual and a "dma" address to that space. It is not clear
+ * whether this could be called from an interrupt context or not. For
+ * now, we expressly forbid it, especially as some of the stuff we do
+ * here is not interrupt context safe.
+ */
+void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
+{
+ int order;
+ unsigned long page;
+ struct vm_struct *area;
+ void *ret;
+
+ if (in_interrupt())
+ BUG();
+
+ order = __get_order(size);
+
+ page = __get_free_pages(gfp, order);
+ if (!page)
+ goto no_page;
+
+ memset((void *)page, 0, PAGE_SIZE << order);
+ clean_cache_area(page, PAGE_SIZE << order);
+
+ *dma_handle = virt_to_bus((void *)page);
+
+ area = get_vm_area(size, VM_IOREMAP); /* maybe new type? */
+ if (!area)
+ goto no_area;
+
+ ret = __ioremap(virt_to_phys((void *)page), PAGE_SIZE << order, 0);
+ if (ret)
+ return ret;
+
+no_area:
+ free_pages(page, order);
+no_page:
+ BUG();
+ return NULL;
+}
+
+/*
+ * free a page as defined by the above mapping. We expressly forbid
+ * calling this from interrupt context.
+ */
+void consistent_free(void *vaddr)
+{
+ if (in_interrupt())
+ BUG();
+
+ __iounmap(vaddr);
+}
+
+/*
+ * make an area consistent.
+ */
+void consistent_sync(void *vaddr, size_t size, int rw)
+{
+ switch (rw) {
+ case 0:
+ BUG();
+ case 1: /* invalidate only */
+ dma_cache_inv(vaddr, size);
+ break;
+ case 2: /* writeback only */
+ dma_cache_wback(vaddr, size);
+ break;
+ case 3: /* writeback and invalidate */
+ dma_cache_wback_inv(vaddr, size);
+ break;
+ }
+}
FUNET's LINUX-ADM group, [email protected]
TCL-scripts by Sam Shen (who was at: [email protected])