qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: qemu-devel@nongnu.org
Cc: Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [RFC 13/14] vga: Add endian control register
Date: Tue, 24 Jun 2014 09:11:07 +1000	[thread overview]
Message-ID: <1403565068-15229-14-git-send-email-benh@kernel.crashing.org> (raw)
In-Reply-To: <1403565068-15229-1-git-send-email-benh@kernel.crashing.org>

Include the endian state in the migration stream as an optional
subsection which we only include when the endian isn't the default,
thus enabling backward compatibility of the common case.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 hw/display/vga.c     | 55 ++++++++++++++++++++++++++++++++++++++++++++++------
 hw/display/vga_int.h | 15 +++++++++++++-
 2 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/hw/display/vga.c b/hw/display/vga.c
index 29d57cf..54b1fbe 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -615,6 +615,11 @@ uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
         }
     } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
         val = s->vram_size / (64 * 1024);
+    } else if (s->vbe_index == VBE_DISPI_INDEX_EXTENDED_CAPS) {
+        val = VBE_DISPI_HAS_ENDIAN_CTRL;
+    } else if (s->vbe_index == VBE_DISPI_INDEX_ENDIAN_CTRL) {
+        val = s->big_endian_fb ? VBE_DISPI_BIG_ENDIAN :
+                VBE_DISPI_LITTLE_ENDIAN;
     } else {
         val = 0;
     }
@@ -634,7 +639,8 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
 {
     VGACommonState *s = opaque;
 
-    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
+    if (s->vbe_index <= VBE_DISPI_INDEX_NB ||
+        s->vbe_index == VBE_DISPI_INDEX_ENDIAN_CTRL) {
 #ifdef DEBUG_BOCHS_VBE
         printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
 #endif
@@ -737,7 +743,7 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
                 s->bank_offset = 0;
             }
             s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
-            s->vbe_regs[s->vbe_index] = val;
+            s->vbe_regs[s->vbe_index] = val | VBE_DISPI_EXTCAPS;
             vga_update_memory_access(s);
             break;
         case VBE_DISPI_INDEX_VIRT_WIDTH:
@@ -774,6 +780,9 @@ void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
                 s->vbe_start_addr >>= 2;
             }
             break;
+	case VBE_DISPI_INDEX_ENDIAN_CTRL:
+            s->big_endian_fb = !!(val & VBE_DISPI_BIG_ENDIAN);
+            break;
         default:
             break;
         }
@@ -1464,7 +1473,8 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
     if (s->line_offset != s->last_line_offset ||
         disp_width != s->last_width ||
         height != s->last_height ||
-        s->last_depth != depth) {
+        s->last_depth != depth ||
+        s->last_byteswap != byteswap) {
 	if (depth == 32 || depth == 24 ||
            ((depth == 16 || depth == 15) && !byteswap)) {
             pixman_format_code_t format =
@@ -1483,6 +1493,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
         s->last_height = height;
         s->last_line_offset = s->line_offset;
         s->last_depth = depth;
+        s->last_byteswap = byteswap;
         full_update = 1;
     } else if (is_buffer_shared(surface) &&
                (full_update || surface_data(surface) != s->vram_ptr
@@ -1731,6 +1742,7 @@ void vga_common_reset(VGACommonState *s)
     s->vbe_index = 0;
     memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
+    s->vbe_regs[VBE_DISPI_INDEX_ENABLE] = VBE_DISPI_EXTCAPS;
     s->vbe_start_addr = 0;
     s->vbe_line_offset = 0;
     s->vbe_bank_mask = (s->vram_size >> 16) - 1;
@@ -1751,6 +1763,7 @@ void vga_common_reset(VGACommonState *s)
     s->cursor_start = 0;
     s->cursor_end = 0;
     s->cursor_offset = 0;
+    s->big_endian_fb = s->default_endian_fb;
     memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
     memset(s->last_palette, '\0', sizeof(s->last_palette));
     memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
@@ -1982,6 +1995,28 @@ static int vga_common_post_load(void *opaque, int version_id)
     return 0;
 }
 
+static bool vga_endian_state_needed(void *opaque)
+{
+    VGACommonState *s = opaque;
+
+    /*
+     * Only send the endian state if it's different from the
+     * default one, thus ensuring backward compatibility for
+     * migration of the common case
+     */
+    return s->default_endian_fb != s->big_endian_fb;
+}
+
+const VMStateDescription vmstate_vga_endian = {
+    .name = "vga.endian",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8_EQUAL(big_endian_fb, VGACommonState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 const VMStateDescription vmstate_vga_common = {
     .name = "vga",
     .version_id = 2,
@@ -2018,6 +2053,14 @@ const VMStateDescription vmstate_vga_common = {
         VMSTATE_UINT32(vbe_line_offset, VGACommonState),
         VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
         VMSTATE_END_OF_LIST()
+    },
+    .subsections = (VMStateSubsection []) {
+        {
+            .vmsd = &vmstate_vga_endian,
+            .needed = vga_endian_state_needed,
+        }, {
+            /* empty */
+        }
     }
 };
 
@@ -2084,14 +2127,14 @@ void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate)
     }
 
     /*
-     * Set default fb endian based on target, should probably be turned
+     * Set default fb endian based on target, could probably be turned
      * into a device attribute set by the machine/platform to remove
      * all target endian dependencies from this file.
      */
 #ifdef TARGET_WORDS_BIGENDIAN
-    s->big_endian_fb = true;
+    s->default_endian_fb = true;
 #else
-    s->big_endian_fb = false;
+    s->default_endian_fb = false;
 #endif
     vga_dirty_log_start(s);
 }
diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index ae64321..894c6ab 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -47,6 +47,8 @@
 #define VBE_DISPI_INDEX_Y_OFFSET        0x9
 #define VBE_DISPI_INDEX_NB              0xa /* size of vbe_regs[] */
 #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa /* read-only, not in vbe_regs */
+#define VBE_DISPI_INDEX_EXTENDED_CAPS   0xb /* read-only, not in vbe_regs */
+#define VBE_DISPI_INDEX_ENDIAN_CTRL     0xc /* not in vbe_regs */
 
 #define VBE_DISPI_ID0                   0xB0C0
 #define VBE_DISPI_ID1                   0xB0C1
@@ -55,13 +57,22 @@
 #define VBE_DISPI_ID4                   0xB0C4
 #define VBE_DISPI_ID5                   0xB0C5
 
+/* VBE_DISPI_INDEX_ENABLE fields */
 #define VBE_DISPI_DISABLED              0x00
 #define VBE_DISPI_ENABLED               0x01
 #define VBE_DISPI_GETCAPS               0x02
+#define VBE_DISPI_EXTCAPS               0x10 /* RO: set when 0xb present */
 #define VBE_DISPI_8BIT_DAC              0x20
 #define VBE_DISPI_LFB_ENABLED           0x40
 #define VBE_DISPI_NOCLEARMEM            0x80
 
+/* VBE_DISPI_INDEX_EXTENDED_CAPS fields */
+#define VBE_DISPI_HAS_ENDIAN_CTRL	0x01 /* RO: has endian control reg */
+
+/* VBE_DISPI_INDEX_ENDIAN_CTRL */
+#define VBE_DISPI_LITTLE_ENDIAN		0x00
+#define VBE_DISPI_BIG_ENDIAN		0x01
+
 #define VBE_DISPI_LFB_PHYSICAL_ADDRESS  0xE0000000
 
 #define CH_ATTR_SIZE (160 * 100)
@@ -148,6 +159,7 @@ typedef struct VGACommonState {
     uint32_t last_width, last_height; /* in chars or pixels */
     uint32_t last_scr_width, last_scr_height; /* in pixels */
     uint32_t last_depth; /* in bits */
+    bool last_byteswap;
     uint8_t cursor_start, cursor_end;
     bool cursor_visible_phase;
     int64_t cursor_blink_time;
@@ -155,7 +167,8 @@ typedef struct VGACommonState {
     const GraphicHwOps *hw_ops;
     bool full_update_text;
     bool full_update_gfx;
-    bool big_endian_fb;
+    uint8_t big_endian_fb;
+    uint8_t default_endian_fb;
     /* hardware mouse cursor support */
     uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32];
     void (*cursor_invalidate)(struct VGACommonState *s);
-- 
1.9.1

  parent reply	other threads:[~2014-06-23 23:12 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-23 23:10 [Qemu-devel] [RFC 00/14] VGA cleanups and endian control Benjamin Herrenschmidt
2014-06-23 23:10 ` [Qemu-devel] [RFC 01/14] vga: Create direct sufaces for depth 24 too Benjamin Herrenschmidt
2014-07-01  7:09   ` Gerd Hoffmann
2014-07-01  9:31     ` Benjamin Herrenschmidt
2014-06-23 23:10 ` [Qemu-devel] [RFC 02/14] ui: Remove unused QEMU_BIG_ENDIAN_FLAG Benjamin Herrenschmidt
2014-06-23 23:10 ` [Qemu-devel] [RFC 03/14] vga: Start cutting out non-32bpp conversion support Benjamin Herrenschmidt
2014-06-23 23:10 ` [Qemu-devel] [RFC 04/14] vga: Remove remainder of old conversion cruft Benjamin Herrenschmidt
2014-06-23 23:10 ` [Qemu-devel] [RFC 05/14] vga: Remove unused vga_draw_line24() and vga_draw_line32() Benjamin Herrenschmidt
2014-06-23 23:11 ` [Qemu-devel] [RFC 06/14] vga: 15 and 16bpp draw functions are "swapping" only Benjamin Herrenschmidt
2014-06-23 23:11 ` [Qemu-devel] [RFC 07/14] vga: Remove rgb_to_pixel indirection Benjamin Herrenschmidt
2014-06-23 23:11 ` [Qemu-devel] [RFC 08/14] vga: Simplify vga_draw_blank() a bit Benjamin Herrenschmidt
2014-06-23 23:11 ` [Qemu-devel] [RFC 09/14] cirrus: Remove non-32bpp cursor drawing Benjamin Herrenschmidt
2014-06-23 23:11 ` [Qemu-devel] [RFC 10/14] vga: Remove some "should be done in BIOS" comments Benjamin Herrenschmidt
2014-06-30 11:31   ` Gerd Hoffmann
2014-06-23 23:11 ` [Qemu-devel] [RFC 11/14] vga: Make fb endian a common state variable Benjamin Herrenschmidt
2014-06-23 23:24   ` Peter Maydell
2014-06-23 23:44     ` Benjamin Herrenschmidt
2014-06-23 23:11 ` [Qemu-devel] [RFC 12/14] vga: Rename vga_template.h to vga-helpers.h Benjamin Herrenschmidt
2014-06-23 23:11 ` Benjamin Herrenschmidt [this message]
2014-06-23 23:48   ` [Qemu-devel] [RFC 13/14] vga: Add endian control register Benjamin Herrenschmidt
2014-06-30 11:38   ` Gerd Hoffmann
2014-06-30 12:34     ` Benjamin Herrenschmidt
2014-06-23 23:11 ` [Qemu-devel] [RFC 14/14] ppc/spapr/vga: Switch VGA endian on H_SET_MODE Benjamin Herrenschmidt
2014-06-30 11:49   ` Gerd Hoffmann
2014-06-30 12:34     ` Benjamin Herrenschmidt
2014-06-30 11:50 ` [Qemu-devel] [RFC 00/14] VGA cleanups and endian control Gerd Hoffmann
2014-06-30 12:36   ` Benjamin Herrenschmidt
2014-06-30 13:03     ` Gerd Hoffmann
2014-06-30 13:36       ` Benjamin Herrenschmidt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1403565068-15229-14-git-send-email-benh@kernel.crashing.org \
    --to=benh@kernel.crashing.org \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).