[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC 13/14] vga: Add endian control register
From: |
Benjamin Herrenschmidt |
Subject: |
Re: [Qemu-devel] [RFC 13/14] vga: Add endian control register |
Date: |
Tue, 24 Jun 2014 09:48:51 +1000 |
On Tue, 2014-06-24 at 09:11 +1000, Benjamin Herrenschmidt wrote:
> 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.
Note: This description is a bit too terse, sorry about that....
This is based on the proposed register addition that I've discussed
in a separate email, adding an "extended capabilities" register and
using it to expose the endian control.
Arguably, this could be split into 2 patches...
At this point however, I'd first want to make sure we all agree on the
approach before going down into the details.
I haven't been successful contacting the Bochs folks, either on their
mailing list or on IRC.
Ben.
> Signed-off-by: Benjamin Herrenschmidt <address@hidden>
> ---
> 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);
- [Qemu-devel] [RFC 09/14] cirrus: Remove non-32bpp cursor drawing, (continued)
- [Qemu-devel] [RFC 09/14] cirrus: Remove non-32bpp cursor drawing, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 01/14] vga: Create direct sufaces for depth 24 too, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 04/14] vga: Remove remainder of old conversion cruft, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 06/14] vga: 15 and 16bpp draw functions are "swapping" only, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 03/14] vga: Start cutting out non-32bpp conversion support, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 08/14] vga: Simplify vga_draw_blank() a bit, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 10/14] vga: Remove some "should be done in BIOS" comments, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 07/14] vga: Remove rgb_to_pixel indirection, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 13/14] vga: Add endian control register, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 12/14] vga: Rename vga_template.h to vga-helpers.h, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 05/14] vga: Remove unused vga_draw_line24() and vga_draw_line32(), Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 11/14] vga: Make fb endian a common state variable, Benjamin Herrenschmidt, 2014/06/23
- [Qemu-devel] [RFC 14/14] ppc/spapr/vga: Switch VGA endian on H_SET_MODE, Benjamin Herrenschmidt, 2014/06/23