mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 11:23:43 +08:00
char: make some qemu_chr_fe skip if no driver
In most cases, front ends do not care about the side effect of CharBackend, so we can simply skip the checks and call the qemu_chr_fe functions even without associated CharDriver. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20161022095318.17775-20-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
c39860e6dc
commit
fa394ed625
@ -1903,7 +1903,7 @@ static void pxa2xx_fir_write(void *opaque, hwaddr addr,
|
||||
} else {
|
||||
ch = ~value;
|
||||
}
|
||||
if (s->chr.chr && s->enable && (s->control[0] & (1 << 3))) { /* TXE */
|
||||
if (s->enable && (s->control[0] & (1 << 3))) { /* TXE */
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
@ -1975,10 +1975,8 @@ static void pxa2xx_fir_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PXA2xxFIrState *s = PXA2XX_FIR(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, pxa2xx_fir_is_empty,
|
||||
pxa2xx_fir_rx, pxa2xx_fir_event, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr, pxa2xx_fir_is_empty,
|
||||
pxa2xx_fir_rx, pxa2xx_fir_event, s, NULL);
|
||||
}
|
||||
|
||||
static bool pxa2xx_fir_vmstate_validate(void *opaque, int version_id)
|
||||
|
@ -1020,9 +1020,7 @@ static void strongarm_uart_update_parameters(StrongARMUARTState *s)
|
||||
ssp.data_bits = data_bits;
|
||||
ssp.stop_bits = stop_bits;
|
||||
s->char_transmit_time = (NANOSECONDS_PER_SECOND / speed) * frame_size;
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
|
||||
}
|
||||
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
|
||||
|
||||
DPRINTF(stderr, "%s speed=%d parity=%c data=%d stop=%d\n", s->chr->label,
|
||||
speed, parity, data_bits, stop_bits);
|
||||
@ -1239,13 +1237,11 @@ static void strongarm_uart_init(Object *obj)
|
||||
s->rx_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_rx_to, s);
|
||||
s->tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_tx, s);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr,
|
||||
strongarm_uart_can_receive,
|
||||
strongarm_uart_receive,
|
||||
strongarm_uart_event,
|
||||
s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr,
|
||||
strongarm_uart_can_receive,
|
||||
strongarm_uart_receive,
|
||||
strongarm_uart_event,
|
||||
s, NULL);
|
||||
}
|
||||
|
||||
static void strongarm_uart_reset(DeviceState *dev)
|
||||
|
@ -79,9 +79,7 @@ static uint64_t bcm2835_aux_read(void *opaque, hwaddr offset, unsigned size)
|
||||
s->read_pos = 0;
|
||||
}
|
||||
}
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
bcm2835_aux_update(s);
|
||||
return c;
|
||||
|
||||
@ -168,11 +166,9 @@ static void bcm2835_aux_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
case AUX_MU_IO_REG:
|
||||
/* "DLAB bit set means access baudrate register" is NYI */
|
||||
ch = value;
|
||||
if (s->chr.chr) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
break;
|
||||
|
||||
case AUX_MU_IER_REG:
|
||||
@ -282,10 +278,8 @@ static void bcm2835_aux_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
BCM2835AuxState *s = BCM2835_AUX(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, bcm2835_aux_can_receive,
|
||||
bcm2835_aux_receive, NULL, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr, bcm2835_aux_can_receive,
|
||||
bcm2835_aux_receive, NULL, s, NULL);
|
||||
}
|
||||
|
||||
static Property bcm2835_aux_props[] = {
|
||||
|
@ -142,9 +142,7 @@ static void uart_rx_reset(CadenceUARTState *s)
|
||||
{
|
||||
s->rx_wpos = 0;
|
||||
s->rx_count = 0;
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
|
||||
static void uart_tx_reset(CadenceUARTState *s)
|
||||
@ -156,10 +154,8 @@ static void uart_send_breaks(CadenceUARTState *s)
|
||||
{
|
||||
int break_enabled = 1;
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
|
||||
&break_enabled);
|
||||
}
|
||||
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
|
||||
&break_enabled);
|
||||
}
|
||||
|
||||
static void uart_parameters_setup(CadenceUARTState *s)
|
||||
@ -210,9 +206,7 @@ static void uart_parameters_setup(CadenceUARTState *s)
|
||||
|
||||
packet_size += ssp.data_bits + ssp.stop_bits;
|
||||
s->char_tx_time = (NANOSECONDS_PER_SECOND / ssp.speed) * packet_size;
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
|
||||
}
|
||||
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
|
||||
}
|
||||
|
||||
static int uart_can_receive(void *opaque)
|
||||
@ -368,9 +362,7 @@ static void uart_read_rx_fifo(CadenceUARTState *s, uint32_t *c)
|
||||
*c = s->rx_fifo[rx_rpos];
|
||||
s->rx_count--;
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
} else {
|
||||
*c = 0;
|
||||
}
|
||||
@ -474,10 +466,8 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
|
||||
s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||
fifo_trigger_update, s);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
|
||||
uart_event, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
|
||||
uart_event, s, NULL);
|
||||
}
|
||||
|
||||
static void cadence_uart_init(Object *obj)
|
||||
|
@ -76,11 +76,9 @@ static void digic_uart_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
|
||||
switch (addr) {
|
||||
case R_TX:
|
||||
if (s->chr.chr) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
break;
|
||||
|
||||
case R_ST:
|
||||
@ -147,10 +145,8 @@ static void digic_uart_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
DigicUartState *s = DIGIC_UART(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
|
||||
uart_event, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
|
||||
uart_event, s, NULL);
|
||||
}
|
||||
|
||||
static void digic_uart_init(Object *obj)
|
||||
|
@ -599,9 +599,7 @@ static uint64_t escc_mem_read(void *opaque, hwaddr addr,
|
||||
else
|
||||
ret = s->rx;
|
||||
trace_escc_mem_readb_data(CHN_C(s), ret);
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
return ret;
|
||||
default:
|
||||
break;
|
||||
|
@ -231,11 +231,9 @@ static void etraxfs_ser_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ETRAXSerial *s = ETRAX_SERIAL(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr,
|
||||
serial_can_receive, serial_receive,
|
||||
serial_event, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr,
|
||||
serial_can_receive, serial_receive,
|
||||
serial_event, s, NULL);
|
||||
}
|
||||
|
||||
static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
|
||||
|
@ -121,9 +121,7 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
|
||||
s->usr2 &= ~USR2_RDR;
|
||||
s->uts1 |= UTS1_RXEMPTY;
|
||||
imx_update(s);
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
return c;
|
||||
|
||||
@ -182,11 +180,9 @@ static void imx_serial_write(void *opaque, hwaddr offset,
|
||||
case 0x10: /* UTXD */
|
||||
ch = value;
|
||||
if (s->ucr2 & UCR2_TXEN) {
|
||||
if (s->chr.chr) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
s->usr1 &= ~USR1_TRDY;
|
||||
imx_update(s);
|
||||
s->usr1 |= USR1_TRDY;
|
||||
@ -215,9 +211,7 @@ static void imx_serial_write(void *opaque, hwaddr offset,
|
||||
}
|
||||
if (value & UCR2_RXEN) {
|
||||
if (!(s->ucr2 & UCR2_RXEN)) {
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
}
|
||||
s->ucr2 = value & 0xffff;
|
||||
@ -319,12 +313,10 @@ static void imx_serial_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
IMXSerialState *s = IMX_SERIAL(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, imx_can_receive, imx_receive,
|
||||
imx_event, s, NULL);
|
||||
} else {
|
||||
DPRINTF("No char dev for uart\n");
|
||||
}
|
||||
DPRINTF("char dev for uart: %p\n", qemu_chr_fe_get_driver(&s->chr));
|
||||
|
||||
qemu_chr_fe_set_handlers(&s->chr, imx_can_receive, imx_receive,
|
||||
imx_event, s, NULL);
|
||||
}
|
||||
|
||||
static void imx_serial_init(Object *obj)
|
||||
|
@ -288,9 +288,7 @@ static uint16_t io_read(IPackDevice *ip, uint8_t addr)
|
||||
if (ch->rx_pending == 0) {
|
||||
ch->sr &= ~SR_RXRDY;
|
||||
blk->isr &= ~ISR_RXRDY(channel);
|
||||
if (ch->dev.chr) {
|
||||
qemu_chr_fe_accept_input(&ch->dev);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&ch->dev);
|
||||
} else {
|
||||
ch->rhr_idx = (ch->rhr_idx + 1) % RX_FIFO_SIZE;
|
||||
}
|
||||
@ -357,13 +355,11 @@ static void io_write(IPackDevice *ip, uint8_t addr, uint16_t val)
|
||||
case REG_THRa:
|
||||
case REG_THRb:
|
||||
if (ch->sr & SR_TXRDY) {
|
||||
uint8_t thr = reg;
|
||||
DPRINTF("Write THR%c (0x%x)\n", channel + 'a', reg);
|
||||
if (ch->dev.chr) {
|
||||
uint8_t thr = reg;
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&ch->dev, &thr, 1);
|
||||
}
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&ch->dev, &thr, 1);
|
||||
} else {
|
||||
DPRINTF("Write THR%c (0x%x), Tx disabled\n", channel + 'a', reg);
|
||||
}
|
||||
|
@ -75,11 +75,9 @@ void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx)
|
||||
trace_lm32_juart_set_jtx(s->jtx);
|
||||
|
||||
s->jtx = jtx;
|
||||
if (s->chr.chr) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
|
||||
void lm32_juart_set_jrx(DeviceState *d, uint32_t jtx)
|
||||
@ -120,10 +118,8 @@ static void lm32_juart_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
LM32JuartState *s = LM32_JUART(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, juart_can_rx, juart_rx,
|
||||
juart_event, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr, juart_can_rx, juart_rx,
|
||||
juart_event, s, NULL);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_lm32_juart = {
|
||||
|
@ -177,11 +177,9 @@ static void uart_write(void *opaque, hwaddr addr,
|
||||
addr >>= 2;
|
||||
switch (addr) {
|
||||
case R_RXTX:
|
||||
if (s->chr.chr) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
break;
|
||||
case R_IER:
|
||||
case R_LCR:
|
||||
@ -267,10 +265,8 @@ static void lm32_uart_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
LM32UartState *s = LM32_UART(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
|
||||
uart_event, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
|
||||
uart_event, s, NULL);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_lm32_uart = {
|
||||
|
@ -114,11 +114,9 @@ uint64_t mcf_uart_read(void *opaque, hwaddr addr,
|
||||
static void mcf_uart_do_tx(mcf_uart_state *s)
|
||||
{
|
||||
if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) {
|
||||
if (s->chr.chr) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, (unsigned char *)&s->tb, 1);
|
||||
}
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, (unsigned char *)&s->tb, 1);
|
||||
s->sr |= MCF_UART_TxEMP;
|
||||
}
|
||||
if (s->tx_enabled) {
|
||||
|
@ -124,9 +124,7 @@ static void uart_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
addr >>= 2;
|
||||
switch (addr) {
|
||||
case R_RXTX:
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
s->regs[R_STAT] |= STAT_TX_EVT;
|
||||
break;
|
||||
case R_DIV:
|
||||
@ -200,10 +198,8 @@ static void milkymist_uart_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
MilkymistUartState *s = MILKYMIST_UART(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
|
||||
uart_event, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
|
||||
uart_event, s, NULL);
|
||||
}
|
||||
|
||||
static void milkymist_uart_init(Object *obj)
|
||||
|
@ -87,9 +87,7 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
|
||||
trace_pl011_read_fifo(s->read_count);
|
||||
s->rsr = c >> 8;
|
||||
pl011_update(s);
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
r = c;
|
||||
break;
|
||||
case 1: /* UARTRSR */
|
||||
@ -168,11 +166,9 @@ static void pl011_write(void *opaque, hwaddr offset,
|
||||
case 0: /* UARTDR */
|
||||
/* ??? Check if transmitter is enabled. */
|
||||
ch = value;
|
||||
if (s->chr.chr) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
s->int_level |= PL011_INT_TX;
|
||||
pl011_update(s);
|
||||
break;
|
||||
@ -332,10 +328,8 @@ static void pl011_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
PL011State *s = PL011(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
|
||||
pl011_event, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
|
||||
pl011_event, s, NULL);
|
||||
}
|
||||
|
||||
static void pl011_class_init(ObjectClass *oc, void *data)
|
||||
|
@ -312,10 +312,8 @@ static int console_init(SCLPEvent *event)
|
||||
}
|
||||
console_available = true;
|
||||
|
||||
if (scon->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
|
||||
chr_read, NULL, scon, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
|
||||
chr_read, NULL, scon, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -227,10 +227,8 @@ static int console_init(SCLPEvent *event)
|
||||
return -1;
|
||||
}
|
||||
console_available = true;
|
||||
if (scon->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
|
||||
chr_read, NULL, scon, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
|
||||
chr_read, NULL, scon, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -97,17 +97,13 @@ static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr,
|
||||
case USART_SR:
|
||||
retvalue = s->usart_sr;
|
||||
s->usart_sr &= ~USART_SR_TC;
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
return retvalue;
|
||||
case USART_DR:
|
||||
DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr);
|
||||
s->usart_sr |= USART_SR_TXE;
|
||||
s->usart_sr &= ~USART_SR_RXNE;
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&s->chr);
|
||||
qemu_set_irq(s->irq, 0);
|
||||
return s->usart_dr & 0x3FF;
|
||||
case USART_BRR:
|
||||
@ -152,11 +148,9 @@ static void stm32f2xx_usart_write(void *opaque, hwaddr addr,
|
||||
case USART_DR:
|
||||
if (value < 0xF000) {
|
||||
ch = value;
|
||||
if (s->chr.chr) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
s->usart_sr |= USART_SR_TC;
|
||||
s->usart_sr &= ~USART_SR_TXE;
|
||||
}
|
||||
@ -212,10 +206,8 @@ static void stm32f2xx_usart_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
STM32F2XXUsartState *s = STM32F2XX_USART(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, stm32f2xx_usart_can_receive,
|
||||
stm32f2xx_usart_receive, NULL, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr, stm32f2xx_usart_can_receive,
|
||||
stm32f2xx_usart_receive, NULL, s, NULL);
|
||||
}
|
||||
|
||||
static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
|
||||
|
@ -108,7 +108,7 @@ static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
|
||||
DeviceState *dev = DEVICE(port);
|
||||
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
|
||||
|
||||
if (vcon->chr.chr && !k->is_console) {
|
||||
if (!k->is_console) {
|
||||
qemu_chr_fe_set_open(&vcon->chr, guest_connected);
|
||||
}
|
||||
|
||||
@ -122,9 +122,7 @@ static void guest_writable(VirtIOSerialPort *port)
|
||||
{
|
||||
VirtConsole *vcon = VIRTIO_CONSOLE(port);
|
||||
|
||||
if (vcon->chr.chr) {
|
||||
qemu_chr_fe_accept_input(&vcon->chr);
|
||||
}
|
||||
qemu_chr_fe_accept_input(&vcon->chr);
|
||||
}
|
||||
|
||||
/* Readiness of the guest to accept data on a port */
|
||||
|
@ -244,10 +244,8 @@ static int con_initialise(struct XenDevice *xendev)
|
||||
return -1;
|
||||
|
||||
xen_be_bind_evtchn(&con->xendev);
|
||||
if (con->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&con->chr, xencons_can_receive,
|
||||
xencons_receive, NULL, con, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&con->chr, xencons_can_receive,
|
||||
xencons_receive, NULL, con, NULL);
|
||||
|
||||
xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
|
||||
con->ring_ref,
|
||||
|
@ -143,11 +143,9 @@ uart_write(void *opaque, hwaddr addr,
|
||||
break;
|
||||
|
||||
case R_TX:
|
||||
if (s->chr.chr) {
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
}
|
||||
/* XXX this blocks entire thread. Rewrite to use
|
||||
* qemu_chr_fe_write and background I/O callbacks */
|
||||
qemu_chr_fe_write_all(&s->chr, &ch, 1);
|
||||
s->regs[addr] = value;
|
||||
|
||||
/* hax. */
|
||||
@ -213,10 +211,8 @@ static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
XilinxUARTLite *s = XILINX_UARTLITE(dev);
|
||||
|
||||
if (s->chr.chr) {
|
||||
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
|
||||
uart_event, s, NULL);
|
||||
}
|
||||
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
|
||||
uart_event, s, NULL);
|
||||
}
|
||||
|
||||
static void xilinx_uartlite_init(Object *obj)
|
||||
|
@ -168,6 +168,7 @@ CharDriverState *qemu_chr_new(const char *label, const char *filename);
|
||||
* @qemu_chr_fe_disconnect:
|
||||
*
|
||||
* Close a fd accpeted by character backend.
|
||||
* Without associated CharDriver, do nothing.
|
||||
*/
|
||||
void qemu_chr_fe_disconnect(CharBackend *be);
|
||||
|
||||
@ -181,7 +182,8 @@ void qemu_chr_cleanup(void);
|
||||
/**
|
||||
* @qemu_chr_fe_wait_connected:
|
||||
*
|
||||
* Wait for characted backend to be connected.
|
||||
* Wait for characted backend to be connected, return < 0 on error or
|
||||
* if no assicated CharDriver.
|
||||
*/
|
||||
int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp);
|
||||
|
||||
@ -220,6 +222,7 @@ void qemu_chr_free(CharDriverState *chr);
|
||||
* Ask the backend to override its normal echo setting. This only really
|
||||
* applies to the stdio backend and is used by the QMP server such that you
|
||||
* can see what you type if you try to type QMP commands.
|
||||
* Without associated CharDriver, do nothing.
|
||||
*
|
||||
* @echo true to enable echo, false to disable echo
|
||||
*/
|
||||
@ -230,13 +233,15 @@ void qemu_chr_fe_set_echo(CharBackend *be, bool echo);
|
||||
*
|
||||
* Set character frontend open status. This is an indication that the
|
||||
* front end is ready (or not) to begin doing I/O.
|
||||
* Without associated CharDriver, do nothing.
|
||||
*/
|
||||
void qemu_chr_fe_set_open(CharBackend *be, int fe_open);
|
||||
|
||||
/**
|
||||
* @qemu_chr_fe_event:
|
||||
*
|
||||
* Send an event from the front end to the back end.
|
||||
* Send an event from the front end to the back end. It does nothing
|
||||
* without associated CharDriver.
|
||||
*
|
||||
* @event the event to send
|
||||
*/
|
||||
@ -245,8 +250,9 @@ void qemu_chr_fe_event(CharBackend *be, int event);
|
||||
/**
|
||||
* @qemu_chr_fe_printf:
|
||||
*
|
||||
* Write to a character backend using a printf style interface.
|
||||
* This function is thread-safe.
|
||||
* Write to a character backend using a printf style interface. This
|
||||
* function is thread-safe. It does nothing without associated
|
||||
* CharDriver.
|
||||
*
|
||||
* @fmt see #printf
|
||||
*/
|
||||
@ -259,7 +265,7 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
|
||||
* If the backend is connected, create and add a #GSource that fires
|
||||
* when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP)
|
||||
* is active; return the #GSource's tag. If it is disconnected,
|
||||
* return 0.
|
||||
* or without associated CharDriver, return 0.
|
||||
*
|
||||
* @cond the condition to poll for
|
||||
* @func the function to call when the condition happens
|
||||
@ -278,7 +284,7 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
|
||||
* @buf the data
|
||||
* @len the number of bytes to send
|
||||
*
|
||||
* Returns: the number of bytes consumed
|
||||
* Returns: the number of bytes consumed (0 if no assicated CharDriver)
|
||||
*/
|
||||
int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len);
|
||||
|
||||
@ -293,7 +299,7 @@ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len);
|
||||
* @buf the data
|
||||
* @len the number of bytes to send
|
||||
*
|
||||
* Returns: the number of bytes consumed
|
||||
* Returns: the number of bytes consumed (0 if no assicated CharDriver)
|
||||
*/
|
||||
int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len);
|
||||
|
||||
@ -305,7 +311,7 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len);
|
||||
* @buf the data buffer
|
||||
* @len the number of bytes to read
|
||||
*
|
||||
* Returns: the number of bytes read
|
||||
* Returns: the number of bytes read (0 if no assicated CharDriver)
|
||||
*/
|
||||
int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len);
|
||||
|
||||
@ -317,8 +323,9 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len);
|
||||
* @cmd see CHR_IOCTL_*
|
||||
* @arg the data associated with @cmd
|
||||
*
|
||||
* Returns: if @cmd is not supported by the backend, -ENOTSUP, otherwise the
|
||||
* return value depends on the semantics of @cmd
|
||||
* Returns: if @cmd is not supported by the backend or there is no
|
||||
* associated CharDriver, -ENOTSUP, otherwise the return
|
||||
* value depends on the semantics of @cmd
|
||||
*/
|
||||
int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg);
|
||||
|
||||
@ -357,7 +364,7 @@ int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num);
|
||||
* result in overwriting the fd array with the new value without being send.
|
||||
* Upon writing the message the fd array is freed.
|
||||
*
|
||||
* Returns: -1 if fd passing isn't supported.
|
||||
* Returns: -1 if fd passing isn't supported or no associated CharDriver.
|
||||
*/
|
||||
int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num);
|
||||
|
||||
@ -418,7 +425,8 @@ bool qemu_chr_fe_init(CharBackend *b, CharDriverState *s, Error **errp);
|
||||
/**
|
||||
* @qemu_chr_fe_get_driver:
|
||||
*
|
||||
* Returns the driver associated with a CharBackend or NULL.
|
||||
* Returns the driver associated with a CharBackend or NULL if no
|
||||
* associated CharDriver.
|
||||
*/
|
||||
CharDriverState *qemu_chr_fe_get_driver(CharBackend *be);
|
||||
|
||||
@ -426,6 +434,8 @@ CharDriverState *qemu_chr_fe_get_driver(CharBackend *be);
|
||||
* @qemu_chr_fe_deinit:
|
||||
*
|
||||
* Dissociate the CharBackend from the CharDriver.
|
||||
*
|
||||
* Safe to call without associated CharDriver.
|
||||
*/
|
||||
void qemu_chr_fe_deinit(CharBackend *b);
|
||||
|
||||
@ -441,6 +451,8 @@ void qemu_chr_fe_deinit(CharBackend *b);
|
||||
*
|
||||
* Set the front end char handlers. The front end takes the focus if
|
||||
* any of the handler is non-NULL.
|
||||
*
|
||||
* Without associated CharDriver, nothing is changed.
|
||||
*/
|
||||
void qemu_chr_fe_set_handlers(CharBackend *b,
|
||||
IOCanReadHandler *fd_can_read,
|
||||
@ -452,7 +464,9 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
|
||||
/**
|
||||
* @qemu_chr_fe_take_focus:
|
||||
*
|
||||
* Take the focus (if the front end is muxed)
|
||||
* Take the focus (if the front end is muxed).
|
||||
*
|
||||
* Without associated CharDriver, nothing is changed.
|
||||
*/
|
||||
void qemu_chr_fe_take_focus(CharBackend *b);
|
||||
|
||||
|
50
qemu-char.c
50
qemu-char.c
@ -273,6 +273,10 @@ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len)
|
||||
CharDriverState *s = be->chr;
|
||||
int ret;
|
||||
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->replay && replay_mode == REPLAY_MODE_PLAY) {
|
||||
int offset;
|
||||
replay_char_write_event_load(&ret, &offset);
|
||||
@ -325,6 +329,10 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len)
|
||||
{
|
||||
CharDriverState *s = be->chr;
|
||||
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return qemu_chr_write_all(s, buf, len);
|
||||
}
|
||||
|
||||
@ -334,10 +342,10 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len)
|
||||
int offset = 0, counter = 10;
|
||||
int res;
|
||||
|
||||
if (!s->chr_sync_read) {
|
||||
if (!s || !s->chr_sync_read) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (s->replay && replay_mode == REPLAY_MODE_PLAY) {
|
||||
return replay_char_read_all_load(buf);
|
||||
}
|
||||
@ -378,7 +386,8 @@ int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg)
|
||||
{
|
||||
CharDriverState *s = be->chr;
|
||||
int res;
|
||||
if (!s->chr_ioctl || s->replay) {
|
||||
|
||||
if (!s || !s->chr_ioctl || s->replay) {
|
||||
res = -ENOTSUP;
|
||||
} else {
|
||||
res = s->chr_ioctl(s, cmd, arg);
|
||||
@ -418,7 +427,7 @@ int qemu_chr_fe_get_msgfd(CharBackend *be)
|
||||
CharDriverState *s = be->chr;
|
||||
int fd;
|
||||
int res = (qemu_chr_fe_get_msgfds(be, &fd, 1) == 1) ? fd : -1;
|
||||
if (s->replay) {
|
||||
if (s && s->replay) {
|
||||
fprintf(stderr,
|
||||
"Replay: get msgfd is not supported for serial devices yet\n");
|
||||
exit(1);
|
||||
@ -430,6 +439,10 @@ int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int len)
|
||||
{
|
||||
CharDriverState *s = be->chr;
|
||||
|
||||
if (!s) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s->get_msgfds ? s->get_msgfds(s, fds, len) : -1;
|
||||
}
|
||||
|
||||
@ -437,6 +450,10 @@ int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num)
|
||||
{
|
||||
CharDriverState *s = be->chr;
|
||||
|
||||
if (!s) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return s->set_msgfds ? s->set_msgfds(s, fds, num) : -1;
|
||||
}
|
||||
|
||||
@ -449,6 +466,10 @@ void qemu_chr_fe_accept_input(CharBackend *be)
|
||||
{
|
||||
CharDriverState *s = be->chr;
|
||||
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->chr_accept_input)
|
||||
s->chr_accept_input(s);
|
||||
qemu_notify_event();
|
||||
@ -945,6 +966,10 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
|
||||
|
||||
void qemu_chr_fe_take_focus(CharBackend *b)
|
||||
{
|
||||
if (!b->chr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (b->chr->is_mux) {
|
||||
mux_set_focus(b->chr->opaque, b->tag);
|
||||
}
|
||||
@ -3347,6 +3372,11 @@ static int qemu_chr_wait_connected(CharDriverState *chr, Error **errp)
|
||||
|
||||
int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp)
|
||||
{
|
||||
if (!be->chr) {
|
||||
error_setg(errp, "missing associated backend");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return qemu_chr_wait_connected(be->chr, errp);
|
||||
}
|
||||
|
||||
@ -4151,7 +4181,7 @@ void qemu_chr_fe_set_echo(CharBackend *be, bool echo)
|
||||
{
|
||||
CharDriverState *chr = be->chr;
|
||||
|
||||
if (chr->chr_set_echo) {
|
||||
if (chr && chr->chr_set_echo) {
|
||||
chr->chr_set_echo(chr, echo);
|
||||
}
|
||||
}
|
||||
@ -4160,6 +4190,10 @@ void qemu_chr_fe_set_open(CharBackend *be, int fe_open)
|
||||
{
|
||||
CharDriverState *chr = be->chr;
|
||||
|
||||
if (!chr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (chr->fe_open == fe_open) {
|
||||
return;
|
||||
}
|
||||
@ -4173,7 +4207,7 @@ void qemu_chr_fe_event(CharBackend *be, int event)
|
||||
{
|
||||
CharDriverState *chr = be->chr;
|
||||
|
||||
if (chr->chr_fe_event) {
|
||||
if (chr && chr->chr_fe_event) {
|
||||
chr->chr_fe_event(chr, event);
|
||||
}
|
||||
}
|
||||
@ -4185,7 +4219,7 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
|
||||
GSource *src;
|
||||
guint tag;
|
||||
|
||||
if (s->chr_add_watch == NULL) {
|
||||
if (!s || s->chr_add_watch == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4205,7 +4239,7 @@ void qemu_chr_fe_disconnect(CharBackend *be)
|
||||
{
|
||||
CharDriverState *chr = be->chr;
|
||||
|
||||
if (chr->chr_disconnect) {
|
||||
if (chr && chr->chr_disconnect) {
|
||||
chr->chr_disconnect(chr);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user