Index: qemu/hw/iommu.c =================================================================== --- qemu.orig/hw/iommu.c 2006-08-24 18:53:19.000000000 +0000 +++ qemu/hw/iommu.c 2006-08-24 19:23:59.000000000 +0000 @@ -186,21 +186,56 @@ iommu_mem_writew, }; -uint32_t iommu_translate_local(void *opaque, uint32_t addr) +static uint32_t iommu_page_get_flags(void *opaque, uint32_t addr) { IOMMUState *s = opaque; - uint32_t iopte, pa, tmppte; + uint32_t iopte; iopte = s->regs[1] << 4; addr &= ~s->iostart; iopte += (addr >> (PAGE_SHIFT - 2)) & ~3; - pa = ldl_phys(iopte); + return ldl_phys(iopte); +} + +uint32_t iommu_translate_local(void *opaque, uint32_t addr) +{ + uint32_t pa, tmppte; + + pa = iommu_page_get_flags(opaque, addr); tmppte = pa; pa = ((pa & IOPTE_PAGE) << 4) + (addr & PAGE_MASK); DPRINTF("xlate dva %x => pa %x (iopte[%x] = %x)\n", addr, pa, iopte, tmppte); return pa; } +void sparc_iommu_memory_rw_local(void *opaque, target_phys_addr_t addr, + uint8_t *buf, int len, int is_write) +{ + int l, flags; + target_ulong page; + void * p; + + while (len > 0) { + page = addr & TARGET_PAGE_MASK; + l = (page + TARGET_PAGE_SIZE) - addr; + if (l > len) + l = len; + flags = iommu_page_get_flags(opaque, page); + if (!(flags & IOPTE_VALID)) + return; + if (is_write) { + if (!(flags & IOPTE_WRITE)) + return; + cpu_physical_memory_write(addr, buf, len); + } else { + cpu_physical_memory_read(buf, addr, len); + } + len -= l; + buf += l; + addr += l; + } +} + static void iommu_save(QEMUFile *f, void *opaque) { IOMMUState *s = opaque; Index: qemu/hw/sun4m.c =================================================================== --- qemu.orig/hw/sun4m.c 2006-08-24 19:17:45.000000000 +0000 +++ qemu/hw/sun4m.c 2006-08-24 19:18:51.000000000 +0000 @@ -199,12 +199,17 @@ return iommu_translate_local(iommu, addr); } -void sparc_iommu_memory_rw(target_phys_addr_t addr, - uint8_t *buf, int len, int is_write) +void sparc_iommu_memory_read(target_phys_addr_t addr, + uint8_t *buf, int len) { - return sparc_iommu_memory_rwl(iommu, addr, buf, len, is_write); + return sparc_iommu_memory_rw_local(iommu, addr, buf, len, 0); } +void sparc_iommu_memory_write(target_phys_addr_t addr, + uint8_t *buf, int len) +{ + return sparc_iommu_memory_rw_local(iommu, addr, buf, len, 1); +} static void *slavio_misc; Index: qemu/vl.h =================================================================== --- qemu.orig/vl.h 2006-08-24 19:17:55.000000000 +0000 +++ qemu/vl.h 2006-08-24 19:19:59.000000000 +0000 @@ -1027,10 +1027,16 @@ extern QEMUMachine sun4m_machine; uint32_t iommu_translate(uint32_t addr); void pic_set_irq_cpu(int irq, int level, unsigned int cpu); +void sparc_iommu_memory_read(target_phys_addr_t addr, + uint8_t *buf, int len); +void sparc_iommu_memory_write(target_phys_addr_t addr, + uint8_t *buf, int len); /* iommu.c */ void *iommu_init(uint32_t addr); uint32_t iommu_translate_local(void *opaque, uint32_t addr); +void sparc_iommu_memory_rw_local(void *opaque, target_phys_addr_t addr, + uint8_t *buf, int len, int is_write); /* lance.c */ void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr);