Index: ioemu/vl.c
===================================================================
--- ioemu.orig/vl.c	2007-05-03 15:07:15.000000000 +0100
+++ ioemu/vl.c	2007-05-03 15:07:15.000000000 +0100
@@ -5924,6 +5924,7 @@
     unsigned long ioreq_pfn;
     extern void *shared_page;
     extern void *buffered_io_page;
+    extern void *buffered_pio_page;
     unsigned long nr_pages;
 
     char qemu_dm_logfilename[64];
@@ -6530,6 +6531,10 @@
                                        PROT_READ|PROT_WRITE,
                                        BUFFER_IO_PAGE_START >> PAGE_SHIFT);
 
+    buffered_pio_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+                                       PROT_READ|PROT_WRITE,
+                                       BUFFER_PIO_PAGE_START >> PAGE_SHIFT);
+
     for (i = 0; i < nr_pages; i++)
         page_array[i] = i;
 	
Index: ioemu/hw/ide.c
===================================================================
--- ioemu.orig/hw/ide.c	2007-05-03 15:07:15.000000000 +0100
+++ ioemu/hw/ide.c	2007-05-03 15:07:15.000000000 +0100
@@ -474,6 +474,121 @@
 }
 #endif /* DMA_MULTI_THREAD */
 
+#if defined(__ia64__)
+#include <xen/hvm/ioreq.h>
+
+struct buffered_piopage *buffered_pio_page;
+
+static inline struct pio_buffer *
+piobuf_by_addr(uint32_t addr)
+{
+    if (addr == 0x1F0)
+        return &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY];
+    if (addr == 0x170)
+        return &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY];
+    return NULL;
+}
+
+static void
+buffered_pio_init(void)
+{
+    struct pio_buffer *p1, *p2;
+    uint32_t off1, off2;
+
+    if (!buffered_pio_page)
+        return;
+
+    p1 = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY];
+    p2 = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY];
+    off1 = offsetof(struct buffered_piopage, buffer);
+    off2 = (off1 + TARGET_PAGE_SIZE)/2;
+
+    p1->buf_size = off2 - off1;
+    p1->page_offset = off1;
+
+    p2->buf_size = TARGET_PAGE_SIZE - off2;
+    p2->page_offset = off2;
+}
+
+static inline void
+buffered_pio_flush(struct pio_buffer *piobuf)
+{
+    IDEState *s = piobuf->opaque;
+    uint32_t pointer = piobuf->pointer;
+
+    if (s != NULL && pointer > 0) {
+        uint8_t *buf = (uint8_t *)buffered_pio_page + piobuf->page_offset;
+        memcpy(s->data_ptr, buf, pointer);
+        s->data_ptr += pointer;
+    }
+}
+
+static inline void
+buffered_pio_reset(IDEState *s)
+{
+    struct pio_buffer *piobuf;
+
+    if ((unsigned)s->drive_serial - 1 < 2)      /* 1,2 */
+        piobuf = &buffered_pio_page->pio[PIO_BUFFER_IDE_PRIMARY];
+    else if ((unsigned)s->drive_serial - 3 < 2) /* 3,4 */
+        piobuf = &buffered_pio_page->pio[PIO_BUFFER_IDE_SECONDARY];
+    else
+        return;
+    buffered_pio_flush(piobuf);
+    piobuf->pointer = 0;
+    piobuf->data_end = 0;
+    piobuf->opaque = NULL;
+}
+
+static inline void
+buffered_pio_write(IDEState *s, uint32_t addr, int size)
+{
+    struct pio_buffer *piobuf = piobuf_by_addr(addr);
+    int data_end;
+
+    if (!piobuf)
+        return;
+    buffered_pio_flush(piobuf);
+    data_end = s->data_end - s->data_ptr - size;
+    if (data_end <= 0)
+        data_end = 0;
+    else if (data_end > piobuf->buf_size)
+        data_end = piobuf->buf_size;
+    piobuf->pointer = 0;
+    piobuf->data_end = data_end;
+    piobuf->opaque = s;
+}
+
+static inline void
+buffered_pio_read(IDEState *s, uint32_t addr, int size)
+{
+    struct pio_buffer *piobuf = piobuf_by_addr(addr);
+    int data_end;
+
+    if (!piobuf)
+        return;
+    s->data_ptr += piobuf->pointer;
+    data_end = s->data_end - s->data_ptr - size;
+    if (data_end <= 0) {
+        data_end = 0;
+    } else {
+	uint8_t *buf = (uint8_t *)buffered_pio_page + piobuf->page_offset;
+        if (data_end > piobuf->buf_size)
+            data_end = piobuf->buf_size;
+        memcpy(buf, s->data_ptr + size, data_end);
+    }
+    piobuf->pointer = 0;
+    piobuf->data_end = data_end;
+    piobuf->opaque = NULL;
+}
+
+#else /* !__ia64__ */
+#define buffered_pio_init()         do {} while (0)
+#define buffered_pio_reset(I)       do {} while (0)
+#define buffered_pio_write(I,A,S)   do {} while (0)
+#define buffered_pio_read(I,A,S)    do {} while (0)
+#endif
+
 static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb);
 
 static void padstr(char *str, const char *src, int len)
@@ -658,6 +773,7 @@
     s->data_ptr = buf;
     s->data_end = buf + size;
     s->status |= DRQ_STAT;
+    buffered_pio_reset(s);
 }
 
 static void ide_transfer_stop(IDEState *s)
@@ -666,6 +782,7 @@
     s->data_ptr = s->io_buffer;
     s->data_end = s->io_buffer;
     s->status &= ~DRQ_STAT;
+    buffered_pio_reset(s);
 }
 
 static int64_t ide_get_sector(IDEState *s)
@@ -1578,6 +1695,7 @@
         ide_if[0].select = (val & ~0x10) | 0xa0;
         ide_if[1].select = (val | 0x10) | 0xa0;
         /* select drive */
+        buffered_pio_reset(ide_if->cur_drive);
         unit = (val >> 4) & 1;
         s = ide_if + unit;
         ide_if->cur_drive = s;
@@ -1936,6 +2054,7 @@
     IDEState *s = ((IDEState *)opaque)->cur_drive;
     uint8_t *p;
 
+    buffered_pio_write(s, addr, 2);
     p = s->data_ptr;
     *(uint16_t *)p = le16_to_cpu(val);
     p += 2;
@@ -1949,6 +2068,8 @@
     IDEState *s = ((IDEState *)opaque)->cur_drive;
     uint8_t *p;
     int ret;
+    
+    buffered_pio_read(s, addr, 2);
     p = s->data_ptr;
     ret = cpu_to_le16(*(uint16_t *)p);
     p += 2;
@@ -1963,6 +2084,7 @@
     IDEState *s = ((IDEState *)opaque)->cur_drive;
     uint8_t *p;
 
+    buffered_pio_write(s, addr, 4);
     p = s->data_ptr;
     *(uint32_t *)p = le32_to_cpu(val);
     p += 4;
@@ -1977,6 +2099,7 @@
     uint8_t *p;
     int ret;
     
+    buffered_pio_read(s, addr, 4);
     p = s->data_ptr;
     ret = cpu_to_le32(*(uint32_t *)p);
     p += 4;
@@ -2634,6 +2757,8 @@
     ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
     ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
 
+    buffered_pio_init();
+
     register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
     register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
 
