Index: qemu-0.9.0/hw/ide.c
===================================================================
--- qemu-0.9.0.orig/hw/ide.c	2007-02-28 11:12:55.000000000 +0100
+++ qemu-0.9.0/hw/ide.c	2007-02-28 11:13:04.000000000 +0100
@@ -720,6 +720,7 @@
     return 1;
 }
 
+#if !defined(USE_LIBPOSIX_AIO) || defined(CONFIG_USER_ONLY)
 /* XXX: handle errors */
 static void ide_read_dma_cb(void *opaque, int ret)
 {
@@ -763,6 +764,76 @@
     bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n, 
                               ide_read_dma_cb, bm);
 }
+#else /* USE_LIBPOSIX_AIO */
+static void ide_read_dma_cb(void *opaque, int ret)
+{
+    BMDMAState *bm = opaque;
+    IDEState *s = bm->ide_if;
+    int64_t sector_num;
+    int nsector;
+    int len;
+    uint8_t *phy_addr;
+
+    if (s->nsector == 0) {
+        s->status = READY_STAT | SEEK_STAT;
+	ide_set_irq(s);
+    eot:
+	bm->status &= ~BM_STATUS_DMAING;
+	bm->status |= BM_STATUS_INT;
+	bm->dma_cb = NULL;
+	bm->ide_if = NULL;
+	bm->aiocb = NULL;
+	return;
+    }
+
+    /* launch next transfer */
+
+    if (bm->cur_prd_len == 0) {
+        struct {
+            uint32_t addr;
+            uint32_t size;
+        } prd;
+
+        /* end of table (with a fail safe of one page) */
+
+        if (bm->cur_prd_last ||
+            (bm->cur_addr - bm->addr) >= 4096)
+            return;
+
+        cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);
+        bm->cur_addr += 8;
+        prd.addr = le32_to_cpu(prd.addr);
+        prd.size = le32_to_cpu(prd.size);
+        len = prd.size & 0xfffe;
+        if (len == 0)
+            len = 0x10000;
+        bm->cur_prd_len = len;
+        bm->cur_prd_addr = prd.addr;
+        bm->cur_prd_last = (prd.size & 0x80000000);
+    }
+
+    len = (s->nsector<<9);
+    phy_addr = cpu_physical_page_addr(bm->cur_prd_addr, &len, 1);
+    if (phy_addr == (uint8_t *)-1)
+    	goto eot;
+
+    nsector = (len >>9);
+    bm->cur_prd_addr += (nsector<<9);
+    bm->cur_prd_len -= (nsector<<9);
+
+    sector_num = ide_get_sector(s);
+    ide_set_sector(s, sector_num + nsector);
+    s->nsector -= nsector;
+
+#ifdef DEBUG_AIO
+    printf("aio_read: sector_num=%lld n=%d\n", (unsigned long long)sector_num, 1);
+#endif
+
+    bm->aiocb = bdrv_aio_read(s->bs, sector_num, phy_addr, nsector,
+    			      ide_read_dma_cb, bm);
+
+}
+#endif /* USE_LIBPOSIX_AIO */
 
 static void ide_sector_read_dma(IDEState *s)
 {
@@ -822,6 +893,7 @@
 }
 
 /* XXX: handle errors */
+#if !defined(USE_LIBPOSIX_AIO) || defined(CONFIG_USER_ONLY)
 static void ide_write_dma_cb(void *opaque, int ret)
 {
     BMDMAState *bm = opaque;
@@ -860,11 +932,80 @@
     if (dma_buf_rw(bm, 0) == 0)
         goto eot;
 #ifdef DEBUG_AIO
-    printf("aio_write: sector_num=%lld n=%d\n", sector_num, n);
+    printf("aio_write: sector_num=%lld n=%d\n", (unsigned long long)sector_num, n);
 #endif
     bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n, 
                                ide_write_dma_cb, bm);
 }
