]> Git Repo - qemu.git/blobdiff - hw/vga.c
find -type f | xargs sed -i 's/[\t ]$//g' # on most files
[qemu.git] / hw / vga.c
index 2c425ffe9bb01633cd80947b016f559cd0508194..de74764e56c9242818226e8e0dced1d4893d2443 100644 (file)
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1,8 +1,8 @@
 /*
  * QEMU VGA Emulator.
- * 
+ *
  * Copyright (c) 2003 Fabrice Bellard
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
@@ -23,6 +23,7 @@
  */
 #include "vl.h"
 #include "vga_int.h"
+#include "pixel_ops.h"
 
 //#define DEBUG_VGA
 //#define DEBUG_VGA_MEM
@@ -143,8 +144,7 @@ static uint32_t expand4[256];
 static uint16_t expand2[256];
 static uint8_t expand4to8[16];
 
-VGAState *vga_state;
-int vga_io_memory;
+static void vga_screen_dump(void *opaque, const char *filename);
 
 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
 {
@@ -166,7 +166,7 @@ static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
             break;
         case 0x3c1:
             index = s->ar_index & 0x1f;
-            if (index < 21) 
+            if (index < 21)
                 val = s->ar[index];
             else
                 val = 0;
@@ -347,7 +347,7 @@ static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
         case 0x09:
         case 0x0c:
         case 0x0d:
-        case 0x12: /* veritcal display end */
+        case 0x12: /* vertical display end */
             s->cr[s->cr_index] = val;
             break;
         default:
@@ -376,10 +376,29 @@ static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
     VGAState *s = opaque;
     uint32_t val;
 
-    if (s->vbe_index <= VBE_DISPI_INDEX_NB)
-        val = s->vbe_regs[s->vbe_index];
-    else
+    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
+        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
+            switch(s->vbe_index) {
+                /* XXX: do not hardcode ? */
+            case VBE_DISPI_INDEX_XRES:
+                val = VBE_DISPI_MAX_XRES;
+                break;
+            case VBE_DISPI_INDEX_YRES:
+                val = VBE_DISPI_MAX_YRES;
+                break;
+            case VBE_DISPI_INDEX_BPP:
+                val = VBE_DISPI_MAX_BPP;
+                break;
+            default:
+                val = s->vbe_regs[s->vbe_index];
+                break;
+            }
+        } else {
+            val = s->vbe_regs[s->vbe_index];
+        }
+    } else {
         val = 0;
+    }
 #ifdef DEBUG_BOCHS_VBE
     printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
 #endif
@@ -404,7 +423,9 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
         case VBE_DISPI_INDEX_ID:
             if (val == VBE_DISPI_ID0 ||
                 val == VBE_DISPI_ID1 ||
-                val == VBE_DISPI_ID2) {
+                val == VBE_DISPI_ID2 ||
+                val == VBE_DISPI_ID3 ||
+                val == VBE_DISPI_ID4) {
                 s->vbe_regs[s->vbe_index] = val;
             }
             break;
@@ -421,40 +442,45 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
         case VBE_DISPI_INDEX_BPP:
             if (val == 0)
                 val = 8;
-            if (val == 4 || val == 8 || val == 15 || 
+            if (val == 4 || val == 8 || val == 15 ||
                 val == 16 || val == 24 || val == 32) {
                 s->vbe_regs[s->vbe_index] = val;
             }
             break;
         case VBE_DISPI_INDEX_BANK:
-            val &= s->vbe_bank_mask;
+            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
+              val &= (s->vbe_bank_mask >> 2);
+            } else {
+              val &= s->vbe_bank_mask;
+            }
             s->vbe_regs[s->vbe_index] = val;
             s->bank_offset = (val << 16);
             break;
         case VBE_DISPI_INDEX_ENABLE:
