diff --git a/Makefile.objs b/Makefile.objs
index 5241262..3fddb8e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -221,7 +221,7 @@ hw-obj-$(CONFIG_LAN9118) += lan9118.o
 hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
 
 # IDE
-hw-obj-$(CONFIG_IDE_CORE) += ide/core.o
+hw-obj-$(CONFIG_IDE_CORE) += ide/core.o ide/pata.o
 hw-obj-$(CONFIG_IDE_QDEV) += ide/qdev.o
 hw-obj-$(CONFIG_IDE_PCI) += ide/pci.o
 hw-obj-$(CONFIG_IDE_ISA) += ide/isa.o
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 073c038..e6ee31d 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -34,8 +34,6 @@
 
 #include <hw/ide/internal.h>
 
-#define IDE_PAGE_SIZE 4096
-
 static const int smart_attributes[][5] = {
     /* id,  flags, val, wrst, thrsh */
     { 0x01, 0x03, 0x64, 0x64, 0x06}, /* raw read */
@@ -67,8 +65,6 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
 static int ide_handle_rw_error(IDEState *s, int error, int op);
 static void ide_flush_cache(IDEState *s);
 
-static void pata_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb);
-
 static void padstr(char *str, const char *src, int len)
 {
     int i, v;
@@ -337,16 +333,6 @@ static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
     s->bus->ops->transfer_start_fn(s,buf,size,end_transfer_func);
 }
 
-static void pata_transfer_start(IDEState *s, uint8_t *buf, int size,
-                               EndTransferFunc *end_transfer_func)
-{
-    s->end_transfer_func = end_transfer_func;
-    s->data_ptr = buf;
-    s->data_end = buf + size;
-    if (!(s->status & ERR_STAT))
-        s->status |= DRQ_STAT;
-}
-
 static void ide_transfer_stop(IDEState *s)
 {
     s->end_transfer_func = ide_transfer_stop;
@@ -443,46 +429,6 @@ static void ide_sector_read(IDEState *s)
 }
 
 
-/* return 0 if buffer completed */
-static int dma_buf_prepare(BMDMAState *bm, int is_write)
-{
-    IDEState *s = bmdma_active_if(bm);
-    struct {
-        uint32_t addr;
-        uint32_t size;
-    } prd;
-    int l, len;
-
-    qemu_sglist_init(&s->sg, s->nsector / (IDE_PAGE_SIZE / 512) + 1);
-    s->io_buffer_size = 0;
-    for(;;) {
-        if (bm->cur_prd_len == 0) {
-            /* end of table (with a fail safe of one page) */
-            if (bm->cur_prd_last ||
-                (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE)
-                return s->io_buffer_size != 0;
-            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);
-        }
-        l = bm->cur_prd_len;
-        if (l > 0) {
-            qemu_sglist_add(&s->sg, bm->cur_prd_addr, l);
-            bm->cur_prd_addr += l;
-            bm->cur_prd_len -= l;
-            s->io_buffer_size += l;
-        }
-    }
-    return 1;
-}
-
 static void dma_buf_commit(IDEState *s, int is_write)
 {
     qemu_sglist_destroy(&s->sg);
@@ -525,54 +471,6 @@ static int ide_handle_rw_error(IDEState *s, int error, int op)
     return 1;
 }
 
-/* return 0 if buffer completed */
-static int dma_buf_rw(BMDMAState *bm, int is_write)
-{
-    IDEState *s = bmdma_active_if(bm);
-    struct {
-        uint32_t addr;
-        uint32_t size;
-    } prd;
-    int l, len;
-
-    for(;;) {
-        l = s->io_buffer_size - s->io_buffer_index;
-        if (l <= 0)
-            break;
-        if (bm->cur_prd_len == 0) {
-            /* end of table (with a fail safe of one page) */
-            if (bm->cur_prd_last ||
-                (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE)
-                return 0;
-            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);
-        }
-        if (l > bm->cur_prd_len)
-            l = bm->cur_prd_len;
-        if (l > 0) {
-            if (is_write) {
-                cpu_physical_memory_write(bm->cur_prd_addr,
-                                          s->io_buffer + s->io_buffer_index, l);
-            } else {
-                cpu_physical_memory_read(bm->cur_prd_addr,
-                                          s->io_buffer + s->io_buffer_index, l);
-            }
-            bm->cur_prd_addr += l;
-            bm->cur_prd_len -= l;
-            s->io_buffer_index += l;
-        }
-    }
-    return 1;
-}
-
 static void ide_read_dma_cb(void *opaque, int ret)
 {
     BMDMAState *bm = opaque;
@@ -2595,18 +2493,6 @@ static void ide_dummy_transfer_stop(IDEState *s)
     s->io_buffer[3] = 0xff;
 }
 
