[OpenBIOS] [PATCH 10/13] Implement ofmem_map_io() within OFMEM as a function to map I/O memory (similar to SPARC32's private map_io() function).

Mark Cave-Ayland mark.cave-ayland at siriusit.co.uk
Fri Dec 31 00:22:38 CET 2010


As a consequence we need to maintain a separate I/O range within OFMEM, and add management functions similar to those that
exist for the virtual and physical ranges. At the same time, we introduce a couple of new OFMEM arch functions called
ofmem_arch_get_iomem_base() and ofmem_arch_get_iomem_top() to control the range of allocatable I/O memory which is again
similar to the existing method used for the virtual and physical ranges.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at siriusit.co.uk>
---
 openbios-devel/arch/ppc/qemu/ofmem.c        |   12 ++++++
 openbios-devel/arch/sparc32/ofmem_sparc32.c |   10 +++++
 openbios-devel/arch/sparc64/ofmem_sparc64.c |   12 ++++++
 openbios-devel/include/libopenbios/ofmem.h  |    9 ++++-
 openbios-devel/libopenbios/ofmem_common.c   |   52 +++++++++++++++++++++++++++
 5 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/openbios-devel/arch/ppc/qemu/ofmem.c b/openbios-devel/arch/ppc/qemu/ofmem.c
index 80fad75..4c6825e 100644
--- a/openbios-devel/arch/ppc/qemu/ofmem.c
+++ b/openbios-devel/arch/ppc/qemu/ofmem.c
@@ -132,6 +132,18 @@ void ofmem_arch_early_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell
     /* none yet */
 }
 
+ucell ofmem_arch_get_iomem_base(void)
+{
+    /* Currently unused */
+    return 0;
+}
+
+ucell ofmem_arch_get_iomem_top(void)
+{
+    /* Currently unused */
+    return 0;
+}
+
 retain_t *ofmem_arch_get_retained(void)
 {
     /* not implemented */
diff --git a/openbios-devel/arch/sparc32/ofmem_sparc32.c b/openbios-devel/arch/sparc32/ofmem_sparc32.c
index 77112ec..6815349 100644
--- a/openbios-devel/arch/sparc32/ofmem_sparc32.c
+++ b/openbios-devel/arch/sparc32/ofmem_sparc32.c
@@ -71,6 +71,16 @@ phys_addr_t ofmem_arch_get_phys_top(void)
 	return (uintptr_t)ofmem->ramsize - 0x1000000;
 }
 
+ucell ofmem_arch_get_iomem_base(void)
+{
+	return pointer2cell(&_end);
+}
+
+ucell ofmem_arch_get_iomem_top(void)
+{
+	return pointer2cell(&_iomem);
+}
+
 retain_t *ofmem_arch_get_retained(void)
 {
 	/* Not used */
diff --git a/openbios-devel/arch/sparc64/ofmem_sparc64.c b/openbios-devel/arch/sparc64/ofmem_sparc64.c
index 6a4fb5e..1655978 100644
--- a/openbios-devel/arch/sparc64/ofmem_sparc64.c
+++ b/openbios-devel/arch/sparc64/ofmem_sparc64.c
@@ -70,6 +70,18 @@ phys_addr_t ofmem_arch_get_phys_top(void)
 	return ofmem->ramsize;
 }
 
+ucell ofmem_arch_get_iomem_base(void)
+{
+	/* Currently unused */
+	return 0;
+}
+
+ucell ofmem_arch_get_iomem_top(void)
+{
+	/* Currently unused */
+	return 0;
+}
+
 retain_t *ofmem_arch_get_retained(void)
 {
 	/* Retained area is at the top of physical RAM */
diff --git a/openbios-devel/include/libopenbios/ofmem.h b/openbios-devel/include/libopenbios/ofmem.h
index e350dec..940f5cc 100644
--- a/openbios-devel/include/libopenbios/ofmem.h
+++ b/openbios-devel/include/libopenbios/ofmem.h
@@ -46,6 +46,7 @@ typedef struct {
 
 	range_t			*phys_range;
 	range_t			*virt_range;
+	range_t			*io_range;
 
 	translation_t	*trans;		/* this is really a translation_t */
 } ofmem_t;
@@ -63,6 +64,8 @@ extern void*    	ofmem_arch_get_malloc_base(void);
 extern ucell    	ofmem_arch_get_heap_top(void);
 extern ucell    	ofmem_arch_get_virt_top(void);
 extern phys_addr_t 	ofmem_arch_get_phys_top(void);
+extern ucell		ofmem_arch_get_iomem_base(void);
+extern ucell		ofmem_arch_get_iomem_top(void);
 extern retain_t*	ofmem_arch_get_retained(void);
 extern int			ofmem_arch_get_physaddr_cellsize(void);
 extern int			ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value);