-            if (val & VBE_DISPI_ENABLED) {
+            if ((val & VBE_DISPI_ENABLED) &&
+                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
                 int h, shift_control;
 
-                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 
+                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
                     s->vbe_regs[VBE_DISPI_INDEX_XRES];
-                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = 
+                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
                     s->vbe_regs[VBE_DISPI_INDEX_YRES];
                 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
                 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
-                
+               
                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
                 else
-                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * 
+                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
                         ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
                 s->vbe_start_addr = 0;
-                
+
                 /* clear the screen (should be done in BIOS) */
                 if (!(val & VBE_DISPI_NOCLEARMEM)) {
-                    memset(s->vram_ptr, 0, 
+                    memset(s->vram_ptr, 0,
                            s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
                 }
-                
+               
                 /* we initialize the VGA graphic mode (should be done
                    in BIOS) */
                 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
@@ -462,16 +488,16 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
                 s->cr[0x13] = s->vbe_line_offset >> 3;
                 /* width */
                 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
-                /* height */
+                /* height (only meaningful if < 1024) */
                 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
                 s->cr[0x12] = h;
-                s->cr[0x07] = (s->cr[0x07] & ~0x42) | 
+                s->cr[0x07] = (s->cr[0x07] & ~0x42) |
                     ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
                 /* line compare to 1023 */
                 s->cr[0x18] = 0xff;
                 s->cr[0x07] |= 0x10;
                 s->cr[0x09] |= 0x40;
-                
+               
                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
                     shift_control = 0;
                     s->sr[0x01] &= ~8; /* no double line */
@@ -486,6 +512,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
                 /* XXX: the bios should do that */
                 s->bank_offset = 0;
             }
+            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
             s->vbe_regs[s->vbe_index] = val;
             break;
         case VBE_DISPI_INDEX_VIRT_WIDTH:
@@ -535,7 +562,7 @@ uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
     VGAState *s = opaque;
     int memory_map_mode, plane;
     uint32_t ret;
-    
+   
     /* convert to VGA memory offset */
     memory_map_mode = (s->gr[6] >> 2) & 3;
     addr &= 0x1ffff;
@@ -559,7 +586,7 @@ uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
             return 0xff;
         break;
     }
-    
+   
     if (s->sr[4] & 0x08) {
         /* chain 4 mode : simplest access */
         ret = s->vram_ptr[addr];
@@ -649,7 +676,7 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
             return;
         break;
     }
-    
+   
     if (s->sr[4] & 0x08) {
         /* chain 4 mode : simplest access */
         plane = addr & 3;
@@ -740,11 +767,11 @@ void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
         mask = s->sr[2];
         s->plane_updated |= mask; /* only used to detect font change */
         write_mask = mask16[mask];
-        ((uint32_t *)s->vram_ptr)[addr] = 
-            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
+        ((uint32_t *)s->vram_ptr)[addr] =
+            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
             (val & write_mask);
 #ifdef DEBUG_VGA_MEM
-            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
+            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
                    addr * 4, write_mask, val);
 #endif
             cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
@@ -781,40 +808,32 @@ typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
                              const uint8_t *font_ptr, int h,
                              uint32_t fgcol, uint32_t bgcol);
 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
-                                  const uint8_t *font_ptr, int h, 
+                                  const uint8_t *font_ptr, int h,
                                   uint32_t fgcol, uint32_t bgcol, int dup9);
-typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
+typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
                                 const uint8_t *s, int width);
 
-static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
-{
-    return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
-}
-
-static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
-{
-    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
-}
-
-static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
-{
-    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
-}
-
-static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
-{
-    return (r << 16) | (g << 8) | b;
-}
-
 #define DEPTH 8
 #include "vga_template.h"
 
 #define DEPTH 15
 #include "vga_template.h"
 
+#define BGR_FORMAT
+#define DEPTH 15
+#include "vga_template.h"
+
 #define DEPTH 16
 #include "vga_template.h"
 
+#define BGR_FORMAT
+#define DEPTH 16
+#include "vga_template.h"
+
+#define DEPTH 32
+#include "vga_template.h"
+
+#define BGR_FORMAT
 #define DEPTH 32
 #include "vga_template.h"
 
@@ -835,6 +854,15 @@ static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned
     return col;
 }
 
+static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
+                                          unsigned int b)
+{
+    unsigned int col;
+    col = rgb_to_pixel15bgr(r, g, b);
+    col |= col << 16;
+    return col;
+}
+
 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
 {
     unsigned int col;
@@ -843,6 +871,15 @@ static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned
     return col;
 }
 
+static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
+                                          unsigned int b)
+{
+    unsigned int col;
+    col = rgb_to_pixel16bgr(r, g, b);
+    col |= col << 16;
+    return col;
+}
+
 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
 {
     unsigned int col;
@@ -850,6 +887,13 @@ static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned
     return col;
 }
 
