summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/drivers/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/drivers/iommu.c')
-rw-r--r--qemu/roms/openbios/drivers/iommu.c207
1 files changed, 0 insertions, 207 deletions
diff --git a/qemu/roms/openbios/drivers/iommu.c b/qemu/roms/openbios/drivers/iommu.c
deleted file mode 100644
index cd9a64bb6..000000000
--- a/qemu/roms/openbios/drivers/iommu.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/**
- ** Proll (PROM replacement)
- ** iommu.c: Functions for DVMA management.
- ** Copyright 1999 Pete Zaitcev
- ** This code is licensed under GNU General Public License.
- **/
-#include "config.h"
-#include "libopenbios/bindings.h"
-#include "libopenbios/ofmem.h"
-#include "drivers/drivers.h"
-#include "iommu.h"
-#include "arch/sparc32/ofmem_sparc32.h"
-
-#ifdef CONFIG_DEBUG_IOMMU
-#define DPRINTF(fmt, args...) \
- do { printk(fmt , ##args); } while (0)
-#else
-#define DPRINTF(fmt, args...)
-#endif
-
-/*
- * IOMMU parameters
- */
-struct iommu {
- struct iommu_regs *regs;
- unsigned int *page_table;
- unsigned long plow; /* Base bus address */
-};
-
-static struct iommu ciommu;
-
-static void
-iommu_invalidate(struct iommu_regs *iregs)
-{
- iregs->tlbflush = 0;
-}
-
-/*
- * XXX This is a problematic interface. We alloc _memory_ which is uncached.
- * So if we ever reuse allocations somebody is going to get uncached pages.
- * Returned address is always aligned by page.
- * BTW, we were not going to give away anonymous storage, were we not?
- */
-void *
-dvma_alloc(int size, unsigned int *pphys)
-{
- void *va;
- unsigned int pa, ba;
- unsigned int npages;
- unsigned int mva, mpa;
- unsigned int i;
- unsigned int *iopte;
- struct iommu *t = &ciommu;
- int ret;
-
- npages = (size + (PAGE_SIZE-1)) / PAGE_SIZE;
- ret = ofmem_posix_memalign(&va, npages * PAGE_SIZE, PAGE_SIZE);
- if (ret != 0)
- return NULL;
-
- ba = (unsigned int)mem_alloc(&cdvmem, npages * PAGE_SIZE, PAGE_SIZE);
- if (ba == 0)
- return NULL;
-
- pa = (unsigned int)va2pa((unsigned long)va);
-
- /*
- * Change page attributes in MMU to uncached.
- */
- mva = (unsigned int) va;
- mpa = (unsigned int) pa;
- ofmem_arch_map_pages(mpa, mva, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(mpa));
-
- /*
- * Map into IOMMU page table.
- */
- mpa = (unsigned int) pa;
- iopte = &t->page_table[(ba - t->plow) / PAGE_SIZE];
- for (i = 0; i < npages; i++) {
- *iopte++ = MKIOPTE(mpa);
- mpa += PAGE_SIZE;
- }
-
- *pphys = ba;
-
- return va;
-}
-
-/*
- * Initialize IOMMU
- * This looks like initialization of CPU MMU but
- * the routine is higher in food chain.
- */
-static struct iommu_regs *
-iommu_init(struct iommu *t, uint64_t base)
-{
- unsigned int *ptab;
- int ptsize;
-#ifdef CONFIG_DEBUG_IOMMU
- unsigned int impl, vers;
-#endif
- unsigned int tmp;
- struct iommu_regs *regs;
- int ret;
- unsigned long vasize;
-
- regs = (struct iommu_regs *)ofmem_map_io(base, IOMMU_REGS);
- if (regs == NULL) {
- DPRINTF("Cannot map IOMMU\n");
- for (;;) { }
- }
- t->regs = regs;
-#ifdef CONFIG_DEBUG_IOMMU
- impl = (regs->control & IOMMU_CTRL_IMPL) >> 28;
- vers = (regs->control & IOMMU_CTRL_VERS) >> 24;
-#endif
-
- tmp = regs->control;
- tmp &= ~(IOMMU_CTRL_RNGE);
-
- tmp |= (IOMMU_RNGE_32MB | IOMMU_CTRL_ENAB);
- t->plow = 0xfe000000; /* End - 32 MB */
- /* Size of VA region that we manage */
- vasize = 0x2000000; /* 32 MB */
-
- regs->control = tmp;
- iommu_invalidate(regs);
-
- /* Allocate IOMMU page table */
- /* Tremendous alignment causes great waste... */
- ptsize = (vasize / PAGE_SIZE) * sizeof(int);
- ret = ofmem_posix_memalign((void *)&ptab, ptsize, ptsize);
- if (ret != 0) {
- DPRINTF("Cannot allocate IOMMU table [0x%x]\n", ptsize);
- for (;;) { }
- }
- t->page_table = ptab;
-
- /* flush_cache_all(); */
- /** flush_tlb_all(); **/
- tmp = (unsigned int)va2pa((unsigned long)ptab);
- regs->base = tmp >> 4;
- iommu_invalidate(regs);
-
- DPRINTF("IOMMU: impl %d vers %d page table at 0x%p (pa 0x%x) of size %d bytes\n",
- impl, vers, t->page_table, tmp, ptsize);
-
- mem_init(&cdvmem, (char*)t->plow, (char *)0xfffff000);
- return regs;
-}
-
-/* ( addr.lo addr.hi size -- virt ) */
-
-static void
-ob_iommu_map_in(void)
-{
- phys_addr_t phys;
- ucell size, virt;
-
- size = POP();
- phys = POP();
- phys = (phys << 32) + POP();
-
- virt = ofmem_map_io(phys, size);
-
- PUSH(virt);
-}
-
-/* ( virt size ) */
-
-static void
-ob_iommu_map_out(void)
-{
- ucell size = POP();
- ucell virt = POP();
-
- ofmem_release_io(virt, size);
-}
-
-void
-ob_init_iommu(uint64_t base)
-{
- struct iommu_regs *regs;
-
- regs = iommu_init(&ciommu, base);
-
- push_str("/iommu");
- fword("find-device");
- PUSH((unsigned long)regs);
- fword("encode-int");
- push_str("address");
- fword("property");
-
- PUSH(base >> 32);
- fword("encode-int");
- PUSH(base & 0xffffffff);
- fword("encode-int");
- fword("encode+");
- PUSH(IOMMU_REGS);
- fword("encode-int");
- fword("encode+");
- push_str("reg");
- fword("property");
-
- bind_func("map-in", ob_iommu_map_in);
- bind_func("map-out", ob_iommu_map_out);
-}