-static void pata_set_irq(IDEBus *bus)
-{
-    BMDMAState *bm = bus->bmdma;
-
-    if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) {
-        if (bm) {
-            bm->status |= BM_STATUS_INT;
-        }
-        qemu_irq_raise(bus->irq);
-    }
-}
-
 static void ide_reset(IDEState *s)
 {
 #ifdef DEBUG_IDE
@@ -2744,14 +2630,6 @@ static void ide_init1(IDEBus *bus, int unit)
                                            ide_sector_write_timer_cb, s);
 }
 
-static IDEBusOps ide_bus_ops = {
-    .transfer_start_fn = pata_transfer_start,
-    .irq_set_fn = pata_set_irq,
-    .dma_start_fn = pata_dma_start,
-    .dma_prepare_fn = dma_buf_prepare,
-    .dma_rw_fn = dma_buf_rw,
-};
-
 void ide_init2(IDEBus *bus, qemu_irq irq)
 {
     int i;
@@ -2761,7 +2639,7 @@ void ide_init2(IDEBus *bus, qemu_irq irq)
         ide_reset(&bus->ifs[i]);
     }
     bus->irq = irq;
-    bus->ops = &ide_bus_ops;
+    pata_init(bus);
 }
 
 /* TODO convert users to qdev and remove */
@@ -2785,7 +2663,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
         }
     }
     bus->irq = irq;
-    bus->ops = &ide_bus_ops;
+    pata_init(bus);
 }
 
 void ide_init_ioport(IDEBus *bus, int iobase, int iobase2)
@@ -2957,24 +2835,6 @@ const VMStateDescription vmstate_ide_bus = {
 /***********************************************************/
 /* PCI IDE definitions */
 
-static void pata_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb)
-{
-    BMDMAState *bm = s->bus->bmdma;
-
-    if(!bm)
-        return;
-    bm->unit = s->unit;
-    bm->dma_cb = dma_cb;
-    bm->cur_prd_last = 0;
-    bm->cur_prd_addr = 0;
-    bm->cur_prd_len = 0;
-    bm->sector_num = ide_get_sector(s);
-    bm->nsector = s->nsector;
-    if (bm->status & BM_STATUS_DMAING) {
-        bm->dma_cb(bm, 0);
-    }
-}
-
 static void ide_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb)
 {
     s->bus->ops->dma_start_fn(s,dma_cb);
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 1261eea..dc69a1f 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -588,4 +588,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val);
 void ide_bus_new(IDEBus *idebus, DeviceState *dev);
 IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive);
 
+/* hw/ide/pata.c */
+void pata_init(IDEBus *bus);
+
 #endif /* HW_IDE_INTERNAL_H */