+static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
+{
+    unsigned int col;
+    col = rgb_to_pixel32bgr(r, g, b);
+    return col;
+}
+
 /* return true if the palette was modified */
 static int update_palette16(VGAState *s)
 {
@@ -865,8 +909,8 @@ static int update_palette16(VGAState *s)
         else
             v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
         v = v * 3;
-        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
-                              c6_to_8(s->palette[v + 1]), 
+        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
+                              c6_to_8(s->palette[v + 1]),
                               c6_to_8(s->palette[v + 2]));
         if (col != palette[i]) {
             full_update = 1;
@@ -886,9 +930,15 @@ static int update_palette256(VGAState *s)
     palette = s->last_palette;
     v = 0;
     for(i = 0; i < 256; i++) {
-        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
-                              c6_to_8(s->palette[v + 1]), 
-                              c6_to_8(s->palette[v + 2]));
+        if (s->dac_8bit) {
+          col = s->rgb_to_pixel(s->palette[v],
+                                s->palette[v + 1],
+                                s->palette[v + 2]);
+        } else {
+          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
+                                c6_to_8(s->palette[v + 1]),
+                                c6_to_8(s->palette[v + 2]));
+        }
         if (col != palette[i]) {
             full_update = 1;
             palette[i] = col;
@@ -898,27 +948,35 @@ static int update_palette256(VGAState *s)
     return full_update;
 }
 
-static void vga_get_offsets(VGAState *s, 
-                            uint32_t *pline_offset, 
-                            uint32_t *pstart_addr)
+static void vga_get_offsets(VGAState *s,
+                            uint32_t *pline_offset,
+                            uint32_t *pstart_addr,
+                            uint32_t *pline_compare)
 {
-    uint32_t start_addr, line_offset;
+    uint32_t start_addr, line_offset, line_compare;
 #ifdef CONFIG_BOCHS_VBE
     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
         line_offset = s->vbe_line_offset;
         start_addr = s->vbe_start_addr;
+        line_compare = 65535;
     } else
 #endif
-    {  
+    { 
         /* compute line_offset in bytes */
         line_offset = s->cr[0x13];
         line_offset <<= 3;
 
         /* starting address */
         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
+
+        /* line compare */
+        line_compare = s->cr[0x18] |
+            ((s->cr[0x07] & 0x10) << 4) |
+            ((s->cr[0x09] & 0x40) << 3);
     }
     *pline_offset = line_offset;
     *pstart_addr = start_addr;
+    *pline_compare = line_compare;
 }
 
 /* update start_addr and line_offset. Return TRUE if modified */
@@ -926,14 +984,10 @@ static int update_basic_params(VGAState *s)
 {
     int full_update;
     uint32_t start_addr, line_offset, line_compare;
-    
+   
     full_update = 0;
 
-    s->get_offsets(s, &line_offset, &start_addr);
-    /* line compare */
-    line_compare = s->cr[0x18] | 
-        ((s->cr[0x07] & 0x10) << 4) |
-        ((s->cr[0x09] & 0x40) << 3);
+    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
 
     if (line_offset != s->line_offset ||
         start_addr != s->start_addr ||
@@ -946,42 +1000,62 @@ static int update_basic_params(VGAState *s)
     return full_update;
 }
 
-static inline int get_depth_index(int depth)
+#define NB_DEPTHS 7
+
+static inline int get_depth_index(DisplayState *s)
 {
-    switch(depth) {
+    switch(s->depth) {
     default:
     case 8:
         return 0;
     case 15:
-        return 1;
+        if (s->bgr)
+            return 5;
+        else
+            return 1;
     case 16:
-        return 2;
+        if (s->bgr)
+            return 6;
+        else
+            return 2;
     case 32:
-        return 3;
+        if (s->bgr)
+            return 4;
+        else
+            return 3;
     }
 }
 
-static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
+static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
     vga_draw_glyph8_8,
     vga_draw_glyph8_16,
     vga_draw_glyph8_16,
     vga_draw_glyph8_32,
+    vga_draw_glyph8_32,
+    vga_draw_glyph8_16,
+    vga_draw_glyph8_16,
 };
 
-static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
+static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
     vga_draw_glyph16_8,
     vga_draw_glyph16_16,
     vga_draw_glyph16_16,
     vga_draw_glyph16_32,
+    vga_draw_glyph16_32,
+    vga_draw_glyph16_16,
+    vga_draw_glyph16_16,
 };
 
