Index: qemu/hw/sun4m.c =================================================================== --- qemu.orig/hw/sun4m.c 2007-08-20 20:11:31.000000000 +0000 +++ qemu/hw/sun4m.c 2007-08-22 20:03:28.000000000 +0000 @@ -82,19 +82,10 @@ { return 0; } -int DMA_read_memory (int nchan, void *buf, int pos, int size) -{ - return 0; -} -int DMA_write_memory (int nchan, void *buf, int pos, int size) -{ - return 0; -} void DMA_hold_DREQ (int nchan) {} void DMA_release_DREQ (int nchan) {} void DMA_schedule(int nchan) {} void DMA_run (void) {} -void DMA_init (int high_page_enable) {} void DMA_register_channel (int nchan, DMA_transfer_handler transfer_handler, void *opaque) @@ -289,6 +280,17 @@ slavio_set_power_fail(slavio_misc, 1); } +static void sparc_dma_memory_rw(void *opaque, target_phys_addr_t addr, + uint8_t *buf, int len, int is_write) +{ + cpu_physical_memory_rw(addr, buf, len, is_write); +} + +static void sparc_dummy_memory_rw(void *opaque, target_phys_addr_t addr, + uint8_t *buf, int len, int is_write) +{ +} + static void main_cpu_reset(void *opaque) { CPUState *env = opaque; @@ -316,6 +318,7 @@ qemu_irq *cpu_irqs[MAX_CPUS], *slavio_irq, *slavio_cpu_irq, *espdma_irq, *ledma_irq; qemu_irq *esp_reset, *le_reset; + qemu_dma *physical_dma, *dummy_dma, *dvma; /* init CPUs */ sparc_find_by_name(cpu_model, &def); @@ -344,7 +347,11 @@ /* allocate RAM */ cpu_register_physical_memory(0, RAM_size, 0); - iommu = iommu_init(hwdef->iommu_base); + physical_dma = qemu_init_dma(sparc_dma_memory_rw, NULL); + dummy_dma = qemu_init_dma(sparc_dummy_memory_rw, NULL); + + iommu = iommu_init(hwdef->iommu_base, physical_dma, &dvma); + slavio_intctl = slavio_intctl_init(hwdef->intctl_base, hwdef->intctl_base + 0x10000ULL, &hwdef->intbit_to_level[0], @@ -391,7 +398,8 @@ // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq], serial_hds[1], serial_hds[0]); - fdctrl_init(slavio_irq[hwdef->fd_irq], 0, 1, hwdef->fd_base, fd_table); + fdctrl_init(slavio_irq[hwdef->fd_irq], 0, 1, hwdef->fd_base, fd_table, + dummy_dma); main_esp = esp_init(bs_table, hwdef->esp_base, espdma, *espdma_irq, esp_reset); Index: qemu/hw/iommu.c =================================================================== --- qemu.orig/hw/iommu.c 2007-08-20 20:11:31.000000000 +0000 +++ qemu/hw/iommu.c 2007-08-22 19:53:40.000000000 +0000 @@ -104,6 +104,7 @@ target_phys_addr_t addr; uint32_t regs[IOMMU_NREGS]; target_phys_addr_t iostart; + qemu_dma *parent_dma; } IOMMUState; static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr) @@ -202,7 +203,8 @@ static uint32_t iommu_page_get_flags(IOMMUState *s, target_phys_addr_t addr) { - uint32_t iopte, ret; + uint32_t ret; + target_phys_addr_t iopte; #ifdef DEBUG_IOMMU target_phys_addr_t pa = addr; #endif @@ -210,7 +212,8 @@ iopte = s->regs[IOMMU_BASE] << 4; addr &= ~s->iostart; iopte += (addr >> (PAGE_SHIFT - 2)) & ~3; - ret = ldl_phys(iopte); + dma_memory_read(s->parent_dma, iopte, (uint8_t *)&ret, 4); + bswap32s(&ret); DPRINTF("get flags addr " TARGET_FMT_plx " => pte %x, *ptes = %x\n", pa, iopte, ret); @@ -245,6 +248,7 @@ void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write) { + IOMMUState *s = opaque; int l; uint32_t flags; target_phys_addr_t page, phys_addr; @@ -259,16 +263,12 @@ iommu_bad_addr(opaque, page, is_write); return; } - phys_addr = iommu_translate_pa(opaque, addr, flags); - if (is_write) { - if (!(flags & IOPTE_WRITE)) { - iommu_bad_addr(opaque, page, is_write); - return; - } - cpu_physical_memory_write(phys_addr, buf, len); - } else { - cpu_physical_memory_read(phys_addr, buf, len); + if (is_write && !(flags & IOPTE_WRITE)) { + iommu_bad_addr(opaque, page, is_write); + return; } + phys_addr = iommu_translate_pa(opaque, addr, flags); + dma_memory_rw(s->parent_dma, phys_addr, buf, len, is_write); len -= l; buf += l; addr += l; @@ -309,7 +309,8 @@ s->regs[IOMMU_CTRL] = IOMMU_VERSION; } -void *iommu_init(target_phys_addr_t addr) +void *iommu_init(target_phys_addr_t addr, qemu_dma *parent_dma, + qemu_dma **dvma) { IOMMUState *s; int iommu_io_memory; @@ -322,7 +323,10 @@ iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s); cpu_register_physical_memory(addr, IOMMU_NREGS * 4, iommu_io_memory); - + + s->parent_dma = parent_dma; + *dvma = qemu_init_dma(sparc_iommu_memory_rw, s); + register_savevm("iommu", addr, 2, iommu_save, iommu_load, s); qemu_register_reset(iommu_reset, s); return s; Index: qemu/vl.h =================================================================== --- qemu.orig/vl.h 2007-08-22 19:51:31.000000000 +0000 +++ qemu/vl.h 2007-08-22 20:03:09.000000000 +0000 @@ -1263,7 +1263,8 @@ extern QEMUMachine ss5_machine, ss10_machine; /* iommu.c */ -void *iommu_init(target_phys_addr_t addr); +void *iommu_init(target_phys_addr_t addr, qemu_dma *parent_dma, + qemu_dma **dvma); void sparc_iommu_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write); static inline void sparc_iommu_memory_read(void *opaque,