[OpenBIOS] [PATCH 13/16] 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
Thu Dec 30 19:07:16 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 | 11 ++++--
openbios-devel/libopenbios/ofmem_common.c | 52 +++++++++++++++++++++++++++
5 files changed, 94 insertions(+), 3 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 bd6f69b..83f22b5 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..fa37146 100644
--- a/openbios-devel/include/libopenbios/ofmem.h
+++ b/openbios-devel/include/libopenbios/ofmem.h
@@ -46,7 +46,8 @@ 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 34caa2f..f1394af 100644
--- a/openbios-devel/libopenbios/ofmem_common.c
+++ b/openbios-devel/libopenbios/ofmem_common.c
@@ -547,6 +547,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 )
{
@@ -793,6 +822,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