-static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
+static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
     vga_draw_glyph9_8,
     vga_draw_glyph9_16,
     vga_draw_glyph9_16,
     vga_draw_glyph9_32,
+    vga_draw_glyph9_32,
+    vga_draw_glyph9_16,
+    vga_draw_glyph9_16,
 };
-    
+   
 static const uint8_t cursor_glyph[32 * 4] = {
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -999,13 +1073,13 @@ static const uint8_t cursor_glyph[32 * 4] = {
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-};    
+};   
 
-/* 
- * Text mode update 
+/*
+ * Text mode update
  * Missing:
  * - double scan
- * - double width 
+ * - double width
  * - underline
  * - flashing
  */
@@ -1024,7 +1098,7 @@ static void vga_draw_text(VGAState *s, int full_update)
 
     full_update |= update_palette16(s);
     palette = s->last_palette;
-    
+   
     /* compute font data address (in plane 2) */
     v = s->sr[3];
     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
@@ -1064,8 +1138,8 @@ static void vga_draw_text(VGAState *s, int full_update)
         /* ugly hack for CGA 160x100x16 - explain me the logic */
         height = 100;
     } else {
-        height = s->cr[0x12] | 
-            ((s->cr[0x07] & 0x02) << 7) | 
+        height = s->cr[0x12] |
+            ((s->cr[0x07] & 0x02) << 7) |
             ((s->cr[0x07] & 0x40) << 3);
         height = (height + 1) / cheight;
     }
@@ -1100,14 +1174,14 @@ static void vga_draw_text(VGAState *s, int full_update)
         s->cursor_end = s->cr[0xb];
     }
     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
-    
-    depth_index = get_depth_index(s->ds->depth);
+   
+    depth_index = get_depth_index(s->ds);
     if (cw == 16)
         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
     else
         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
-    
+   
     dest = s->ds->data;
     linesize = s->ds->linesize;
     ch_attr_ptr = s->last_ch_attr;
