qemu_irq irq;
CharDriverState *chr;
int last_break_enable;
- target_phys_addr_t base;
int it_shift;
int baudbase;
int tsr_retry;
if ((s->ier & UART_IER_RLSI) && (s->lsr & UART_LSR_INT_ANY)) {
tmp_iir = UART_IIR_RLSI;
- } else if (s->timeout_ipending) {
+ } else if ((s->ier & UART_IER_RDI) && s->timeout_ipending) {
+ /* Note that(s->ier & UART_IER_RDI) can mask this interrupt,
+ * this is not in the specification but is observed on existing
+ * hardware. */
tmp_iir = UART_IIR_CTI;
} else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR)) {
if (!(s->fcr & UART_FCR_FE)) {
static void serial_receive_break(SerialState *s)
{
s->rbr = 0;
+ /* When the LSR_DR is set a null byte is pushed into the fifo */
+ fifo_put(s, RECV_FIFO, '\0');
s->lsr |= UART_LSR_BI | UART_LSR_DR;
serial_update_irq(s);
}
{
s->irq = irq;
s->baudbase = baudbase;
- s->chr = chr;
+ s->chr = chr ?: qemu_chr_open("null", "null", NULL);
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);
s->transmit_timer = qemu_new_timer(vm_clock, (QEMUTimerCB *) serial_xmit, s);
- qemu_register_reset(serial_reset, s);
+ qemu_register_reset(serial_reset, 0, s);
serial_reset(s);
+ qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
+ serial_event, s);
}
/* If fd is zero, it means that the serial device uses the console */
SerialState *s;
s = qemu_mallocz(sizeof(SerialState));
- if (!s)
- return NULL;
serial_init_core(s, irq, baudbase, chr);
register_ioport_write(base, 8, 1, serial_ioport_write, s);
register_ioport_read(base, 8, 1, serial_ioport_read, s);
- qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1,
- serial_event, s);
return s;
}
{
SerialState *s = opaque;
- return serial_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFF;
+ return serial_ioport_read(s, addr >> s->it_shift) & 0xFF;
}
void serial_mm_writeb (void *opaque,
{
SerialState *s = opaque;
- serial_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFF);
+ serial_ioport_write(s, addr >> s->it_shift, value & 0xFF);
}
uint32_t serial_mm_readw (void *opaque, target_phys_addr_t addr)
SerialState *s = opaque;
uint32_t val;
- val = serial_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFFFF;
+ val = serial_ioport_read(s, addr >> s->it_shift) & 0xFFFF;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap16(value);
#endif
- serial_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFFFF);
+ serial_ioport_write(s, addr >> s->it_shift, value & 0xFFFF);
}
uint32_t serial_mm_readl (void *opaque, target_phys_addr_t addr)
SerialState *s = opaque;
uint32_t val;
- val = serial_ioport_read(s, (addr - s->base) >> s->it_shift);
+ val = serial_ioport_read(s, addr >> s->it_shift);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap32(value);
#endif
- serial_ioport_write(s, (addr - s->base) >> s->it_shift, value);
+ serial_ioport_write(s, addr >> s->it_shift, value);
}
static CPUReadMemoryFunc *serial_mm_read[] = {
int s_io_memory;
s = qemu_mallocz(sizeof(SerialState));
- if (!s)
- return NULL;
- s->base = base;
s->it_shift = it_shift;
serial_init_core(s, irq, baudbase, chr);
serial_mm_write, s);
cpu_register_physical_memory(base, 8 << it_shift, s_io_memory);
}
- qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1,
- serial_event, s);
serial_update_msl(s);
return s;
}