Annotation of qemu/roms/openbios/drivers/iommu.c, revision 1.1.1.2

1.1       root        1: /**
                      2:  ** Proll (PROM replacement)
                      3:  ** iommu.c: Functions for DVMA management.
                      4:  ** Copyright 1999 Pete Zaitcev
                      5:  ** This code is licensed under GNU General Public License.
                      6:  **/
                      7: #include "config.h"
                      8: #include "libopenbios/bindings.h"
                      9: #include "drivers/drivers.h"
                     10: #include "iommu.h"
1.1.1.2 ! root       11: #include "arch/sparc32/ofmem_sparc32.h"
1.1       root       12: 
                     13: #ifdef CONFIG_DEBUG_IOMMU
                     14: #define DPRINTF(fmt, args...)                   \
                     15:     do { printk(fmt , ##args); } while (0)
                     16: #else
                     17: #define DPRINTF(fmt, args...)
                     18: #endif
                     19: 
                     20: /*
                     21:  * IOMMU parameters
                     22:  */
                     23: struct iommu {
                     24:     struct iommu_regs *regs;
                     25:     unsigned int *page_table;
                     26:     unsigned long plow;     /* Base bus address */
                     27: };
                     28: 
                     29: static struct iommu ciommu;
                     30: 
                     31: static void
                     32: iommu_invalidate(struct iommu_regs *iregs)
                     33: {
                     34:     iregs->tlbflush = 0;
                     35: }
                     36: 
                     37: /*
                     38:  * XXX This is a problematic interface. We alloc _memory_ which is uncached.
                     39:  * So if we ever reuse allocations somebody is going to get uncached pages.
                     40:  * Returned address is always aligned by page.
                     41:  * BTW, we were not going to give away anonymous storage, were we not?
                     42:  */
                     43: void *
                     44: dvma_alloc(int size, unsigned int *pphys)
                     45: {
                     46:     void *va;
                     47:     unsigned int pa, ba;
                     48:     unsigned int npages;
                     49:     unsigned int mva, mpa;
                     50:     unsigned int i;
                     51:     unsigned int *iopte;
                     52:     struct iommu *t = &ciommu;
                     53:     int ret;
                     54: 
                     55:     npages = (size + (PAGE_SIZE-1)) / PAGE_SIZE;
                     56:     ret = ofmem_posix_memalign(&va, npages * PAGE_SIZE, PAGE_SIZE);
                     57:     if (ret != 0)
                     58:         return NULL;
                     59: 
                     60:     ba = (unsigned int)mem_alloc(&cdvmem, npages * PAGE_SIZE, PAGE_SIZE);
                     61:     if (ba == 0)
                     62:         return NULL;
                     63: 
                     64:     pa = (unsigned int)va2pa((unsigned long)va);
                     65: 
                     66:     /*
                     67:      * Change page attributes in MMU to uncached.
                     68:      */
                     69:     mva = (unsigned int) va;
                     70:     mpa = (unsigned int) pa;
1.1.1.2 ! root       71:     ofmem_arch_map_pages(mpa, mva, npages * PAGE_SIZE, ofmem_arch_io_translation_mode(mpa));
1.1       root       72: 
                     73:     /*
                     74:      * Map into IOMMU page table.
                     75:      */
                     76:     mpa = (unsigned int) pa;
                     77:     iopte = &t->page_table[(ba - t->plow) / PAGE_SIZE];
                     78:     for (i = 0; i < npages; i++) {
                     79:         *iopte++ = MKIOPTE(mpa);
                     80:         mpa += PAGE_SIZE;
                     81:     }
                     82: 
                     83:     *pphys = ba;
                     84: 
                     85:     return va;
                     86: }
                     87: 
                     88: /*
                     89:  * Initialize IOMMU
                     90:  * This looks like initialization of CPU MMU but
                     91:  * the routine is higher in food chain.
                     92:  */
                     93: static struct iommu_regs *
                     94: iommu_init(struct iommu *t, uint64_t base)
                     95: {
                     96:     unsigned int *ptab;
                     97:     int ptsize;
                     98: #ifdef CONFIG_DEBUG_IOMMU
                     99:     unsigned int impl, vers;
                    100: #endif
                    101:     unsigned int tmp;
                    102:     struct iommu_regs *regs;
                    103:     int ret;
                    104:     unsigned long vasize;
                    105: 
                    106:     regs = (struct iommu_regs *)ofmem_map_io(base, IOMMU_REGS);
                    107:     if (regs == NULL) {
                    108:         DPRINTF("Cannot map IOMMU\n");
                    109:         for (;;) { }
                    110:     }
                    111:     t->regs = regs;
                    112: #ifdef CONFIG_DEBUG_IOMMU
                    113:     impl = (regs->control & IOMMU_CTRL_IMPL) >> 28;
                    114:     vers = (regs->control & IOMMU_CTRL_VERS) >> 24;
                    115: #endif
                    116: 
                    117:     tmp = regs->control;
                    118:     tmp &= ~(IOMMU_CTRL_RNGE);
                    119: 
                    120:     tmp |= (IOMMU_RNGE_32MB | IOMMU_CTRL_ENAB);
                    121:     t->plow = 0xfe000000;              /* End - 32 MB */
                    122:     /* Size of VA region that we manage */
                    123:     vasize = 0x2000000; /* 32 MB */
                    124: 
                    125:     regs->control = tmp;
                    126:     iommu_invalidate(regs);
                    127: 
                    128:     /* Allocate IOMMU page table */
                    129:     /* Tremendous alignment causes great waste... */
                    130:     ptsize = (vasize / PAGE_SIZE) * sizeof(int);
                    131:     ret = ofmem_posix_memalign((void *)&ptab, ptsize, ptsize);
                    132:     if (ret != 0) {
                    133:         DPRINTF("Cannot allocate IOMMU table [0x%x]\n", ptsize);
                    134:         for (;;) { }
                    135:     }
                    136:     t->page_table = ptab;
                    137: 
                    138:     /* flush_cache_all(); */
                    139:     /** flush_tlb_all(); **/
                    140:     tmp = (unsigned int)va2pa((unsigned long)ptab);
                    141:     regs->base = tmp >> 4;
                    142:     iommu_invalidate(regs);
                    143: 
                    144:     DPRINTF("IOMMU: impl %d vers %d page table at 0x%p (pa 0x%x) of size %d bytes\n",
                    145:             impl, vers, t->page_table, tmp, ptsize);
                    146: 
                    147:     mem_init(&cdvmem, (char*)t->plow, (char *)0xfffff000);
                    148:     return regs;
                    149: }
                    150: 
                    151: void
                    152: ob_init_iommu(uint64_t base)
                    153: {
                    154:     struct iommu_regs *regs;
                    155: 
                    156:     regs = iommu_init(&ciommu, base);
                    157: 
                    158:     push_str("/iommu");
                    159:     fword("find-device");
                    160:     PUSH((unsigned long)regs);
                    161:     fword("encode-int");
                    162:     push_str("address");
                    163:     fword("property");
                    164: 
                    165:     PUSH(base >> 32);
                    166:     fword("encode-int");
                    167:     PUSH(base & 0xffffffff);
                    168:     fword("encode-int");
                    169:     fword("encode+");
                    170:     PUSH(IOMMU_REGS);
                    171:     fword("encode-int");
                    172:     fword("encode+");
                    173:     push_str("reg");
                    174:     fword("property");
                    175: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.