@@ -1136,13 +1210,13 @@ static void vga_draw_text(VGAState *s, int full_update)
                 bgcol = palette[cattr >> 4];
                 fgcol = palette[cattr & 0x0f];
                 if (cw != 9) {
-                    vga_draw_glyph8(d1, linesize, 
+                    vga_draw_glyph8(d1, linesize,
                                     font_ptr, cheight, fgcol, bgcol);
                 } else {
                     dup9 = 0;
                     if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
                         dup9 = 1;
-                    vga_draw_glyph9(d1, linesize, 
+                    vga_draw_glyph9(d1, linesize,
                                     font_ptr, cheight, fgcol, bgcol, dup9);
                 }
                 if (src == cursor_ptr &&
@@ -1158,10 +1232,10 @@ static void vga_draw_text(VGAState *s, int full_update)
                         h = line_last - line_start + 1;
                         d = d1 + linesize * line_start;
                         if (cw != 9) {
-                            vga_draw_glyph8(d, linesize, 
+                            vga_draw_glyph8(d, linesize,
                                             cursor_glyph, h, fgcol, bgcol);
                         } else {
-                            vga_draw_glyph9(d, linesize, 
+                            vga_draw_glyph9(d, linesize,
                                             cursor_glyph, h, fgcol, bgcol, 1);
                         }
                     }
@@ -1172,7 +1246,7 @@ static void vga_draw_text(VGAState *s, int full_update)
             ch_attr_ptr++;
         }
         if (cx_max != -1) {
-            dpy_update(s->ds, cx_min * cw, cy * cheight, 
+            dpy_update(s->ds, cx_min * cw, cy * cheight,
                        (cx_max - cx_min + 1) * cw, cheight);
         }
         dest += linesize * cheight;
@@ -1194,56 +1268,98 @@ enum {
     VGA_DRAW_LINE_NB,
 };
 
-static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
+static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
     vga_draw_line2_8,
     vga_draw_line2_16,
     vga_draw_line2_16,
     vga_draw_line2_32,
+    vga_draw_line2_32,
+    vga_draw_line2_16,
+    vga_draw_line2_16,
 
     vga_draw_line2d2_8,
     vga_draw_line2d2_16,
     vga_draw_line2d2_16,
     vga_draw_line2d2_32,
+    vga_draw_line2d2_32,
+    vga_draw_line2d2_16,
+    vga_draw_line2d2_16,
 
     vga_draw_line4_8,
     vga_draw_line4_16,
     vga_draw_line4_16,
     vga_draw_line4_32,
+    vga_draw_line4_32,
+    vga_draw_line4_16,
+    vga_draw_line4_16,
 
     vga_draw_line4d2_8,
     vga_draw_line4d2_16,
     vga_draw_line4d2_16,
     vga_draw_line4d2_32,
+    vga_draw_line4d2_32,
+    vga_draw_line4d2_16,
+    vga_draw_line4d2_16,
 
     vga_draw_line8d2_8,
     vga_draw_line8d2_16,
     vga_draw_line8d2_16,
     vga_draw_line8d2_32,
+    vga_draw_line8d2_32,
+    vga_draw_line8d2_16,
+    vga_draw_line8d2_16,
 
     vga_draw_line8_8,
     vga_draw_line8_16,
     vga_draw_line8_16,
     vga_draw_line8_32,
+    vga_draw_line8_32,
+    vga_draw_line8_16,
+    vga_draw_line8_16,
 
     vga_draw_line15_8,
     vga_draw_line15_15,
     vga_draw_line15_16,
     vga_draw_line15_32,
+    vga_draw_line15_32bgr,
+    vga_draw_line15_15bgr,
+    vga_draw_line15_16bgr,
 
     vga_draw_line16_8,
     vga_draw_line16_15,
     vga_draw_line16_16,
     vga_draw_line16_32,
+    vga_draw_line16_32bgr,
+    vga_draw_line16_15bgr,
+    vga_draw_line16_16bgr,
 
     vga_draw_line24_8,
     vga_draw_line24_15,
     vga_draw_line24_16,
     vga_draw_line24_32,
+    vga_draw_line24_32bgr,
+    vga_draw_line24_15bgr,
+    vga_draw_line24_16bgr,
 
     vga_draw_line32_8,
     vga_draw_line32_15,
     vga_draw_line32_16,
     vga_draw_line32_32,
+    vga_draw_line32_32bgr,
+    vga_draw_line32_15bgr,
+    vga_draw_line32_16bgr,
+};
+
+typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
+
+static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
+    rgb_to_pixel8_dup,
+    rgb_to_pixel15_dup,
+    rgb_to_pixel16_dup,
+    rgb_to_pixel32_dup,
+    rgb_to_pixel32bgr_dup,
+    rgb_to_pixel15bgr_dup,
+    rgb_to_pixel16bgr_dup,
 };
 
 static int vga_get_bpp(VGAState *s)
@@ -1252,7 +1368,7 @@ static int vga_get_bpp(VGAState *s)
 #ifdef CONFIG_BOCHS_VBE
     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
-    } else 
+    } else
 #endif
     {
         ret = 0;
@@ -1263,12 +1379,20 @@ static int vga_get_bpp(VGAState *s)
 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
 {
     int width, height;
-    
-    width = (s->cr[0x01] + 1) * 8;
-    height = s->cr[0x12] | 
-        ((s->cr[0x07] & 0x02) << 7) | 
-        ((s->cr[0x07] & 0x40) << 3);
-    height = (height + 1);
+   
+#ifdef CONFIG_BOCHS_VBE
+    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
+        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
+        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
+    } else
+#endif
+    {
+        width = (s->cr[0x01] + 1) * 8;
+        height = s->cr[0x12] |
+            ((s->cr[0x07] & 0x02) << 7) |
+            ((s->cr[0x07] & 0x40) << 3);
+        height = (height + 1);
+    }
     *pwidth = width;
     *pheight = height;
 }
@@ -1285,7 +1409,7 @@ void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
     }
 }
 
-/* 
+/*
  * graphic modes
  */
 static void vga_draw_graphic(VGAState *s, int full_update)
@@ -1296,7 +1420,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
     uint8_t *d;
     uint32_t v, addr1, addr;
     vga_draw_line_func *vga_draw_line;
-    
+   
     full_update |= update_basic_params(s);
 
     s->get_resolution(s, &width, &height);
@@ -1318,7 +1442,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
         s->shift_control = shift_control;
         s->double_scan = double_scan;
     }
-    
+   
     if (shift_control == 0) {
         full_update |= update_palette16(s);
         if (s->sr[0x01] & 8) {
@@ -1360,7 +1484,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
             break;
         }
     }
-    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
+    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
 
     if (disp_width != s->last_width ||
         height != s->last_height) {
@@ -1373,7 +1497,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
     }
     if (s->cursor_invalidate)
         s->cursor_invalidate(s);
