diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 1f508b6576..4b5e470e26 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -942,8 +942,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(0, parallel_hds[0]); for(i = 0; i < MAX_FD; i++) { diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index b3abc61551..d7b301a9cc 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -31,9 +31,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 */ @@ -262,8 +259,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 071b887e4e..9c3e3c5b15 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -1022,9 +1022,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 }; @@ -1332,8 +1329,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 dfcddb31d3..d85f7fdb60 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 cb7167eeb3..889284a239 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -685,7 +685,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 4cdf2303a0..e044923101 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) @@ -707,18 +714,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); @@ -731,7 +733,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) { @@ -739,7 +771,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); @@ -830,8 +865,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) { @@ -842,3 +880,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 f77714e247..37e3dda41b 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -337,9 +337,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 }; @@ -602,8 +599,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]); } }