diff --git a/hw/ide/pata.c b/hw/ide/pata.c
new file mode 100644
index 0000000..13cb53a
--- /dev/null
+++ b/hw/ide/pata.c
@@ -0,0 +1,178 @@
+/*
+ * QEMU Parallel ATA (IDE) Emulator
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ * Copyright (c) 2006 Openedhand Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <hw/hw.h>
+#include <hw/pc.h>
+#include <hw/pci.h>
+#include <hw/scsi.h>
+#include "qemu-error.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "dma.h"
+#include "blockdev.h"
+
+#include <hw/ide/internal.h>
+
+#define IDE_PAGE_SIZE 4096
+
+static void pata_dma_start(IDEState *s, BlockDriverCompletionFunc *dma_cb)
+{
+    BMDMAState *bm = s->bus->bmdma;
+
+    if(!bm)
+        return;
+    bm->unit = s->unit;
+    bm->dma_cb = dma_cb;
+    bm->cur_prd_last = 0;
+    bm->cur_prd_addr = 0;
+    bm->cur_prd_len = 0;
+    bm->sector_num = ide_get_sector(s);
+    bm->nsector = s->nsector;
+    if (bm->status & BM_STATUS_DMAING) {
+        bm->dma_cb(bm, 0);
+    }
+}
+
+static void pata_transfer_start(IDEState *s, uint8_t *buf, int size,
+                               EndTransferFunc *end_transfer_func)
+{
+    s->end_transfer_func = end_transfer_func;
+    s->data_ptr = buf;
+    s->data_end = buf + size;
+    if (!(s->status & ERR_STAT))
+        s->status |= DRQ_STAT;
+}
+
+static void pata_set_irq(IDEBus *bus)
+{
+    BMDMAState *bm = bus->bmdma;
+
+    if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) {
+        if (bm) {
+            bm->status |= BM_STATUS_INT;
+        }
+        qemu_irq_raise(bus->irq);
+    }
+}
+
+/* return 0 if buffer completed */
+static int dma_buf_prepare(BMDMAState *bm, int is_write)
+{
+    IDEState *s = bmdma_active_if(bm);
+    struct {
+        uint32_t addr;
+        uint32_t size;
+    } prd;
+    int l, len;
+
+    qemu_sglist_init(&s->sg, s->nsector / (IDE_PAGE_SIZE / 512) + 1);
+    s->io_buffer_size = 0;
+    for(;;) {
+        if (bm->cur_prd_len == 0) {
+            /* end of table (with a fail safe of one page) */
+            if (bm->cur_prd_last ||
+                (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE)
+                return s->io_buffer_size != 0;
+            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);
+        }
+        l = bm->cur_prd_len;
+        if (l > 0) {
+            qemu_sglist_add(&s->sg, bm->cur_prd_addr, l);
+            bm->cur_prd_addr += l;
+            bm->cur_prd_len -= l;
+            s->io_buffer_size += l;
+        }
+    }
+    return 1;
+}
+
+/* return 0 if buffer completed */
+static int dma_buf_rw(BMDMAState *bm, int is_write)
+{
+    IDEState *s = bmdma_active_if(bm);
+    struct {
+        uint32_t addr;
+        uint32_t size;
+    } prd;
+    int l, len;
+
+    for(;;) {
+        l = s->io_buffer_size - s->io_buffer_index;
+        if (l <= 0)
+            break;
+        if (bm->cur_prd_len == 0) {
+            /* end of table (with a fail safe of one page) */
+            if (bm->cur_prd_last ||
+                (bm->cur_addr - bm->addr) >= IDE_PAGE_SIZE)
+                return 0;
+            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);
+        }
+        if (l > bm->cur_prd_len)
+            l = bm->cur_prd_len;
+        if (l > 0) {
+            if (is_write) {
+                cpu_physical_memory_write(bm->cur_prd_addr,
+                                          s->io_buffer + s->io_buffer_index, l);
+            } else {
+                cpu_physical_memory_read(bm->cur_prd_addr,
+                                          s->io_buffer + s->io_buffer_index, l);
+            }
+            bm->cur_prd_addr += l;
+            bm->cur_prd_len -= l;
+            s->io_buffer_index += l;
+        }
+    }
+    return 1;
+}
+
+static IDEBusOps ide_bus_ops = {
+    .transfer_start_fn = pata_transfer_start,
+    .irq_set_fn = pata_set_irq,
+    .dma_start_fn = pata_dma_start,
+    .dma_prepare_fn = dma_buf_prepare,
+    .dma_rw_fn = dma_buf_rw,
+};
+
+void pata_init(IDEBus *bus)
+{
+    bus->ops = &ide_bus_ops;
+}