@@ -104,25 +107,27 @@ extern void ofmem_register( phandle_t ph_memory, phandle_t ph_mmu );
 extern ucell ofmem_claim( ucell addr, ucell size, ucell align );
 extern phys_addr_t ofmem_claim_phys( phys_addr_t mphys, ucell size, ucell align );
 extern ucell ofmem_claim_virt( ucell mvirt, ucell size, ucell align );
+extern ucell ofmem_claim_io( ucell virt, ucell size, ucell align );
 
 extern phys_addr_t ofmem_retain( phys_addr_t phys, ucell size, ucell align );
 
 extern int   ofmem_map( phys_addr_t phys, ucell virt, ucell size, ucell mode );
 extern int   ofmem_unmap( ucell virt, ucell size );
+extern ucell ofmem_map_io( phys_addr_t phys, ucell size );
 
 extern void  ofmem_release( ucell virt, ucell size );
 extern void  ofmem_release_phys( phys_addr_t phys, ucell size );
 extern void  ofmem_release_virt( ucell virt, ucell size );
 extern phys_addr_t ofmem_translate( ucell virt, ucell *ret_mode );
 
-#ifdef CONFIG_PPC
+/* Currently the same for all architectures */
 #define PAGE_SHIFT   12
 
+#ifdef CONFIG_PPC
 unsigned long get_ram_top( void );
 unsigned long get_ram_bottom( void );
 
 #elif defined(CONFIG_SPARC32)
-#define PAGE_SHIFT   12
 
 /* arch/sparc32/lib.c */
 struct mem;
diff --git a/openbios-devel/libopenbios/ofmem_common.c b/openbios-devel/libopenbios/ofmem_common.c
index e1accb2..7f6223b 100644
--- a/openbios-devel/libopenbios/ofmem_common.c
+++ b/openbios-devel/libopenbios/ofmem_common.c
@@ -551,6 +551,35 @@ ucell ofmem_claim_virt( ucell virt, ucell size, ucell align )
 			get_ram_size(), ofmem_arch_get_virt_top(), 1 );
 }
 
+static ucell ofmem_claim_io_( ucell virt, ucell size, ucell align,
+		ucell min, ucell max, int reverse )
+{
+	ofmem_t *ofmem = ofmem_arch_get_private();
+	if( !align ) {
+		if( !is_free( virt, size, ofmem->io_range ) ) {
+			OFMEM_TRACE("Non-free I/O memory claimed!\n");
+			return -1;
+		}
+		add_entry( virt, size, &ofmem->io_range );
+		return virt;
+	}
+
+	virt = find_area( align, size, ofmem->io_range, min, max, reverse );
+	if( virt == -1 ) {
+		printk("ofmem_claim_io - out of space (failed request for " FMT_ucellx " bytes)\n", size);
+		return -1;
+	}
+	add_entry( virt, size, &ofmem->io_range );
+	return virt;
+}
+
+ucell ofmem_claim_io( ucell virt, ucell size, ucell align )
+{
+	/* Claim a section of memory from the I/O range */
+	return ofmem_claim_io_( virt, size, align,
+			ofmem_arch_get_iomem_base(), ofmem_arch_get_iomem_top(), 0 );
+}
+
 /* if align != 0, phys is ignored. Returns -1 on error */
 phys_addr_t ofmem_retain( phys_addr_t phys, ucell size, ucell align )
 {
@@ -797,6 +826,29 @@ int ofmem_unmap( ucell virt, ucell size )
 	return 0;
 }
 
+ucell ofmem_map_io( phys_addr_t phys, ucell size )
+{
+	/* Claim virtual memory from the I/O range and map the page-aligned
+	   physical address phys to it, returning the newly allocated
+	   virtual address */
+	ucell virt, mode;
+	phys_addr_t off;
+	int npages;
+
+	off = phys & (PAGE_SIZE - 1);
+	npages = (off + size - 1) / PAGE_SIZE + 1;
+	phys &= ~(PAGE_SIZE - 1);
+
+	virt = ofmem_claim_io(-1, npages * PAGE_SIZE, PAGE_SIZE);
+
+	mode = ofmem_arch_io_translation_mode(off);
+
+	ofmem_map_page_range(phys, virt, npages * PAGE_SIZE, mode);
+	ofmem_arch_early_map_pages(phys, virt, npages * PAGE_SIZE, mode);
+
+	return (virt + off);
+}
+
 /* virtual -> physical. */
 phys_addr_t ofmem_translate( ucell virt, ucell *mode )
 {
-- 
1.7.2.3




More information about the OpenBIOS mailing list