From patchwork Tue Jun 21 12:23:36 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Dovgalyuk X-Patchwork-Id: 101281 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D2606B6F77 for ; Tue, 21 Jun 2011 22:28:48 +1000 (EST) Received: from localhost ([::1]:35469 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QZ04S-0001kH-5M for incoming@patchwork.ozlabs.org; Tue, 21 Jun 2011 08:28:44 -0400 Received: from eggs.gnu.org ([140.186.70.92]:56190) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QZ00h-0001QR-Gd for qemu-devel@nongnu.org; Tue, 21 Jun 2011 08:24:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QZ00c-0005qS-6D for qemu-devel@nongnu.org; Tue, 21 Jun 2011 08:24:51 -0400 Received: from smtp.ispras.ru ([83.149.198.202]:39249) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QZ00b-0005oV-4C for qemu-devel@nongnu.org; Tue, 21 Jun 2011 08:24:45 -0400 Received: from PASHAISP (ispserv.ispras.ru [83.149.198.72]) by smtp.ispras.ru (Postfix) with ESMTP id 3B4A35D407D for ; Tue, 21 Jun 2011 16:18:45 +0400 (MSD) From: "Pavel Dovgaluk" To: "'qemu-devel'" Date: Tue, 21 Jun 2011 16:23:36 +0400 Message-ID: <001501cc300e$0b66bea0$22343be0$@Dovgaluk@ispras.ru> MIME-Version: 1.0 X-Mailer: Microsoft Office Outlook 12.0 Thread-Index: AcwwDgtJSHdU19qoQFSnHsmA3w0qrw== Content-Language: ru X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 83.149.198.202 Subject: [Qemu-devel] [PATCH] Fix serial interface vmstate X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch fixes save/restore of serial interface's state. It includes changing of fcr setter function (it now does not invoke an interrupt while loading vmstate), and saving/restoring all fields that describe the state of serial interface (including timers). Signed-off-by: Pavel Dovgalyuk --- hw/serial.c | 133 ++++++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 87 insertions(+), 46 deletions(-) diff --git a/hw/serial.c b/hw/serial.c index 0ee61dd..936e048 100644 --- a/hw/serial.c +++ b/hw/serial.c @@ -362,6 +362,62 @@ static void serial_xmit(void *opaque) } +/* Setter for FCR. + is_load flag means, that value is set while loading VM state + and interrupt should not be invoked */ +static void serial_write_fcr(void *opaque, uint32_t val, int is_load) +{ + SerialState *s = opaque; + + val = val & 0xFF; + + if (s->fcr == val) + return; + + /* Did the enable/disable flag change? If so, make sure FIFOs get flushed */ + if ((val ^ s->fcr) & UART_FCR_FE) + val |= UART_FCR_XFR | UART_FCR_RFR; + + /* FIFO clear */ + + if (val & UART_FCR_RFR) { + qemu_del_timer(s->fifo_timeout_timer); + s->timeout_ipending=0; + fifo_clear(s,RECV_FIFO); + } + + if (val & UART_FCR_XFR) { + fifo_clear(s,XMIT_FIFO); + } + + if (val & UART_FCR_FE) { + s->iir |= UART_IIR_FE; + /* Set RECV_FIFO trigger Level */ + switch (val & 0xC0) { + case UART_FCR_ITL_1: + s->recv_fifo.itl = 1; + break; + case UART_FCR_ITL_2: + s->recv_fifo.itl = 4; + break; + case UART_FCR_ITL_3: + s->recv_fifo.itl = 8; + break; + case UART_FCR_ITL_4: + s->recv_fifo.itl = 14; + break; + } + } else + s->iir &= ~UART_IIR_FE; + + /* Set fcr - or at least the bits in it that are supposed to "stick" */ + s->fcr = val & 0xC9; + if (!is_load) { + serial_update_irq(s); + } +} + + static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) { SerialState *s = opaque; @@ -414,50 +470,7 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) } break; case 2: - val = val & 0xFF; - - if (s->fcr == val) - break; - - /* Did the enable/disable flag change? If so, make sure FIFOs get flushed */ - if ((val ^ s->fcr) & UART_FCR_FE) - val |= UART_FCR_XFR | UART_FCR_RFR; - - /* FIFO clear */ - - if (val & UART_FCR_RFR) { - qemu_del_timer(s->fifo_timeout_timer); - s->timeout_ipending=0; - fifo_clear(s,RECV_FIFO); - } - - if (val & UART_FCR_XFR) { - fifo_clear(s,XMIT_FIFO); - } - - if (val & UART_FCR_FE) { - s->iir |= UART_IIR_FE; - /* Set RECV_FIFO trigger Level */ - switch (val & 0xC0) { - case UART_FCR_ITL_1: - s->recv_fifo.itl = 1; - break; - case UART_FCR_ITL_2: - s->recv_fifo.itl = 4; - break; - case UART_FCR_ITL_3: - s->recv_fifo.itl = 8; - break; - case UART_FCR_ITL_4: - s->recv_fifo.itl = 14; - break; - } - } else - s->iir &= ~UART_IIR_FE; - - /* Set fcr - or at least the bits in it that are supposed to "stick" */ - s->fcr = val & 0xC9; - serial_update_irq(s); + serial_write_fcr(s, val, 0); break; case 3: { @@ -673,20 +686,38 @@ static int serial_post_load(void *opaque, int version_id) s->fcr_vmstate = 0; } /* Initialize fcr via setter to perform essential side-effects */ - serial_ioport_write(s, 0x02, s->fcr_vmstate); + serial_write_fcr(s, s->fcr_vmstate, 1); serial_update_parameters(s); return 0; } + +static const VMStateDescription vmstate_fifo = { + .name = "serial FIFO", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField []) { + VMSTATE_BUFFER(data, SerialFIFO), + VMSTATE_UINT8(count, SerialFIFO), + VMSTATE_UINT8(itl, SerialFIFO), + VMSTATE_UINT8(tail, SerialFIFO), + VMSTATE_UINT8(head, SerialFIFO), + VMSTATE_END_OF_LIST() + } +}; + + static const VMStateDescription vmstate_serial = { .name = "serial", - .version_id = 3, + .version_id = 4, .minimum_version_id = 2, .pre_save = serial_pre_save, .post_load = serial_post_load, .fields = (VMStateField []) { VMSTATE_UINT16_V(divider, SerialState, 2), VMSTATE_UINT8(rbr, SerialState), + VMSTATE_UINT8_V(thr, SerialState, 4), + VMSTATE_UINT8_V(tsr, SerialState, 4), VMSTATE_UINT8(ier, SerialState), VMSTATE_UINT8(iir, SerialState), VMSTATE_UINT8(lcr, SerialState), @@ -695,6 +726,16 @@ static const VMStateDescription vmstate_serial = { VMSTATE_UINT8(msr, SerialState), VMSTATE_UINT8(scr, SerialState), VMSTATE_UINT8_V(fcr_vmstate, SerialState, 3), + VMSTATE_INT32_V(thr_ipending, SerialState, 4), + VMSTATE_INT32_V(last_break_enable, SerialState, 4), + VMSTATE_INT32_V(tsr_retry, SerialState, 4), + VMSTATE_STRUCT(recv_fifo, SerialState, 4, vmstate_fifo, SerialFIFO), + VMSTATE_STRUCT(xmit_fifo, SerialState, 4, vmstate_fifo, SerialFIFO), + VMSTATE_TIMER_V(fifo_timeout_timer, SerialState, 4), + VMSTATE_INT32_V(timeout_ipending, SerialState, 4), + VMSTATE_TIMER_V(transmit_timer, SerialState, 4), + VMSTATE_INT32_V(poll_msl, SerialState, 4), + VMSTATE_TIMER_V(modem_status_poll, SerialState, 4), VMSTATE_END_OF_LIST() } };