[OpenBIOS] [PATCH 10/15] SPARC64: implement dma-* words

Mark Cave-Ayland mark.cave-ayland at ilande.co.uk
Mon May 21 23:33:17 CEST 2018


Implement the dma-* words in the root node using Forth, except for dma-alloc
and dma-sync which require C to use the in-built aligned memory allocator and
MMU flushing.

Note that as OpenBIOS doesn't enable the IOMMU for SPARC64 it is possible to
use the aligned memory allocator directly without any extra support code.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
---
 arch/sparc64/openbios.c | 40 ++++++++++++++++++++++++++++++++++++++++
 arch/sparc64/tree.fs    | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c
index 46d44ea..e9e08fd 100644
--- a/arch/sparc64/openbios.c
+++ b/arch/sparc64/openbios.c
@@ -722,6 +722,40 @@ static void init_memory(void)
     PUSH(virt + MEMORY_SIZE);
 }
 
+/* ( size -- virt ) */
+static void
+dma_alloc(void)
+{
+    ucell size = POP();
+    ucell addr;
+    int ret;
+
+    /* OpenBIOS doesn't enable the sun4u IOMMU so we can fall back to
+     * using ofmem_posix_memalign */
+    ret = ofmem_posix_memalign((void *)&addr, size, PAGE_SIZE);
+
+    if (ret) {
+        PUSH(0);
+    } else {
+        PUSH(addr);
+    }
+}
+
+/* ( virt devaddr size -- ) */
+static void
+dma_sync(void)
+{
+    ucell size = POP();
+    POP();
+    ucell virt = POP();
+    ucell va;
+
+    for (va = virt; va < virt + size; va += PAGE_SIZE_8K) {
+        itlb_demap(va);
+        dtlb_demap(va);
+    }
+}
+
 extern volatile uint64_t *obp_ticks_pointer;
 
 static void
@@ -729,6 +763,12 @@ arch_init( void )
 {
 	openbios_init();
 	modules_init();
+
+    bind_func("sparc64-dma-alloc", dma_alloc);
+    feval("['] sparc64-dma-alloc to (dma-alloc)");
+    bind_func("sparc64-dma-sync", dma_sync);
+    feval("['] sparc64-dma-sync to (dma-sync)");
+
 #ifdef CONFIG_DRIVER_PCI
         ob_pci_init();
 
diff --git a/arch/sparc64/tree.fs b/arch/sparc64/tree.fs
index e034b59..a1d5620 100644
--- a/arch/sparc64/tree.fs
+++ b/arch/sparc64/tree.fs
@@ -19,6 +19,30 @@ include config.fs
   rot pocket tohexstr r> tmpstrcat drop
 ;
 
+\ ---------
+\ DMA words
+\ ---------
+
+: sparc64-dma-free  ( virt size -- )
+  2drop
+;
+
+: sparc64-dma-map-in  ( virt size cacheable? -- devaddr )
+  2drop
+;
+
+: sparc64-dma-map-out  ( virt devaddr size -- )
+  (dma-sync)
+;
+
+['] sparc64-dma-free to (dma-free)
+['] sparc64-dma-map-in to (dma-map-in)
+['] sparc64-dma-map-out to (dma-map-out)
+
+\ -------------------------------------------------------------
+\ device-tree
+\ -------------------------------------------------------------
+
 " /" find-device
   2 encode-int " #address-cells" property
   2 encode-int " #size-cells" property
@@ -27,6 +51,29 @@ include config.fs
   : encode-unit encode-unit-upa ;
   : decode-unit decode-unit-upa ;
 
+  : dma-sync  ( virt devaddr size -- )
+    s" (dma-sync)" $find if execute then
+  ;
+
+  : dma-alloc  ( size -- virt )
+    \ OpenBIOS doesn't enable the sun4u IOMMU so we can fall back to using
+    \ alloc-mem
+    h# 2000 + alloc-mem dup
+    h# 2000 1 - and -  \ align to 8K page size
+  ;
+
+  : dma-free  ( virt size -- )
+    2drop
+  ;
+
+  : dma-map-in  ( virt size cacheable? -- devaddr )
+    2drop
+  ;
+
+  : dma-map-out  ( virt devaddr size -- )
+    dma-sync
+  ;
+
 new-device
   " memory" device-name
   " memory" device-type
-- 
2.11.0




More information about the OpenBIOS mailing list