Introduce reset notifier order
[qemu] / hw / serial.c
index d70207e..a82c29c 100644 (file)
@@ -125,7 +125,6 @@ struct SerialState {
     qemu_irq irq;
     CharDriverState *chr;
     int last_break_enable;
-    target_phys_addr_t base;
     int it_shift;
     int baudbase;
     int tsr_retry;
@@ -191,7 +190,10 @@ static void serial_update_irq(SerialState *s)
 
     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)) {
@@ -709,16 +711,18 @@ static void serial_init_core(SerialState *s, qemu_irq irq, int baudbase,
 {
     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 */
@@ -728,8 +732,6 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
     SerialState *s;
 
     s = qemu_mallocz(sizeof(SerialState));
-    if (!s)
-        return NULL;
 
     serial_init_core(s, irq, baudbase, chr);
 
@@ -737,8 +739,6 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
 
     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;
 }
 
@@ -747,7 +747,7 @@ uint32_t serial_mm_readb (void *opaque, target_phys_addr_t addr)
 {
     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,
@@ -755,7 +755,7 @@ 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)
@@ -763,7 +763,7 @@ 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
@@ -777,7 +777,7 @@ void serial_mm_writew (void *opaque,
 #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)
@@ -785,7 +785,7 @@ 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
@@ -799,7 +799,7 @@ void serial_mm_writel (void *opaque,
 #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[] = {
@@ -822,10 +822,7 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
     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);
@@ -836,8 +833,6 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift,
                                              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;
 }