-    
+   
     line_offset = s->line_offset;
 #if 0
     printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
@@ -1400,12 +1524,12 @@ static void vga_draw_graphic(VGAState *s, int full_update)
         }
         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
-        update = full_update | 
+        update = full_update |
             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
         if ((page1 - page0) > TARGET_PAGE_SIZE) {
             /* if wide line, can use another page */
-            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE, 
+            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
                                                     VGA_DIRTY_FLAG);
         }
         /* explicit invalidation for the hardware cursor */
@@ -1423,7 +1547,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
         } else {
             if (y_start >= 0) {
                 /* flush to display */
-                dpy_update(s->ds, 0, y_start, 
+                dpy_update(s->ds, 0, y_start,
                            disp_width, y - y_start);
                 y_start = -1;
             }
@@ -1444,7 +1568,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
     }
     if (y_start >= 0) {
         /* flush to display */
-        dpy_update(s->ds, 0, y_start, 
+        dpy_update(s->ds, 0, y_start,
                    disp_width, y - y_start);
     }
     /* reset modified pages */
@@ -1464,7 +1588,7 @@ static void vga_draw_blank(VGAState *s, int full_update)
         return;
     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
         return;
-    if (s->ds->depth == 8) 
+    if (s->ds->depth == 8)
         val = s->rgb_to_pixel(0, 0, 0);
     else
         val = 0;
@@ -1474,38 +1598,25 @@ static void vga_draw_blank(VGAState *s, int full_update)
         memset(d, val, w);
         d += s->ds->linesize;
     }
-    dpy_update(s->ds, 0, 0, 
+    dpy_update(s->ds, 0, 0,
                s->last_scr_width, s->last_scr_height);
 }
 
 #define GMODE_TEXT     0
 #define GMODE_GRAPH    1
-#define GMODE_BLANK 2 
+#define GMODE_BLANK 2
 
-void vga_update_display(void)
+static void vga_update_display(void *opaque)
 {
-    VGAState *s = vga_state;
+    VGAState *s = (VGAState *)opaque;
     int full_update, graphic_mode;
 
     if (s->ds->depth == 0) {
         /* nothing to do */
     } else {
-        switch(s->ds->depth) {
-        case 8:
-            s->rgb_to_pixel = rgb_to_pixel8_dup;
-            break;
-        case 15:
-            s->rgb_to_pixel = rgb_to_pixel15_dup;
-            break;
-        default:
-        case 16:
-            s->rgb_to_pixel = rgb_to_pixel16_dup;
-            break;
-        case 32:
-            s->rgb_to_pixel = rgb_to_pixel32_dup;
-            break;
-        }
-        
+        s->rgb_to_pixel =
+            rgb_to_pixel_dup_table[get_depth_index(s->ds)];
+       
         full_update = 0;
         if (!(s->ar_index & 0x20)) {
             graphic_mode = GMODE_BLANK;
@@ -1532,10 +1643,10 @@ void vga_update_display(void)
 }
 
 /* force a full display refresh */
-void vga_invalidate_display(void)
+static void vga_invalidate_display(void *opaque)
 {
-    VGAState *s = vga_state;
-    
+    VGAState *s = (VGAState *)opaque;
+   
     s->last_width = -1;
     s->last_height = -1;
 }
@@ -1563,6 +1674,9 @@ static void vga_save(QEMUFile *f, void *opaque)
     VGAState *s = opaque;
     int i;
 
+    if (s->pci_dev)
+        pci_device_save(s->pci_dev, f);
+
     qemu_put_be32s(f, &s->latch);
     qemu_put_8s(f, &s->sr_index);
     qemu_put_buffer(f, s->sr, 8);
@@ -1602,11 +1716,17 @@ static void vga_save(QEMUFile *f, void *opaque)
 static int vga_load(QEMUFile *f, void *opaque, int version_id)
 {
     VGAState *s = opaque;
-    int is_vbe, i;
+    int is_vbe, i, ret;
 
-    if (version_id != 1)
+    if (version_id > 2)
         return -EINVAL;
 
+    if (s->pci_dev && version_id >= 2) {
+        ret = pci_device_load(s->pci_dev, f);
+        if (ret < 0)
+            return ret;
+    }
+
     qemu_get_be32s(f, &s->latch);
     qemu_get_8s(f, &s->sr_index);
     qemu_get_buffer(f, s->sr, 8);
@@ -1650,15 +1770,24 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void vga_map(PCIDevice *pci_dev, int region_num, 
+typedef struct PCIVGAState {
+    PCIDevice dev;
+    VGAState vga_state;
+} PCIVGAState;
+
+static void vga_map(PCIDevice *pci_dev, int region_num,
                     uint32_t addr, uint32_t size, int type)
 {
-    VGAState *s = vga_state;
-
-    cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
+    PCIVGAState *d = (PCIVGAState *)pci_dev;
+    VGAState *s = &d->vga_state;
+    if (region_num == PCI_ROM_SLOT) {
+        cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
+    } else {
+        cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
+    }
 }
 
-void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
+void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
                      unsigned long vga_ram_offset, int vga_ram_size)
 {
     int i, j, v, b;
@@ -1695,23 +1824,17 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
     s->get_bpp = vga_get_bpp;
     s->get_offsets = vga_get_offsets;
     s->get_resolution = vga_get_resolution;
-    /* XXX: currently needed for display */
-    vga_state = s;
+    s->update = vga_update_display;
+    s->invalidate = vga_invalidate_display;
+    s->screen_dump = vga_screen_dump;
 }
 
-
-int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
-                   unsigned long vga_ram_offset, int vga_ram_size)
+/* used by both ISA and PCI */
+void vga_init(VGAState *s)
 {
-    VGAState *s;
+    int vga_io_memory;
 
-    s = qemu_mallocz(sizeof(VGAState));
-    if (!s)
-        return -1;
-
-    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
-
-    register_savevm("vga", 0, 1, vga_save, vga_load, s);
+    register_savevm("vga", 0, 2, vga_save, vga_load, s);
 
     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
 
@@ -1743,7 +1866,7 @@ int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
 
     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
-    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
+    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
 #else
     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
@@ -1754,34 +1877,175 @@ int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
 #endif /* CONFIG_BOCHS_VBE */
 
     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
-    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
+    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
                                  vga_io_memory);
+}
+
+/* Memory mapped interface */
+static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
+{
+    VGAState *s = opaque;
+
+    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
+}
+
+static void vga_mm_writeb (void *opaque,
+                           target_phys_addr_t addr, uint32_t value)
+{
+    VGAState *s = opaque;
+
+    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
+}
+
+static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
+{
+    VGAState *s = opaque;
+
+    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
+}
+
+static void vga_mm_writew (void *opaque,
+                           target_phys_addr_t addr, uint32_t value)
+{
+    VGAState *s = opaque;
+
+    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
+}
+
+static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
+{
+    VGAState *s = opaque;
+
+    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
+}
+
+static void vga_mm_writel (void *opaque,
+                           target_phys_addr_t addr, uint32_t value)
+{
+    VGAState *s = opaque;
+
+    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
+}
+
+static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
+    &vga_mm_readb,
+    &vga_mm_readw,
+    &vga_mm_readl,
+};
+
+static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
+    &vga_mm_writeb,
+    &vga_mm_writew,
+    &vga_mm_writel,
+};
+
+static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
+                        target_phys_addr_t ctrl_base, int it_shift)
+{
+    int s_ioport_ctrl, vga_io_memory;
+
+    s->base_ctrl = ctrl_base;
+    s->it_shift = it_shift;
+    s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
+    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
+
+    register_savevm("vga", 0, 2, vga_save, vga_load, s);
+
+    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
+    s->bank_offset = 0;
+    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
+}
+
+int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
+                 unsigned long vga_ram_offset, int vga_ram_size)
+{
+    VGAState *s;
+
+    s = qemu_mallocz(sizeof(VGAState));
+    if (!s)
+        return -1;
+
+    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+    vga_init(s);
+
+    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
 
-    if (bus) {
-        PCIDevice *d;
-        uint8_t *pci_conf;
-
-        d = pci_register_device(bus, "VGA", 
-                                sizeof(PCIDevice),
-                                -1, NULL, NULL);
-        pci_conf = d->config;
-        pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
-        pci_conf[0x01] = 0x12;
-        pci_conf[0x02] = 0x11;
-        pci_conf[0x03] = 0x11;
-        pci_conf[0x0a] = 0x00; // VGA controller 
-        pci_conf[0x0b] = 0x03;
-        pci_conf[0x0e] = 0x00; // header_type
-
-        /* XXX: vga_ram_size must be a power of two */
-        pci_register_io_region(d, 0, vga_ram_size, 
-                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
-    } else {
 #ifdef CONFIG_BOCHS_VBE
-        /* XXX: use optimized standard vga accesses */
-        cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
-                                     vga_ram_size, vga_ram_offset);
+    /* XXX: use optimized standard vga accesses */
+    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
+                                 vga_ram_size, vga_ram_offset);
 #endif
+    return 0;
+}
+
+int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
+                    unsigned long vga_ram_offset, int vga_ram_size,
+                    target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
+                    int it_shift)
+{
+    VGAState *s;
+
+    s = qemu_mallocz(sizeof(VGAState));
+    if (!s)
+        return -1;
+
+    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+    vga_mm_init(s, vram_base, ctrl_base, it_shift);
+
+    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+
+#ifdef CONFIG_BOCHS_VBE
+    /* XXX: use optimized standard vga accesses */
+    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
+                                 vga_ram_size, vga_ram_offset);
+#endif
+    return 0;
+}
+
+int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+                 unsigned long vga_ram_offset, int vga_ram_size,
+                 unsigned long vga_bios_offset, int vga_bios_size)
+{
+    PCIVGAState *d;
+    VGAState *s;
+    uint8_t *pci_conf;
+   
+    d = (PCIVGAState *)pci_register_device(bus, "VGA",
+                                           sizeof(PCIVGAState),
+                                           -1, NULL, NULL);
+    if (!d)
+        return -1;
+    s = &d->vga_state;
+   
+    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+    vga_init(s);
+
+    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
+
+    s->pci_dev = &d->dev;
+   
+    pci_conf = d->dev.config;
+    pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
+    pci_conf[0x01] = 0x12;
+    pci_conf[0x02] = 0x11;
+    pci_conf[0x03] = 0x11;
+    pci_conf[0x0a] = 0x00; // VGA controller
+    pci_conf[0x0b] = 0x03;
+    pci_conf[0x0e] = 0x00; // header_type
+   
+    /* XXX: vga_ram_size must be a power of two */
+    pci_register_io_region(&d->dev, 0, vga_ram_size,
+                           PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+    if (vga_bios_size != 0) {
+        unsigned int bios_total_size;
+        s->bios_offset = vga_bios_offset;
+        s->bios_size = vga_bios_size;
+        /* must be a power of two */
+        bios_total_size = 1;
+        while (bios_total_size < vga_bios_size)
+            bios_total_size <<= 1;
+        pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
+                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
     }
     return 0;
 }
@@ -1791,7 +2055,7 @@ int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
 
 static int vga_save_w, vga_save_h;
 
-static void vga_save_dpy_update(DisplayState *s, 
+static void vga_save_dpy_update(DisplayState *s,
                                 int x, int y, int w, int h)
 {
 }
@@ -1808,8 +2072,8 @@ static void vga_save_dpy_refresh(DisplayState *s)
 {
 }
 
-static int ppm_save(const char *filename, uint8_t *data, 
-                    int w, int h, int linesize)
+int ppm_save(const char *filename, uint8_t *data,
+             int w, int h, int linesize)
 {
     FILE *f;
     uint8_t *d, *d1;
@@ -1839,13 +2103,13 @@ static int ppm_save(const char *filename, uint8_t *data,
 
 /* save the vga display in a PPM image even if no display is
    available */
-void vga_screen_dump(const char *filename)
+static void vga_screen_dump(void *opaque, const char *filename)
 {
-    VGAState *s = vga_state;
+    VGAState *s = (VGAState *)opaque;
     DisplayState *saved_ds, ds1, *ds = &ds1;
-    
+   
     /* XXX: this is a little hackish */
-    vga_invalidate_display();
+    vga_invalidate_display(s);
     saved_ds = s->ds;
 
     memset(ds, 0, sizeof(DisplayState));
@@ -1856,10 +2120,10 @@ void vga_screen_dump(const char *filename)
 
     s->ds = ds;
     s->graphic_mode = -1;
-    vga_update_display();
-    
+    vga_update_display(s);
+   
     if (ds->data) {
-        ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
+        ppm_save(filename, ds->data, vga_save_w, vga_save_h,
                  s->ds->linesize);
         qemu_free(ds->data);
     }
This page took 0.058632 seconds and 4 git commands to generate.