diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 260f266..ed11b45 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -933,8 +933,8 @@ void mips_malta_init (ram_addr_t ram_size,
     isa_dev = isa_create_simple("i8042");
  
     rtc_state = rtc_init(2000);
-    serial_init(0x3f8, isa_reserve_irq(4), 115200, serial_hds[0]);
-    serial_init(0x2f8, isa_reserve_irq(3), 115200, serial_hds[1]);
+    serial_isa_init(0, serial_hds[0]);
+    serial_isa_init(1, serial_hds[1]);
     if (parallel_hds[0])
         parallel_init(0x378, isa_reserve_irq(7), parallel_hds[0]);
     for(i = 0; i < MAX_FD; i++) {
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index fcc7fed..4c94568 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -29,9 +29,6 @@ static const int ide_iobase[2] = { 0x1f0, 0x170 };
 static const int ide_iobase2[2] = { 0x3f6, 0x376 };
 static const int ide_irq[2] = { 14, 15 };
 
-static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
-static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
-
 static PITState *pit; /* PIT i8254 */
 
 /* i8254 PIT is attached to the IRQ0 at PIC i8259 */
@@ -254,8 +251,7 @@ void mips_r4k_init (ram_addr_t ram_size,
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_init(serial_io[i], i8259[serial_irq[i]], 115200,
-                        serial_hds[i]);
+            serial_isa_init(i, serial_hds[i]);
         }
     }
 
diff --git a/hw/pc.c b/hw/pc.c
index 8865ec0..052c0a2 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1019,9 +1019,6 @@ static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
                                               0x280, 0x380 };
 static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
 
-static const int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
-static const int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
-
 static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
@@ -1329,8 +1326,7 @@ static void pc_init1(ram_addr_t ram_size,
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_init(serial_io[i], isa_reserve_irq(serial_irq[i]), 115200,
-                        serial_hds[i]);
+            serial_isa_init(i, serial_hds[i]);
         }
     }
 
diff --git a/hw/pc.h b/hw/pc.h
index c9cdd4a..b547d17 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -12,6 +12,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
 SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
                              qemu_irq irq, int baudbase,
                              CharDriverState *chr, int ioregister);
+SerialState *serial_isa_init(int index, CharDriverState *chr);
 
 /* parallel.c */
 
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 32f987c..3f57cbb 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -684,7 +684,8 @@ static void ppc_prep_init (ram_addr_t ram_size,
     //    pit = pit_init(0x40, i8259[0]);
     rtc_init(2000);
 
-    serial_init(0x3f8, i8259[4], 115200, serial_hds[0]);
+    if (serial_hds[0])
+        serial_isa_init(0, serial_hds[0]);
     nb_nics1 = nb_nics;
     if (nb_nics1 > NE2000_NB_MAX)
         nb_nics1 = NE2000_NB_MAX;
diff --git a/hw/serial.c b/hw/serial.c
index 1f4ce77..81021e9 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -146,6 +146,13 @@ struct SerialState {
     struct QEMUTimer *modem_status_poll;
 };
 
+typedef struct ISASerialState {
+    ISADevice dev;
+    uint32_t iobase;
+    uint32_t isairq;
+    SerialState state;
+} ISASerialState;
+
 static void serial_receive1(void *opaque, const uint8_t *buf, int size);
 
 static void fifo_clear(SerialState *s, int fifo)
@@ -709,18 +716,13 @@ static void serial_reset(void *opaque)
     qemu_irq_lower(s->irq);
 }
 
-static void serial_init_core(SerialState *s, qemu_irq irq, int baudbase,
-			     CharDriverState *chr)
+static void serial_init_core(SerialState *s)
 {
-    if (!chr) {
+    if (!s->chr) {
         fprintf(stderr, "Can't create serial device, empty char device\n");
 	exit(1);
     }
 
-    s->irq = irq;
-    s->baudbase = baudbase;
-    s->chr = chr;
-
     s->modem_status_poll = qemu_new_timer(vm_clock, (QEMUTimerCB *) serial_update_msl, s);
 
     s->fifo_timeout_timer = qemu_new_timer(vm_clock, (QEMUTimerCB *) fifo_timeout_int, s);
@@ -733,7 +735,37 @@ static void serial_init_core(SerialState *s, qemu_irq irq, int baudbase,
                           serial_event, s);
 }
 
-/* If fd is zero, it means that the serial device uses the console */
+static int serial_isa_initfn(ISADevice *dev)
+{
+    ISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev);
+    SerialState *s = &isa->state;
+
+    s->baudbase = 115200;
+    isa_init_irq(dev, &s->irq, isa->isairq);
+    serial_init_core(s);
+    vmstate_register(isa->iobase, &vmstate_serial, s);
+
+    register_ioport_write(isa->iobase, 8, 1, serial_ioport_write, s);
+    register_ioport_read(isa->iobase, 8, 1, serial_ioport_read, s);
+    return 0;
+}
+
+static const int isa_serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+static const int isa_serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
+
+SerialState *serial_isa_init(int index, CharDriverState *chr)
+{
+    ISADevice *dev;
+
+    dev = isa_create("isa-serial");
+    qdev_prop_set_uint32(&dev->qdev, "iobase", isa_serial_io[index]);
+    qdev_prop_set_uint32(&dev->qdev, "irq", isa_serial_irq[index]);
+    qdev_prop_set_chr(&dev->qdev, "chardev", chr);
+    if (qdev_init(&dev->qdev) != 0)
+        return NULL;
+    return &DO_UPCAST(ISASerialState, dev, dev)->state;
+}
+
 SerialState *serial_init(int base, qemu_irq irq, int baudbase,
                          CharDriverState *chr)
 {
@@ -741,7 +773,10 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
 
     s = qemu_mallocz(sizeof(SerialState));
 
-    serial_init_core(s, irq, baudbase, chr);
+    s->irq = irq;
+    s->baudbase = baudbase;
+    s->chr = chr;
+    serial_init_core(s);
 
     vmstate_register(base, &vmstate_serial, s);
 
@@ -832,8 +867,11 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
     s = qemu_mallocz(sizeof(SerialState));
 
     s->it_shift = it_shift;
+    s->irq = irq;
+    s->baudbase = baudbase;
+    s->chr = chr;
 
-    serial_init_core(s, irq, baudbase, chr);
+    serial_init_core(s);
     vmstate_register(base, &vmstate_serial, s);
 
     if (ioregister) {
@@ -844,3 +882,22 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
     serial_update_msl(s);
     return s;
 }
+
+static ISADeviceInfo serial_isa_info = {
+    .qdev.name  = "isa-serial",
+    .qdev.size  = sizeof(ISASerialState),
+    .init       = serial_isa_initfn,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_HEX32("iobase", ISASerialState, iobase,  0x3f8),
+        DEFINE_PROP_UINT32("irq",   ISASerialState, isairq,  4),
+        DEFINE_PROP_CHR("chardev",  ISASerialState, state.chr),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void serial_register_devices(void)
+{
+    isa_qdev_register(&serial_isa_info);
+}
+
+device_init(serial_register_devices)
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 81ddf48..2b55cf3 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -326,9 +326,6 @@ void cpu_tick_set_limit(void *opaque, uint64_t limit)
     ptimer_set_limit(opaque, -limit, 0);
 }
 
-static const int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
-static const int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
-
 static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
@@ -590,8 +587,7 @@ static void sun4uv_init(ram_addr_t RAM_size,
     }
     for(; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
-            serial_init(serial_io[i], NULL/*serial_irq[i]*/, 115200,
-                        serial_hds[i]);
+            serial_isa_init(i, serial_hds[i]);
         }
     }
 