+#else
+static void ide_write_dma_cb(void *opaque, int ret)
+{
+    BMDMAState *bm = opaque;
+    IDEState *s = bm->ide_if;
+    int64_t sector_num;
+    int nsector;
+    int len;
+    uint8_t *phy_addr;
+
+    if (s->nsector == 0) {
+        s->status = READY_STAT | SEEK_STAT;
+	ide_set_irq(s);
+    eot:
+	bm->status &= ~BM_STATUS_DMAING;
+	bm->status |= BM_STATUS_INT;
+	bm->dma_cb = NULL;
+	bm->ide_if = NULL;
+	bm->aiocb = NULL;
+	return;
+    }
+
+    /* launch next transfer */
+
+    if (bm->cur_prd_len == 0) {
+        struct {
+            uint32_t addr;
+            uint32_t size;
+        } prd;
+
+        /* end of table (with a fail safe of one page) */
+
+        if (bm->cur_prd_last ||
+            (bm->cur_addr - bm->addr) >= 4096)
+            return;
+
+        cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8);
+        bm->cur_addr += 8;
+        prd.addr = le32_to_cpu(prd.addr);
+        prd.size = le32_to_cpu(prd.size);
+        len = prd.size & 0xfffe;
+        if (len == 0)
+            len = 0x10000;
+        bm->cur_prd_len = len;
+        bm->cur_prd_addr = prd.addr;
+        bm->cur_prd_last = (prd.size & 0x80000000);
+    }
+
+    len = (s->nsector<<9);
+    phy_addr = cpu_physical_page_addr(bm->cur_prd_addr, &len, 0);
+    if (phy_addr == (uint8_t *)-1)
+    	goto eot;
+
+    nsector = (len>>9);
+    bm->cur_prd_addr += (nsector<<9);
+    bm->cur_prd_len -= (nsector<<9);
+
+    sector_num = ide_get_sector(s);
+    ide_set_sector(s, sector_num + nsector);
+    s->nsector-=nsector;
+
+#ifdef DEBUG_AIO
+    printf("aio_write: sector_num=%lld n=%d\n", (unsigned long long)sector_num, nsector);
+#endif
+    bm->aiocb = bdrv_aio_write(s->bs, sector_num, phy_addr, nsector,
+    			      ide_write_dma_cb, bm);
+
+}
+#endif /* !defined(USE_LIBPOSIX_AIO) || defined(CONFIG_USER_ONLY) */
 
 static void ide_sector_write_dma(IDEState *s)
 {
Index: qemu-0.9.0/exec.c
===================================================================
--- qemu-0.9.0.orig/exec.c	2007-02-28 11:12:55.000000000 +0100
+++ qemu-0.9.0/exec.c	2007-02-28 11:13:04.000000000 +0100
@@ -2018,6 +2018,40 @@
 }
 
 #else
+#if defined(USE_LIBPOSIX_AIO)
+uint8_t * cpu_physical_page_addr(target_phys_addr_t addr, int *len, int is_write)
+{
+    int l;
+    target_phys_addr_t page;
+    unsigned long pd;
+    PhysPageDesc *p;
+    unsigned long addr1;
+
+    page = addr & TARGET_PAGE_MASK;
+    l = (page + TARGET_PAGE_SIZE) - addr;
+    if (l > *len)
+    	l = *len;
+    else
+    	*len = l;
+    p = phys_page_find(page >> TARGET_PAGE_BITS);
+    if (!p)
+    	return (uint8_t*)-1;
+
+    pd = p->phys_offset;
+
+    addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+
+    if (is_write && !cpu_physical_memory_is_dirty(addr1)) {
+        /* invalidate code */
+        tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
+        /* set dirty bit */
+        phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
+            (0xff & ~CODE_DIRTY_FLAG);
+    }
+    return phys_ram_base + addr1;
+}
+#endif /* USE_LIBPOSIX_AI0 */
+
 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
                             int len, int is_write)
 {
Index: qemu-0.9.0/cpu-all.h
===================================================================
--- qemu-0.9.0.orig/cpu-all.h	2007-02-28 11:12:55.000000000 +0100
+++ qemu-0.9.0/cpu-all.h	2007-02-28 11:13:04.000000000 +0100
@@ -855,6 +855,7 @@
 CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
 CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
 
+uint8_t * cpu_physical_page_addr(target_phys_addr_t addr, int *len, int is_write);
 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                             int len, int is_write);
 static inline void cpu_physical_memory_read(target_phys_addr_t addr, 

