mirror of https://gitee.com/openkylin/qemu.git
serial: split serial.c
Split serial.c into serial.c, serial.h and serial-isa.c. While being at creating a serial.h header file move the serial prototypes from pc.h to the new serial.h. The latter leads to s/pc.h/serial.h/ in tons of boards which just want the serial bits from pc.h Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
ad0b5321f1
commit
488cb996cd
|
@ -20,7 +20,7 @@ common-obj-$(CONFIG_M48T59) += m48t59.o
|
||||||
common-obj-$(CONFIG_ESCC) += escc.o
|
common-obj-$(CONFIG_ESCC) += escc.o
|
||||||
common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
|
common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
|
||||||
|
|
||||||
common-obj-$(CONFIG_SERIAL) += serial.o
|
common-obj-$(CONFIG_SERIAL) += serial.o serial-isa.o
|
||||||
common-obj-$(CONFIG_PARALLEL) += parallel.o
|
common-obj-$(CONFIG_PARALLEL) += parallel.o
|
||||||
common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
|
common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
|
||||||
common-obj-$(CONFIG_PCSPK) += pcspk.o
|
common-obj-$(CONFIG_PCSPK) += pcspk.o
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "mc146818rtc.h"
|
#include "mc146818rtc.h"
|
||||||
#include "ide.h"
|
#include "ide.h"
|
||||||
#include "i8254.h"
|
#include "i8254.h"
|
||||||
|
#include "serial.h"
|
||||||
|
|
||||||
#define MAX_IDE_BUS 2
|
#define MAX_IDE_BUS 2
|
||||||
|
|
||||||
|
|
2
hw/kzm.c
2
hw/kzm.c
|
@ -21,7 +21,7 @@
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
#include "boards.h"
|
#include "boards.h"
|
||||||
#include "pc.h" /* for the FPGA UART that emulates a 16550 */
|
#include "serial.h"
|
||||||
#include "imx.h"
|
#include "imx.h"
|
||||||
|
|
||||||
/* Memory map for Kzm Emulation Baseboard:
|
/* Memory map for Kzm Emulation Baseboard:
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "pc.h"
|
#include "pc.h"
|
||||||
|
#include "serial.h"
|
||||||
#include "fdc.h"
|
#include "fdc.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "boards.h"
|
#include "boards.h"
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "mips.h"
|
#include "mips.h"
|
||||||
#include "mips_cpudevs.h"
|
#include "mips_cpudevs.h"
|
||||||
#include "pc.h"
|
#include "pc.h"
|
||||||
|
#include "serial.h"
|
||||||
#include "isa.h"
|
#include "isa.h"
|
||||||
#include "fdc.h"
|
#include "fdc.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "pc.h"
|
#include "pc.h"
|
||||||
|
#include "serial.h"
|
||||||
#include "fdc.h"
|
#include "fdc.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "boards.h"
|
#include "boards.h"
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "mips.h"
|
#include "mips.h"
|
||||||
#include "mips_cpudevs.h"
|
#include "mips_cpudevs.h"
|
||||||
#include "pc.h"
|
#include "serial.h"
|
||||||
#include "isa.h"
|
#include "isa.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "mips.h"
|
#include "mips.h"
|
||||||
#include "mips_cpudevs.h"
|
#include "mips_cpudevs.h"
|
||||||
#include "pc.h"
|
#include "pc.h"
|
||||||
|
#include "serial.h"
|
||||||
#include "isa.h"
|
#include "isa.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
#include "boards.h"
|
#include "boards.h"
|
||||||
#include "pc.h"
|
#include "serial.h"
|
||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
#include "ptimer.h"
|
#include "ptimer.h"
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
|
|
|
@ -20,8 +20,7 @@
|
||||||
#include "qemu-char.h"
|
#include "qemu-char.h"
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "omap.h"
|
#include "omap.h"
|
||||||
/* We use pc-style serial ports. */
|
#include "serial.h"
|
||||||
#include "pc.h"
|
|
||||||
#include "exec-memory.h"
|
#include "exec-memory.h"
|
||||||
|
|
||||||
/* UARTs */
|
/* UARTs */
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "boards.h"
|
#include "boards.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "pc.h"
|
#include "serial.h"
|
||||||
|
#include "net.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "exec-memory.h"
|
#include "exec-memory.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
|
|
1
hw/pc.c
1
hw/pc.c
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "pc.h"
|
#include "pc.h"
|
||||||
|
#include "serial.h"
|
||||||
#include "apic.h"
|
#include "apic.h"
|
||||||
#include "fdc.h"
|
#include "fdc.h"
|
||||||
#include "ide.h"
|
#include "ide.h"
|
||||||
|
|
27
hw/pc.h
27
hw/pc.h
|
@ -12,33 +12,6 @@
|
||||||
|
|
||||||
/* PC-style peripherals (also used by other machines). */
|
/* PC-style peripherals (also used by other machines). */
|
||||||
|
|
||||||
/* serial.c */
|
|
||||||
|
|
||||||
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
|
|
||||||
CharDriverState *chr);
|
|
||||||
SerialState *serial_mm_init(MemoryRegion *address_space,
|
|
||||||
target_phys_addr_t base, int it_shift,
|
|
||||||
qemu_irq irq, int baudbase,
|
|
||||||
CharDriverState *chr, enum device_endian);
|
|
||||||
static inline bool serial_isa_init(ISABus *bus, int index,
|
|
||||||
CharDriverState *chr)
|
|
||||||
{
|
|
||||||
ISADevice *dev;
|
|
||||||
|
|
||||||
dev = isa_try_create(bus, "isa-serial");
|
|
||||||
if (!dev) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
qdev_prop_set_uint32(&dev->qdev, "index", index);
|
|
||||||
qdev_prop_set_chr(&dev->qdev, "chardev", chr);
|
|
||||||
if (qdev_init(&dev->qdev) < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void serial_set_frequency(SerialState *s, uint32_t frequency);
|
|
||||||
|
|
||||||
/* parallel.c */
|
/* parallel.c */
|
||||||
static inline bool parallel_init(ISABus *bus, int index, CharDriverState *chr)
|
static inline bool parallel_init(ISABus *bus, int index, CharDriverState *chr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include "boards.h"
|
#include "boards.h"
|
||||||
#include "xilinx.h"
|
#include "xilinx.h"
|
||||||
#include "blockdev.h"
|
#include "blockdev.h"
|
||||||
#include "pc.h"
|
#include "serial.h"
|
||||||
#include "exec-memory.h"
|
#include "exec-memory.h"
|
||||||
#include "ssi.h"
|
#include "ssi.h"
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include "e500.h"
|
#include "e500.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "hw/pc.h"
|
#include "hw/serial.h"
|
||||||
#include "hw/pci.h"
|
#include "hw/pci.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "ppc.h"
|
#include "ppc.h"
|
||||||
#include "ppc405.h"
|
#include "ppc405.h"
|
||||||
#include "pc.h"
|
#include "serial.h"
|
||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
#include "qemu-log.h"
|
#include "qemu-log.h"
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "exec-memory.h"
|
#include "exec-memory.h"
|
||||||
#include "pc.h"
|
#include "serial.h"
|
||||||
#include "ppc.h"
|
#include "ppc.h"
|
||||||
#include "ppc405.h"
|
#include "ppc405.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "nvram.h"
|
#include "nvram.h"
|
||||||
#include "pc.h"
|
#include "pc.h"
|
||||||
|
#include "serial.h"
|
||||||
#include "fdc.h"
|
#include "fdc.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "sysbus.h"
|
#include "sysbus.h"
|
||||||
#include "pxa.h"
|
#include "pxa.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
#include "pc.h"
|
#include "serial.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "ssi.h"
|
#include "ssi.h"
|
||||||
#include "qemu-char.h"
|
#include "qemu-char.h"
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* QEMU 16550A UART emulation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003-2004 Fabrice Bellard
|
||||||
|
* Copyright (c) 2008 Citrix Systems, Inc.
|
||||||
|
*
|
||||||
|
* 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 "serial.h"
|
||||||
|
#include "isa.h"
|
||||||
|
|
||||||
|
typedef struct ISASerialState {
|
||||||
|
ISADevice dev;
|
||||||
|
uint32_t index;
|
||||||
|
uint32_t iobase;
|
||||||
|
uint32_t isairq;
|
||||||
|
SerialState state;
|
||||||
|
} ISASerialState;
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
static int serial_isa_initfn(ISADevice *dev)
|
||||||
|
{
|
||||||
|
static int index;
|
||||||
|
ISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev);
|
||||||
|
SerialState *s = &isa->state;
|
||||||
|
|
||||||
|
if (isa->index == -1) {
|
||||||
|
isa->index = index;
|
||||||
|
}
|
||||||
|
if (isa->index >= MAX_SERIAL_PORTS) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (isa->iobase == -1) {
|
||||||
|
isa->iobase = isa_serial_io[isa->index];
|
||||||
|
}
|
||||||
|
if (isa->isairq == -1) {
|
||||||
|
isa->isairq = isa_serial_irq[isa->index];
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
|
||||||
|
s->baudbase = 115200;
|
||||||
|
isa_init_irq(dev, &s->irq, isa->isairq);
|
||||||
|
serial_init_core(s);
|
||||||
|
qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3);
|
||||||
|
|
||||||
|
memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
|
||||||
|
isa_register_ioport(dev, &s->io, isa->iobase);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_isa_serial = {
|
||||||
|
.name = "serial",
|
||||||
|
.version_id = 3,
|
||||||
|
.minimum_version_id = 2,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_STRUCT(state, ISASerialState, 0, vmstate_serial, SerialState),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static Property serial_isa_properties[] = {
|
||||||
|
DEFINE_PROP_UINT32("index", ISASerialState, index, -1),
|
||||||
|
DEFINE_PROP_HEX32("iobase", ISASerialState, iobase, -1),
|
||||||
|
DEFINE_PROP_UINT32("irq", ISASerialState, isairq, -1),
|
||||||
|
DEFINE_PROP_CHR("chardev", ISASerialState, state.chr),
|
||||||
|
DEFINE_PROP_UINT32("wakeup", ISASerialState, state.wakeup, 0),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void serial_isa_class_initfn(ObjectClass *klass, void *data)
|
||||||
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
|
||||||
|
ic->init = serial_isa_initfn;
|
||||||
|
dc->vmsd = &vmstate_isa_serial;
|
||||||
|
dc->props = serial_isa_properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
static TypeInfo serial_isa_info = {
|
||||||
|
.name = "isa-serial",
|
||||||
|
.parent = TYPE_ISA_DEVICE,
|
||||||
|
.instance_size = sizeof(ISASerialState),
|
||||||
|
.class_init = serial_isa_class_initfn,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void serial_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&serial_isa_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(serial_register_types)
|
||||||
|
|
||||||
|
bool serial_isa_init(ISABus *bus, int index, CharDriverState *chr)
|
||||||
|
{
|
||||||
|
ISADevice *dev;
|
||||||
|
|
||||||
|
dev = isa_try_create(bus, "isa-serial");
|
||||||
|
if (!dev) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
qdev_prop_set_uint32(&dev->qdev, "index", index);
|
||||||
|
qdev_prop_set_chr(&dev->qdev, "chardev", chr);
|
||||||
|
if (qdev_init(&dev->qdev) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
143
hw/serial.c
143
hw/serial.c
|
@ -22,12 +22,10 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include "hw.h"
|
|
||||||
|
#include "serial.h"
|
||||||
#include "qemu-char.h"
|
#include "qemu-char.h"
|
||||||
#include "isa.h"
|
|
||||||
#include "pc.h"
|
|
||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
#include "sysemu.h"
|
|
||||||
|
|
||||||
//#define DEBUG_SERIAL
|
//#define DEBUG_SERIAL
|
||||||
|
|
||||||
|
@ -93,8 +91,6 @@
|
||||||
#define UART_FCR_RFR 0x02 /* RCVR Fifo Reset */
|
#define UART_FCR_RFR 0x02 /* RCVR Fifo Reset */
|
||||||
#define UART_FCR_FE 0x01 /* FIFO Enable */
|
#define UART_FCR_FE 0x01 /* FIFO Enable */
|
||||||
|
|
||||||
#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */
|
|
||||||
|
|
||||||
#define XMIT_FIFO 0
|
#define XMIT_FIFO 0
|
||||||
#define RECV_FIFO 1
|
#define RECV_FIFO 1
|
||||||
#define MAX_XMIT_RETRY 4
|
#define MAX_XMIT_RETRY 4
|
||||||
|
@ -107,64 +103,6 @@ do { fprintf(stderr, "serial: " fmt , ## __VA_ARGS__); } while (0)
|
||||||
do {} while (0)
|
do {} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct SerialFIFO {
|
|
||||||
uint8_t data[UART_FIFO_LENGTH];
|
|
||||||
uint8_t count;
|
|
||||||
uint8_t itl; /* Interrupt Trigger Level */
|
|
||||||
uint8_t tail;
|
|
||||||
uint8_t head;
|
|
||||||
} SerialFIFO;
|
|
||||||
|
|
||||||
struct SerialState {
|
|
||||||
uint16_t divider;
|
|
||||||
uint8_t rbr; /* receive register */
|
|
||||||
uint8_t thr; /* transmit holding register */
|
|
||||||
uint8_t tsr; /* transmit shift register */
|
|
||||||
uint8_t ier;
|
|
||||||
uint8_t iir; /* read only */
|
|
||||||
uint8_t lcr;
|
|
||||||
uint8_t mcr;
|
|
||||||
uint8_t lsr; /* read only */
|
|
||||||
uint8_t msr; /* read only */
|
|
||||||
uint8_t scr;
|
|
||||||
uint8_t fcr;
|
|
||||||
uint8_t fcr_vmstate; /* we can't write directly this value
|
|
||||||
it has side effects */
|
|
||||||
/* NOTE: this hidden state is necessary for tx irq generation as
|
|
||||||
it can be reset while reading iir */
|
|
||||||
int thr_ipending;
|
|
||||||
qemu_irq irq;
|
|
||||||
CharDriverState *chr;
|
|
||||||
int last_break_enable;
|
|
||||||
int it_shift;
|
|
||||||
int baudbase;
|
|
||||||
int tsr_retry;
|
|
||||||
uint32_t wakeup;
|
|
||||||
|
|
||||||
uint64_t last_xmit_ts; /* Time when the last byte was successfully sent out of the tsr */
|
|
||||||
SerialFIFO recv_fifo;
|
|
||||||
SerialFIFO xmit_fifo;
|
|
||||||
|
|
||||||
struct QEMUTimer *fifo_timeout_timer;
|
|
||||||
int timeout_ipending; /* timeout interrupt pending state */
|
|
||||||
struct QEMUTimer *transmit_timer;
|
|
||||||
|
|
||||||
|
|
||||||
uint64_t char_transmit_time; /* time to transmit a char in ticks*/
|
|
||||||
int poll_msl;
|
|
||||||
|
|
||||||
struct QEMUTimer *modem_status_poll;
|
|
||||||
MemoryRegion io;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct ISASerialState {
|
|
||||||
ISADevice dev;
|
|
||||||
uint32_t index;
|
|
||||||
uint32_t iobase;
|
|
||||||
uint32_t isairq;
|
|
||||||
SerialState state;
|
|
||||||
} ISASerialState;
|
|
||||||
|
|
||||||
static void serial_receive1(void *opaque, const uint8_t *buf, int size);
|
static void serial_receive1(void *opaque, const uint8_t *buf, int size);
|
||||||
|
|
||||||
static void fifo_clear(SerialState *s, int fifo)
|
static void fifo_clear(SerialState *s, int fifo)
|
||||||
|
@ -687,7 +625,7 @@ static int serial_post_load(void *opaque, int version_id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_serial = {
|
const VMStateDescription vmstate_serial = {
|
||||||
.name = "serial",
|
.name = "serial",
|
||||||
.version_id = 3,
|
.version_id = 3,
|
||||||
.minimum_version_id = 2,
|
.minimum_version_id = 2,
|
||||||
|
@ -736,7 +674,7 @@ static void serial_reset(void *opaque)
|
||||||
qemu_irq_lower(s->irq);
|
qemu_irq_lower(s->irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serial_init_core(SerialState *s)
|
void serial_init_core(SerialState *s)
|
||||||
{
|
{
|
||||||
if (!s->chr) {
|
if (!s->chr) {
|
||||||
fprintf(stderr, "Can't create serial device, empty char device\n");
|
fprintf(stderr, "Can't create serial device, empty char device\n");
|
||||||
|
@ -761,54 +699,15 @@ void serial_set_frequency(SerialState *s, uint32_t frequency)
|
||||||
serial_update_parameters(s);
|
serial_update_parameters(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 };
|
|
||||||
|
|
||||||
static const MemoryRegionPortio serial_portio[] = {
|
static const MemoryRegionPortio serial_portio[] = {
|
||||||
{ 0, 8, 1, .read = serial_ioport_read, .write = serial_ioport_write },
|
{ 0, 8, 1, .read = serial_ioport_read, .write = serial_ioport_write },
|
||||||
PORTIO_END_OF_LIST()
|
PORTIO_END_OF_LIST()
|
||||||
};
|
};
|
||||||
|
|
||||||
static const MemoryRegionOps serial_io_ops = {
|
const MemoryRegionOps serial_io_ops = {
|
||||||
.old_portio = serial_portio
|
.old_portio = serial_portio
|
||||||
};
|
};
|
||||||
|
|
||||||
static int serial_isa_initfn(ISADevice *dev)
|
|
||||||
{
|
|
||||||
static int index;
|
|
||||||
ISASerialState *isa = DO_UPCAST(ISASerialState, dev, dev);
|
|
||||||
SerialState *s = &isa->state;
|
|
||||||
|
|
||||||
if (isa->index == -1)
|
|
||||||
isa->index = index;
|
|
||||||
if (isa->index >= MAX_SERIAL_PORTS)
|
|
||||||
return -1;
|
|
||||||
if (isa->iobase == -1)
|
|
||||||
isa->iobase = isa_serial_io[isa->index];
|
|
||||||
if (isa->isairq == -1)
|
|
||||||
isa->isairq = isa_serial_irq[isa->index];
|
|
||||||
index++;
|
|
||||||
|
|
||||||
s->baudbase = 115200;
|
|
||||||
isa_init_irq(dev, &s->irq, isa->isairq);
|
|
||||||
serial_init_core(s);
|
|
||||||
qdev_set_legacy_instance_id(&dev->qdev, isa->iobase, 3);
|
|
||||||
|
|
||||||
memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8);
|
|
||||||
isa_register_ioport(dev, &s->io, isa->iobase);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const VMStateDescription vmstate_isa_serial = {
|
|
||||||
.name = "serial",
|
|
||||||
.version_id = 3,
|
|
||||||
.minimum_version_id = 2,
|
|
||||||
.fields = (VMStateField []) {
|
|
||||||
VMSTATE_STRUCT(state, ISASerialState, 0, vmstate_serial, SerialState),
|
|
||||||
VMSTATE_END_OF_LIST()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
|
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
|
||||||
CharDriverState *chr)
|
CharDriverState *chr)
|
||||||
{
|
{
|
||||||
|
@ -886,35 +785,3 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
|
||||||
serial_update_msl(s);
|
serial_update_msl(s);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property serial_isa_properties[] = {
|
|
||||||
DEFINE_PROP_UINT32("index", ISASerialState, index, -1),
|
|
||||||
DEFINE_PROP_HEX32("iobase", ISASerialState, iobase, -1),
|
|
||||||
DEFINE_PROP_UINT32("irq", ISASerialState, isairq, -1),
|
|
||||||
DEFINE_PROP_CHR("chardev", ISASerialState, state.chr),
|
|
||||||
DEFINE_PROP_UINT32("wakeup", ISASerialState, state.wakeup, 0),
|
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
|
||||||
};
|
|
||||||
|
|
||||||
static void serial_isa_class_initfn(ObjectClass *klass, void *data)
|
|
||||||
{
|
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
|
||||||
ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
|
|
||||||
ic->init = serial_isa_initfn;
|
|
||||||
dc->vmsd = &vmstate_isa_serial;
|
|
||||||
dc->props = serial_isa_properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TypeInfo serial_isa_info = {
|
|
||||||
.name = "isa-serial",
|
|
||||||
.parent = TYPE_ISA_DEVICE,
|
|
||||||
.instance_size = sizeof(ISASerialState),
|
|
||||||
.class_init = serial_isa_class_initfn,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void serial_register_types(void)
|
|
||||||
{
|
|
||||||
type_register_static(&serial_isa_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
type_init(serial_register_types)
|
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* QEMU 16550A UART emulation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2003-2004 Fabrice Bellard
|
||||||
|
* Copyright (c) 2008 Citrix Systems, Inc.
|
||||||
|
*
|
||||||
|
* 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.h"
|
||||||
|
#include "sysemu.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */
|
||||||
|
|
||||||
|
typedef struct SerialFIFO {
|
||||||
|
uint8_t data[UART_FIFO_LENGTH];
|
||||||
|
uint8_t count;
|
||||||
|
uint8_t itl; /* Interrupt Trigger Level */
|
||||||
|
uint8_t tail;
|
||||||
|
uint8_t head;
|
||||||
|
} SerialFIFO;
|
||||||
|
|
||||||
|
struct SerialState {
|
||||||
|
uint16_t divider;
|
||||||
|
uint8_t rbr; /* receive register */
|
||||||
|
uint8_t thr; /* transmit holding register */
|
||||||
|
uint8_t tsr; /* transmit shift register */
|
||||||
|
uint8_t ier;
|
||||||
|
uint8_t iir; /* read only */
|
||||||
|
uint8_t lcr;
|
||||||
|
uint8_t mcr;
|
||||||
|
uint8_t lsr; /* read only */
|
||||||
|
uint8_t msr; /* read only */
|
||||||
|
uint8_t scr;
|
||||||
|
uint8_t fcr;
|
||||||
|
uint8_t fcr_vmstate; /* we can't write directly this value
|
||||||
|
it has side effects */
|
||||||
|
/* NOTE: this hidden state is necessary for tx irq generation as
|
||||||
|
it can be reset while reading iir */
|
||||||
|
int thr_ipending;
|
||||||
|
qemu_irq irq;
|
||||||
|
CharDriverState *chr;
|
||||||
|
int last_break_enable;
|
||||||
|
int it_shift;
|
||||||
|
int baudbase;
|
||||||
|
int tsr_retry;
|
||||||
|
uint32_t wakeup;
|
||||||
|
|
||||||
|
/* Time when the last byte was successfully sent out of the tsr */
|
||||||
|
uint64_t last_xmit_ts;
|
||||||
|
SerialFIFO recv_fifo;
|
||||||
|
SerialFIFO xmit_fifo;
|
||||||
|
|
||||||
|
struct QEMUTimer *fifo_timeout_timer;
|
||||||
|
int timeout_ipending; /* timeout interrupt pending state */
|
||||||
|
struct QEMUTimer *transmit_timer;
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t char_transmit_time; /* time to transmit a char in ticks */
|
||||||
|
int poll_msl;
|
||||||
|
|
||||||
|
struct QEMUTimer *modem_status_poll;
|
||||||
|
MemoryRegion io;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const VMStateDescription vmstate_serial;
|
||||||
|
extern const MemoryRegionOps serial_io_ops;
|
||||||
|
|
||||||
|
void serial_init_core(SerialState *s);
|
||||||
|
void serial_set_frequency(SerialState *s, uint32_t frequency);
|
||||||
|
|
||||||
|
/* legacy pre qom */
|
||||||
|
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
|
||||||
|
CharDriverState *chr);
|
||||||
|
SerialState *serial_mm_init(MemoryRegion *address_space,
|
||||||
|
target_phys_addr_t base, int it_shift,
|
||||||
|
qemu_irq irq, int baudbase,
|
||||||
|
CharDriverState *chr, enum device_endian end);
|
||||||
|
|
||||||
|
/* serial-isa.c */
|
||||||
|
bool serial_isa_init(ISABus *bus, int index, CharDriverState *chr);
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "pc.h"
|
#include "serial.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "devices.h"
|
#include "devices.h"
|
||||||
#include "sysbus.h"
|
#include "sysbus.h"
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
#include "apb_pci.h"
|
#include "apb_pci.h"
|
||||||
#include "pc.h"
|
#include "pc.h"
|
||||||
|
#include "serial.h"
|
||||||
#include "nvram.h"
|
#include "nvram.h"
|
||||||
#include "fdc.h"
|
#include "fdc.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include "sysbus.h"
|
#include "sysbus.h"
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "pc.h"
|
#include "serial.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "sysemu.h"
|
#include "sysemu.h"
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "exec-memory.h"
|
#include "exec-memory.h"
|
||||||
#include "pc.h"
|
#include "serial.h"
|
||||||
|
#include "net.h"
|
||||||
#include "sysbus.h"
|
#include "sysbus.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "blockdev.h"
|
#include "blockdev.h"
|
||||||
|
|
Loading…
Reference in New Issue