symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/vga.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * QEMU VGA Emulator.
       
     3  *
       
     4  * Copyright (c) 2003 Fabrice Bellard
       
     5  *
       
     6  * Permission is hereby granted, free of charge, to any person obtaining a copy
       
     7  * of this software and associated documentation files (the "Software"), to deal
       
     8  * in the Software without restriction, including without limitation the rights
       
     9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
    10  * copies of the Software, and to permit persons to whom the Software is
       
    11  * furnished to do so, subject to the following conditions:
       
    12  *
       
    13  * The above copyright notice and this permission notice shall be included in
       
    14  * all copies or substantial portions of the Software.
       
    15  *
       
    16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
       
    19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       
    22  * THE SOFTWARE.
       
    23  */
       
    24 #include "hw.h"
       
    25 #include "console.h"
       
    26 #include "pc.h"
       
    27 #include "pci.h"
       
    28 #include "vga_int.h"
       
    29 #include "pixel_ops.h"
       
    30 #include "qemu-timer.h"
       
    31 #include "kvm.h"
       
    32 
       
    33 //#define DEBUG_VGA
       
    34 //#define DEBUG_VGA_MEM
       
    35 //#define DEBUG_VGA_REG
       
    36 
       
    37 //#define DEBUG_BOCHS_VBE
       
    38 
       
    39 /* force some bits to zero */
       
    40 const uint8_t sr_mask[8] = {
       
    41     (uint8_t)~0xfc,
       
    42     (uint8_t)~0xc2,
       
    43     (uint8_t)~0xf0,
       
    44     (uint8_t)~0xc0,
       
    45     (uint8_t)~0xf1,
       
    46     (uint8_t)~0xff,
       
    47     (uint8_t)~0xff,
       
    48     (uint8_t)~0x00,
       
    49 };
       
    50 
       
    51 const uint8_t gr_mask[16] = {
       
    52     (uint8_t)~0xf0, /* 0x00 */
       
    53     (uint8_t)~0xf0, /* 0x01 */
       
    54     (uint8_t)~0xf0, /* 0x02 */
       
    55     (uint8_t)~0xe0, /* 0x03 */
       
    56     (uint8_t)~0xfc, /* 0x04 */
       
    57     (uint8_t)~0x84, /* 0x05 */
       
    58     (uint8_t)~0xf0, /* 0x06 */
       
    59     (uint8_t)~0xf0, /* 0x07 */
       
    60     (uint8_t)~0x00, /* 0x08 */
       
    61     (uint8_t)~0xff, /* 0x09 */
       
    62     (uint8_t)~0xff, /* 0x0a */
       
    63     (uint8_t)~0xff, /* 0x0b */
       
    64     (uint8_t)~0xff, /* 0x0c */
       
    65     (uint8_t)~0xff, /* 0x0d */
       
    66     (uint8_t)~0xff, /* 0x0e */
       
    67     (uint8_t)~0xff, /* 0x0f */
       
    68 };
       
    69 
       
    70 #define cbswap_32(__x) \
       
    71 ((uint32_t)( \
       
    72 		(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
       
    73 		(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
       
    74 		(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
       
    75 		(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
       
    76 
       
    77 #ifdef WORDS_BIGENDIAN
       
    78 #define PAT(x) cbswap_32(x)
       
    79 #else
       
    80 #define PAT(x) (x)
       
    81 #endif
       
    82 
       
    83 #ifdef WORDS_BIGENDIAN
       
    84 #define BIG 1
       
    85 #else
       
    86 #define BIG 0
       
    87 #endif
       
    88 
       
    89 #ifdef WORDS_BIGENDIAN
       
    90 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
       
    91 #else
       
    92 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
       
    93 #endif
       
    94 
       
    95 static const uint32_t mask16[16] = {
       
    96     PAT(0x00000000),
       
    97     PAT(0x000000ff),
       
    98     PAT(0x0000ff00),
       
    99     PAT(0x0000ffff),
       
   100     PAT(0x00ff0000),
       
   101     PAT(0x00ff00ff),
       
   102     PAT(0x00ffff00),
       
   103     PAT(0x00ffffff),
       
   104     PAT(0xff000000),
       
   105     PAT(0xff0000ff),
       
   106     PAT(0xff00ff00),
       
   107     PAT(0xff00ffff),
       
   108     PAT(0xffff0000),
       
   109     PAT(0xffff00ff),
       
   110     PAT(0xffffff00),
       
   111     PAT(0xffffffff),
       
   112 };
       
   113 
       
   114 #undef PAT
       
   115 
       
   116 #ifdef WORDS_BIGENDIAN
       
   117 #define PAT(x) (x)
       
   118 #else
       
   119 #define PAT(x) cbswap_32(x)
       
   120 #endif
       
   121 
       
   122 static const uint32_t dmask16[16] = {
       
   123     PAT(0x00000000),
       
   124     PAT(0x000000ff),
       
   125     PAT(0x0000ff00),
       
   126     PAT(0x0000ffff),
       
   127     PAT(0x00ff0000),
       
   128     PAT(0x00ff00ff),
       
   129     PAT(0x00ffff00),
       
   130     PAT(0x00ffffff),
       
   131     PAT(0xff000000),
       
   132     PAT(0xff0000ff),
       
   133     PAT(0xff00ff00),
       
   134     PAT(0xff00ffff),
       
   135     PAT(0xffff0000),
       
   136     PAT(0xffff00ff),
       
   137     PAT(0xffffff00),
       
   138     PAT(0xffffffff),
       
   139 };
       
   140 
       
   141 static const uint32_t dmask4[4] = {
       
   142     PAT(0x00000000),
       
   143     PAT(0x0000ffff),
       
   144     PAT(0xffff0000),
       
   145     PAT(0xffffffff),
       
   146 };
       
   147 
       
   148 static uint32_t expand4[256];
       
   149 static uint16_t expand2[256];
       
   150 static uint8_t expand4to8[16];
       
   151 
       
   152 static void vga_screen_dump(void *opaque, const char *filename);
       
   153 
       
   154 static void vga_dumb_update_retrace_info(VGAState *s)
       
   155 {
       
   156     (void) s;
       
   157 }
       
   158 
       
   159 static void vga_precise_update_retrace_info(VGAState *s)
       
   160 {
       
   161     int htotal_chars;
       
   162     int hretr_start_char;
       
   163     int hretr_skew_chars;
       
   164     int hretr_end_char;
       
   165 
       
   166     int vtotal_lines;
       
   167     int vretr_start_line;
       
   168     int vretr_end_line;
       
   169 
       
   170     int div2, sldiv2, dots;
       
   171     int clocking_mode;
       
   172     int clock_sel;
       
   173     const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
       
   174     int64_t chars_per_sec;
       
   175     struct vga_precise_retrace *r = &s->retrace_info.precise;
       
   176 
       
   177     htotal_chars = s->cr[0x00] + 5;
       
   178     hretr_start_char = s->cr[0x04];
       
   179     hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
       
   180     hretr_end_char = s->cr[0x05] & 0x1f;
       
   181 
       
   182     vtotal_lines = (s->cr[0x06]
       
   183                     | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
       
   184         ;
       
   185     vretr_start_line = s->cr[0x10]
       
   186         | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
       
   187         ;
       
   188     vretr_end_line = s->cr[0x11] & 0xf;
       
   189 
       
   190 
       
   191     div2 = (s->cr[0x17] >> 2) & 1;
       
   192     sldiv2 = (s->cr[0x17] >> 3) & 1;
       
   193 
       
   194     clocking_mode = (s->sr[0x01] >> 3) & 1;
       
   195     clock_sel = (s->msr >> 2) & 3;
       
   196     dots = (s->msr & 1) ? 8 : 9;
       
   197 
       
   198     chars_per_sec = clk_hz[clock_sel] / dots;
       
   199 
       
   200     htotal_chars <<= clocking_mode;
       
   201 
       
   202     r->total_chars = vtotal_lines * htotal_chars;
       
   203     if (r->freq) {
       
   204         r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
       
   205     } else {
       
   206         r->ticks_per_char = ticks_per_sec / chars_per_sec;
       
   207     }
       
   208 
       
   209     r->vstart = vretr_start_line;
       
   210     r->vend = r->vstart + vretr_end_line + 1;
       
   211 
       
   212     r->hstart = hretr_start_char + hretr_skew_chars;
       
   213     r->hend = r->hstart + hretr_end_char + 1;
       
   214     r->htotal = htotal_chars;
       
   215 
       
   216 #if 0
       
   217     printf (
       
   218         "hz=%f\n"
       
   219         "htotal = %d\n"
       
   220         "hretr_start = %d\n"
       
   221         "hretr_skew = %d\n"
       
   222         "hretr_end = %d\n"
       
   223         "vtotal = %d\n"
       
   224         "vretr_start = %d\n"
       
   225         "vretr_end = %d\n"
       
   226         "div2 = %d sldiv2 = %d\n"
       
   227         "clocking_mode = %d\n"
       
   228         "clock_sel = %d %d\n"
       
   229         "dots = %d\n"
       
   230         "ticks/char = %lld\n"
       
   231         "\n",
       
   232         (double) ticks_per_sec / (r->ticks_per_char * r->total_chars),
       
   233         htotal_chars,
       
   234         hretr_start_char,
       
   235         hretr_skew_chars,
       
   236         hretr_end_char,
       
   237         vtotal_lines,
       
   238         vretr_start_line,
       
   239         vretr_end_line,
       
   240         div2, sldiv2,
       
   241         clocking_mode,
       
   242         clock_sel,
       
   243         clk_hz[clock_sel],
       
   244         dots,
       
   245         r->ticks_per_char
       
   246         );
       
   247 #endif
       
   248 }
       
   249 
       
   250 static uint8_t vga_precise_retrace(VGAState *s)
       
   251 {
       
   252     struct vga_precise_retrace *r = &s->retrace_info.precise;
       
   253     uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
       
   254 
       
   255     if (r->total_chars) {
       
   256         int cur_line, cur_line_char, cur_char;
       
   257         int64_t cur_tick;
       
   258 
       
   259         cur_tick = qemu_get_clock(vm_clock);
       
   260 
       
   261         cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
       
   262         cur_line = cur_char / r->htotal;
       
   263 
       
   264         if (cur_line >= r->vstart && cur_line <= r->vend) {
       
   265             val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
       
   266         } else {
       
   267             cur_line_char = cur_char % r->htotal;
       
   268             if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
       
   269                 val |= ST01_DISP_ENABLE;
       
   270             }
       
   271         }
       
   272 
       
   273         return val;
       
   274     } else {
       
   275         return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
       
   276     }
       
   277 }
       
   278 
       
   279 static uint8_t vga_dumb_retrace(VGAState *s)
       
   280 {
       
   281     return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
       
   282 }
       
   283 
       
   284 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
       
   285 {
       
   286     VGAState *s = opaque;
       
   287     int val, index;
       
   288 
       
   289     /* check port range access depending on color/monochrome mode */
       
   290     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
       
   291         (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
       
   292         val = 0xff;
       
   293     } else {
       
   294         switch(addr) {
       
   295         case 0x3c0:
       
   296             if (s->ar_flip_flop == 0) {
       
   297                 val = s->ar_index;
       
   298             } else {
       
   299                 val = 0;
       
   300             }
       
   301             break;
       
   302         case 0x3c1:
       
   303             index = s->ar_index & 0x1f;
       
   304             if (index < 21)
       
   305                 val = s->ar[index];
       
   306             else
       
   307                 val = 0;
       
   308             break;
       
   309         case 0x3c2:
       
   310             val = s->st00;
       
   311             break;
       
   312         case 0x3c4:
       
   313             val = s->sr_index;
       
   314             break;
       
   315         case 0x3c5:
       
   316             val = s->sr[s->sr_index];
       
   317 #ifdef DEBUG_VGA_REG
       
   318             printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
       
   319 #endif
       
   320             break;
       
   321         case 0x3c7:
       
   322             val = s->dac_state;
       
   323             break;
       
   324 	case 0x3c8:
       
   325 	    val = s->dac_write_index;
       
   326 	    break;
       
   327         case 0x3c9:
       
   328             val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
       
   329             if (++s->dac_sub_index == 3) {
       
   330                 s->dac_sub_index = 0;
       
   331                 s->dac_read_index++;
       
   332             }
       
   333             break;
       
   334         case 0x3ca:
       
   335             val = s->fcr;
       
   336             break;
       
   337         case 0x3cc:
       
   338             val = s->msr;
       
   339             break;
       
   340         case 0x3ce:
       
   341             val = s->gr_index;
       
   342             break;
       
   343         case 0x3cf:
       
   344             val = s->gr[s->gr_index];
       
   345 #ifdef DEBUG_VGA_REG
       
   346             printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
       
   347 #endif
       
   348             break;
       
   349         case 0x3b4:
       
   350         case 0x3d4:
       
   351             val = s->cr_index;
       
   352             break;
       
   353         case 0x3b5:
       
   354         case 0x3d5:
       
   355             val = s->cr[s->cr_index];
       
   356 #ifdef DEBUG_VGA_REG
       
   357             printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
       
   358 #endif
       
   359             break;
       
   360         case 0x3ba:
       
   361         case 0x3da:
       
   362             /* just toggle to fool polling */
       
   363             val = s->st01 = s->retrace(s);
       
   364             s->ar_flip_flop = 0;
       
   365             break;
       
   366         default:
       
   367             val = 0x00;
       
   368             break;
       
   369         }
       
   370     }
       
   371 #if defined(DEBUG_VGA)
       
   372     printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
       
   373 #endif
       
   374     return val;
       
   375 }
       
   376 
       
   377 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
       
   378 {
       
   379     VGAState *s = opaque;
       
   380     int index;
       
   381 
       
   382     /* check port range access depending on color/monochrome mode */
       
   383     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
       
   384         (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
       
   385         return;
       
   386 
       
   387 #ifdef DEBUG_VGA
       
   388     printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
       
   389 #endif
       
   390 
       
   391     switch(addr) {
       
   392     case 0x3c0:
       
   393         if (s->ar_flip_flop == 0) {
       
   394             val &= 0x3f;
       
   395             s->ar_index = val;
       
   396         } else {
       
   397             index = s->ar_index & 0x1f;
       
   398             switch(index) {
       
   399             case 0x00 ... 0x0f:
       
   400                 s->ar[index] = val & 0x3f;
       
   401                 break;
       
   402             case 0x10:
       
   403                 s->ar[index] = val & ~0x10;
       
   404                 break;
       
   405             case 0x11:
       
   406                 s->ar[index] = val;
       
   407                 break;
       
   408             case 0x12:
       
   409                 s->ar[index] = val & ~0xc0;
       
   410                 break;
       
   411             case 0x13:
       
   412                 s->ar[index] = val & ~0xf0;
       
   413                 break;
       
   414             case 0x14:
       
   415                 s->ar[index] = val & ~0xf0;
       
   416                 break;
       
   417             default:
       
   418                 break;
       
   419             }
       
   420         }
       
   421         s->ar_flip_flop ^= 1;
       
   422         break;
       
   423     case 0x3c2:
       
   424         s->msr = val & ~0x10;
       
   425         s->update_retrace_info(s);
       
   426         break;
       
   427     case 0x3c4:
       
   428         s->sr_index = val & 7;
       
   429         break;
       
   430     case 0x3c5:
       
   431 #ifdef DEBUG_VGA_REG
       
   432         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
       
   433 #endif
       
   434         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
       
   435         if (s->sr_index == 1) s->update_retrace_info(s);
       
   436         break;
       
   437     case 0x3c7:
       
   438         s->dac_read_index = val;
       
   439         s->dac_sub_index = 0;
       
   440         s->dac_state = 3;
       
   441         break;
       
   442     case 0x3c8:
       
   443         s->dac_write_index = val;
       
   444         s->dac_sub_index = 0;
       
   445         s->dac_state = 0;
       
   446         break;
       
   447     case 0x3c9:
       
   448         s->dac_cache[s->dac_sub_index] = val;
       
   449         if (++s->dac_sub_index == 3) {
       
   450             memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
       
   451             s->dac_sub_index = 0;
       
   452             s->dac_write_index++;
       
   453         }
       
   454         break;
       
   455     case 0x3ce:
       
   456         s->gr_index = val & 0x0f;
       
   457         break;
       
   458     case 0x3cf:
       
   459 #ifdef DEBUG_VGA_REG
       
   460         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
       
   461 #endif
       
   462         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
       
   463         break;
       
   464     case 0x3b4:
       
   465     case 0x3d4:
       
   466         s->cr_index = val;
       
   467         break;
       
   468     case 0x3b5:
       
   469     case 0x3d5:
       
   470 #ifdef DEBUG_VGA_REG
       
   471         printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
       
   472 #endif
       
   473         /* handle CR0-7 protection */
       
   474         if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
       
   475             /* can always write bit 4 of CR7 */
       
   476             if (s->cr_index == 7)
       
   477                 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
       
   478             return;
       
   479         }
       
   480         switch(s->cr_index) {
       
   481         case 0x01: /* horizontal display end */
       
   482         case 0x07:
       
   483         case 0x09:
       
   484         case 0x0c:
       
   485         case 0x0d:
       
   486         case 0x12: /* vertical display end */
       
   487             s->cr[s->cr_index] = val;
       
   488             break;
       
   489         default:
       
   490             s->cr[s->cr_index] = val;
       
   491             break;
       
   492         }
       
   493 
       
   494         switch(s->cr_index) {
       
   495         case 0x00:
       
   496         case 0x04:
       
   497         case 0x05:
       
   498         case 0x06:
       
   499         case 0x07:
       
   500         case 0x11:
       
   501         case 0x17:
       
   502             s->update_retrace_info(s);
       
   503             break;
       
   504         }
       
   505         break;
       
   506     case 0x3ba:
       
   507     case 0x3da:
       
   508         s->fcr = val & 0x10;
       
   509         break;
       
   510     }
       
   511 }
       
   512 
       
   513 #ifdef CONFIG_BOCHS_VBE
       
   514 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
       
   515 {
       
   516     VGAState *s = opaque;
       
   517     uint32_t val;
       
   518     val = s->vbe_index;
       
   519     return val;
       
   520 }
       
   521 
       
   522 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
       
   523 {
       
   524     VGAState *s = opaque;
       
   525     uint32_t val;
       
   526 
       
   527     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
       
   528         if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
       
   529             switch(s->vbe_index) {
       
   530                 /* XXX: do not hardcode ? */
       
   531             case VBE_DISPI_INDEX_XRES:
       
   532                 val = VBE_DISPI_MAX_XRES;
       
   533                 break;
       
   534             case VBE_DISPI_INDEX_YRES:
       
   535                 val = VBE_DISPI_MAX_YRES;
       
   536                 break;
       
   537             case VBE_DISPI_INDEX_BPP:
       
   538                 val = VBE_DISPI_MAX_BPP;
       
   539                 break;
       
   540             default:
       
   541                 val = s->vbe_regs[s->vbe_index];
       
   542                 break;
       
   543             }
       
   544         } else {
       
   545             val = s->vbe_regs[s->vbe_index];
       
   546         }
       
   547     } else {
       
   548         val = 0;
       
   549     }
       
   550 #ifdef DEBUG_BOCHS_VBE
       
   551     printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
       
   552 #endif
       
   553     return val;
       
   554 }
       
   555 
       
   556 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
       
   557 {
       
   558     VGAState *s = opaque;
       
   559     s->vbe_index = val;
       
   560 }
       
   561 
       
   562 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
       
   563 {
       
   564     VGAState *s = opaque;
       
   565 
       
   566     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
       
   567 #ifdef DEBUG_BOCHS_VBE
       
   568         printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
       
   569 #endif
       
   570         switch(s->vbe_index) {
       
   571         case VBE_DISPI_INDEX_ID:
       
   572             if (val == VBE_DISPI_ID0 ||
       
   573                 val == VBE_DISPI_ID1 ||
       
   574                 val == VBE_DISPI_ID2 ||
       
   575                 val == VBE_DISPI_ID3 ||
       
   576                 val == VBE_DISPI_ID4) {
       
   577                 s->vbe_regs[s->vbe_index] = val;
       
   578             }
       
   579             break;
       
   580         case VBE_DISPI_INDEX_XRES:
       
   581             if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
       
   582                 s->vbe_regs[s->vbe_index] = val;
       
   583             }
       
   584             break;
       
   585         case VBE_DISPI_INDEX_YRES:
       
   586             if (val <= VBE_DISPI_MAX_YRES) {
       
   587                 s->vbe_regs[s->vbe_index] = val;
       
   588             }
       
   589             break;
       
   590         case VBE_DISPI_INDEX_BPP:
       
   591             if (val == 0)
       
   592                 val = 8;
       
   593             if (val == 4 || val == 8 || val == 15 ||
       
   594                 val == 16 || val == 24 || val == 32) {
       
   595                 s->vbe_regs[s->vbe_index] = val;
       
   596             }
       
   597             break;
       
   598         case VBE_DISPI_INDEX_BANK:
       
   599             if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
       
   600               val &= (s->vbe_bank_mask >> 2);
       
   601             } else {
       
   602               val &= s->vbe_bank_mask;
       
   603             }
       
   604             s->vbe_regs[s->vbe_index] = val;
       
   605             s->bank_offset = (val << 16);
       
   606             break;
       
   607         case VBE_DISPI_INDEX_ENABLE:
       
   608             if ((val & VBE_DISPI_ENABLED) &&
       
   609                 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
       
   610                 int h, shift_control;
       
   611 
       
   612                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
       
   613                     s->vbe_regs[VBE_DISPI_INDEX_XRES];
       
   614                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
       
   615                     s->vbe_regs[VBE_DISPI_INDEX_YRES];
       
   616                 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
       
   617                 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
       
   618 
       
   619                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
       
   620                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
       
   621                 else
       
   622                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
       
   623                         ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
       
   624                 s->vbe_start_addr = 0;
       
   625 
       
   626                 /* clear the screen (should be done in BIOS) */
       
   627                 if (!(val & VBE_DISPI_NOCLEARMEM)) {
       
   628                     memset(s->vram_ptr, 0,
       
   629                            s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
       
   630                 }
       
   631 
       
   632                 /* we initialize the VGA graphic mode (should be done
       
   633                    in BIOS) */
       
   634                 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
       
   635                 s->cr[0x17] |= 3; /* no CGA modes */
       
   636                 s->cr[0x13] = s->vbe_line_offset >> 3;
       
   637                 /* width */
       
   638                 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
       
   639                 /* height (only meaningful if < 1024) */
       
   640                 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
       
   641                 s->cr[0x12] = h;
       
   642                 s->cr[0x07] = (s->cr[0x07] & ~0x42) |
       
   643                     ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
       
   644                 /* line compare to 1023 */
       
   645                 s->cr[0x18] = 0xff;
       
   646                 s->cr[0x07] |= 0x10;
       
   647                 s->cr[0x09] |= 0x40;
       
   648 
       
   649                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
       
   650                     shift_control = 0;
       
   651                     s->sr[0x01] &= ~8; /* no double line */
       
   652                 } else {
       
   653                     shift_control = 2;
       
   654                     s->sr[4] |= 0x08; /* set chain 4 mode */
       
   655                     s->sr[2] |= 0x0f; /* activate all planes */
       
   656                 }
       
   657                 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
       
   658                 s->cr[0x09] &= ~0x9f; /* no double scan */
       
   659             } else {
       
   660                 /* XXX: the bios should do that */
       
   661                 s->bank_offset = 0;
       
   662             }
       
   663             s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
       
   664             s->vbe_regs[s->vbe_index] = val;
       
   665             break;
       
   666         case VBE_DISPI_INDEX_VIRT_WIDTH:
       
   667             {
       
   668                 int w, h, line_offset;
       
   669 
       
   670                 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
       
   671                     return;
       
   672                 w = val;
       
   673                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
       
   674                     line_offset = w >> 1;
       
   675                 else
       
   676                     line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
       
   677                 h = s->vram_size / line_offset;
       
   678                 /* XXX: support weird bochs semantics ? */
       
   679                 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
       
   680                     return;
       
   681                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
       
   682                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
       
   683                 s->vbe_line_offset = line_offset;
       
   684             }
       
   685             break;
       
   686         case VBE_DISPI_INDEX_X_OFFSET:
       
   687         case VBE_DISPI_INDEX_Y_OFFSET:
       
   688             {
       
   689                 int x;
       
   690                 s->vbe_regs[s->vbe_index] = val;
       
   691                 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
       
   692                 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
       
   693                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
       
   694                     s->vbe_start_addr += x >> 1;
       
   695                 else
       
   696                     s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
       
   697                 s->vbe_start_addr >>= 2;
       
   698             }
       
   699             break;
       
   700         default:
       
   701             break;
       
   702         }
       
   703     }
       
   704 }
       
   705 #endif
       
   706 
       
   707 /* called for accesses between 0xa0000 and 0xc0000 */
       
   708 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
       
   709 {
       
   710     VGAState *s = opaque;
       
   711     int memory_map_mode, plane;
       
   712     uint32_t ret;
       
   713 
       
   714     /* convert to VGA memory offset */
       
   715     memory_map_mode = (s->gr[6] >> 2) & 3;
       
   716     addr &= 0x1ffff;
       
   717     switch(memory_map_mode) {
       
   718     case 0:
       
   719         break;
       
   720     case 1:
       
   721         if (addr >= 0x10000)
       
   722             return 0xff;
       
   723         addr += s->bank_offset;
       
   724         break;
       
   725     case 2:
       
   726         addr -= 0x10000;
       
   727         if (addr >= 0x8000)
       
   728             return 0xff;
       
   729         break;
       
   730     default:
       
   731     case 3:
       
   732         addr -= 0x18000;
       
   733         if (addr >= 0x8000)
       
   734             return 0xff;
       
   735         break;
       
   736     }
       
   737 
       
   738     if (s->sr[4] & 0x08) {
       
   739         /* chain 4 mode : simplest access */
       
   740         ret = s->vram_ptr[addr];
       
   741     } else if (s->gr[5] & 0x10) {
       
   742         /* odd/even mode (aka text mode mapping) */
       
   743         plane = (s->gr[4] & 2) | (addr & 1);
       
   744         ret = s->vram_ptr[((addr & ~1) << 1) | plane];
       
   745     } else {
       
   746         /* standard VGA latched access */
       
   747         s->latch = ((uint32_t *)s->vram_ptr)[addr];
       
   748 
       
   749         if (!(s->gr[5] & 0x08)) {
       
   750             /* read mode 0 */
       
   751             plane = s->gr[4];
       
   752             ret = GET_PLANE(s->latch, plane);
       
   753         } else {
       
   754             /* read mode 1 */
       
   755             ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
       
   756             ret |= ret >> 16;
       
   757             ret |= ret >> 8;
       
   758             ret = (~ret) & 0xff;
       
   759         }
       
   760     }
       
   761     return ret;
       
   762 }
       
   763 
       
   764 static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
       
   765 {
       
   766     uint32_t v;
       
   767 #ifdef TARGET_WORDS_BIGENDIAN
       
   768     v = vga_mem_readb(opaque, addr) << 8;
       
   769     v |= vga_mem_readb(opaque, addr + 1);
       
   770 #else
       
   771     v = vga_mem_readb(opaque, addr);
       
   772     v |= vga_mem_readb(opaque, addr + 1) << 8;
       
   773 #endif
       
   774     return v;
       
   775 }
       
   776 
       
   777 static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
       
   778 {
       
   779     uint32_t v;
       
   780 #ifdef TARGET_WORDS_BIGENDIAN
       
   781     v = vga_mem_readb(opaque, addr) << 24;
       
   782     v |= vga_mem_readb(opaque, addr + 1) << 16;
       
   783     v |= vga_mem_readb(opaque, addr + 2) << 8;
       
   784     v |= vga_mem_readb(opaque, addr + 3);
       
   785 #else
       
   786     v = vga_mem_readb(opaque, addr);
       
   787     v |= vga_mem_readb(opaque, addr + 1) << 8;
       
   788     v |= vga_mem_readb(opaque, addr + 2) << 16;
       
   789     v |= vga_mem_readb(opaque, addr + 3) << 24;
       
   790 #endif
       
   791     return v;
       
   792 }
       
   793 
       
   794 /* called for accesses between 0xa0000 and 0xc0000 */
       
   795 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
       
   796 {
       
   797     VGAState *s = opaque;
       
   798     int memory_map_mode, plane, write_mode, b, func_select, mask;
       
   799     uint32_t write_mask, bit_mask, set_mask;
       
   800 
       
   801 #ifdef DEBUG_VGA_MEM
       
   802     printf("vga: [0x%x] = 0x%02x\n", addr, val);
       
   803 #endif
       
   804     /* convert to VGA memory offset */
       
   805     memory_map_mode = (s->gr[6] >> 2) & 3;
       
   806     addr &= 0x1ffff;
       
   807     switch(memory_map_mode) {
       
   808     case 0:
       
   809         break;
       
   810     case 1:
       
   811         if (addr >= 0x10000)
       
   812             return;
       
   813         addr += s->bank_offset;
       
   814         break;
       
   815     case 2:
       
   816         addr -= 0x10000;
       
   817         if (addr >= 0x8000)
       
   818             return;
       
   819         break;
       
   820     default:
       
   821     case 3:
       
   822         addr -= 0x18000;
       
   823         if (addr >= 0x8000)
       
   824             return;
       
   825         break;
       
   826     }
       
   827 
       
   828     if (s->sr[4] & 0x08) {
       
   829         /* chain 4 mode : simplest access */
       
   830         plane = addr & 3;
       
   831         mask = (1 << plane);
       
   832         if (s->sr[2] & mask) {
       
   833             s->vram_ptr[addr] = val;
       
   834 #ifdef DEBUG_VGA_MEM
       
   835             printf("vga: chain4: [0x%x]\n", addr);
       
   836 #endif
       
   837             s->plane_updated |= mask; /* only used to detect font change */
       
   838             cpu_physical_memory_set_dirty(s->vram_offset + addr);
       
   839         }
       
   840     } else if (s->gr[5] & 0x10) {
       
   841         /* odd/even mode (aka text mode mapping) */
       
   842         plane = (s->gr[4] & 2) | (addr & 1);
       
   843         mask = (1 << plane);
       
   844         if (s->sr[2] & mask) {
       
   845             addr = ((addr & ~1) << 1) | plane;
       
   846             s->vram_ptr[addr] = val;
       
   847 #ifdef DEBUG_VGA_MEM
       
   848             printf("vga: odd/even: [0x%x]\n", addr);
       
   849 #endif
       
   850             s->plane_updated |= mask; /* only used to detect font change */
       
   851             cpu_physical_memory_set_dirty(s->vram_offset + addr);
       
   852         }
       
   853     } else {
       
   854         /* standard VGA latched access */
       
   855         write_mode = s->gr[5] & 3;
       
   856         switch(write_mode) {
       
   857         default:
       
   858         case 0:
       
   859             /* rotate */
       
   860             b = s->gr[3] & 7;
       
   861             val = ((val >> b) | (val << (8 - b))) & 0xff;
       
   862             val |= val << 8;
       
   863             val |= val << 16;
       
   864 
       
   865             /* apply set/reset mask */
       
   866             set_mask = mask16[s->gr[1]];
       
   867             val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
       
   868             bit_mask = s->gr[8];
       
   869             break;
       
   870         case 1:
       
   871             val = s->latch;
       
   872             goto do_write;
       
   873         case 2:
       
   874             val = mask16[val & 0x0f];
       
   875             bit_mask = s->gr[8];
       
   876             break;
       
   877         case 3:
       
   878             /* rotate */
       
   879             b = s->gr[3] & 7;
       
   880             val = (val >> b) | (val << (8 - b));
       
   881 
       
   882             bit_mask = s->gr[8] & val;
       
   883             val = mask16[s->gr[0]];
       
   884             break;
       
   885         }
       
   886 
       
   887         /* apply logical operation */
       
   888         func_select = s->gr[3] >> 3;
       
   889         switch(func_select) {
       
   890         case 0:
       
   891         default:
       
   892             /* nothing to do */
       
   893             break;
       
   894         case 1:
       
   895             /* and */
       
   896             val &= s->latch;
       
   897             break;
       
   898         case 2:
       
   899             /* or */
       
   900             val |= s->latch;
       
   901             break;
       
   902         case 3:
       
   903             /* xor */
       
   904             val ^= s->latch;
       
   905             break;
       
   906         }
       
   907 
       
   908         /* apply bit mask */
       
   909         bit_mask |= bit_mask << 8;
       
   910         bit_mask |= bit_mask << 16;
       
   911         val = (val & bit_mask) | (s->latch & ~bit_mask);
       
   912 
       
   913     do_write:
       
   914         /* mask data according to sr[2] */
       
   915         mask = s->sr[2];
       
   916         s->plane_updated |= mask; /* only used to detect font change */
       
   917         write_mask = mask16[mask];
       
   918         ((uint32_t *)s->vram_ptr)[addr] =
       
   919             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
       
   920             (val & write_mask);
       
   921 #ifdef DEBUG_VGA_MEM
       
   922             printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
       
   923                    addr * 4, write_mask, val);
       
   924 #endif
       
   925             cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
       
   926     }
       
   927 }
       
   928 
       
   929 static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
       
   930 {
       
   931 #ifdef TARGET_WORDS_BIGENDIAN
       
   932     vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
       
   933     vga_mem_writeb(opaque, addr + 1, val & 0xff);
       
   934 #else
       
   935     vga_mem_writeb(opaque, addr, val & 0xff);
       
   936     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
       
   937 #endif
       
   938 }
       
   939 
       
   940 static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
       
   941 {
       
   942 #ifdef TARGET_WORDS_BIGENDIAN
       
   943     vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
       
   944     vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
       
   945     vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
       
   946     vga_mem_writeb(opaque, addr + 3, val & 0xff);
       
   947 #else
       
   948     vga_mem_writeb(opaque, addr, val & 0xff);
       
   949     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
       
   950     vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
       
   951     vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
       
   952 #endif
       
   953 }
       
   954 
       
   955 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
       
   956                              const uint8_t *font_ptr, int h,
       
   957                              uint32_t fgcol, uint32_t bgcol);
       
   958 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
       
   959                                   const uint8_t *font_ptr, int h,
       
   960                                   uint32_t fgcol, uint32_t bgcol, int dup9);
       
   961 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
       
   962                                 const uint8_t *s, int width);
       
   963 
       
   964 #define DEPTH 8
       
   965 #include "vga_template.h"
       
   966 
       
   967 #define DEPTH 15
       
   968 #include "vga_template.h"
       
   969 
       
   970 #define BGR_FORMAT
       
   971 #define DEPTH 15
       
   972 #include "vga_template.h"
       
   973 
       
   974 #define DEPTH 16
       
   975 #include "vga_template.h"
       
   976 
       
   977 #define BGR_FORMAT
       
   978 #define DEPTH 16
       
   979 #include "vga_template.h"
       
   980 
       
   981 #define DEPTH 32
       
   982 #include "vga_template.h"
       
   983 
       
   984 #define BGR_FORMAT
       
   985 #define DEPTH 32
       
   986 #include "vga_template.h"
       
   987 
       
   988 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
       
   989 {
       
   990     unsigned int col;
       
   991     col = rgb_to_pixel8(r, g, b);
       
   992     col |= col << 8;
       
   993     col |= col << 16;
       
   994     return col;
       
   995 }
       
   996 
       
   997 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
       
   998 {
       
   999     unsigned int col;
       
  1000     col = rgb_to_pixel15(r, g, b);
       
  1001     col |= col << 16;
       
  1002     return col;
       
  1003 }
       
  1004 
       
  1005 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
       
  1006                                           unsigned int b)
       
  1007 {
       
  1008     unsigned int col;
       
  1009     col = rgb_to_pixel15bgr(r, g, b);
       
  1010     col |= col << 16;
       
  1011     return col;
       
  1012 }
       
  1013 
       
  1014 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
       
  1015 {
       
  1016     unsigned int col;
       
  1017     col = rgb_to_pixel16(r, g, b);
       
  1018     col |= col << 16;
       
  1019     return col;
       
  1020 }
       
  1021 
       
  1022 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
       
  1023                                           unsigned int b)
       
  1024 {
       
  1025     unsigned int col;
       
  1026     col = rgb_to_pixel16bgr(r, g, b);
       
  1027     col |= col << 16;
       
  1028     return col;
       
  1029 }
       
  1030 
       
  1031 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
       
  1032 {
       
  1033     unsigned int col;
       
  1034     col = rgb_to_pixel32(r, g, b);
       
  1035     return col;
       
  1036 }
       
  1037 
       
  1038 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
       
  1039 {
       
  1040     unsigned int col;
       
  1041     col = rgb_to_pixel32bgr(r, g, b);
       
  1042     return col;
       
  1043 }
       
  1044 
       
  1045 /* return true if the palette was modified */
       
  1046 static int update_palette16(VGAState *s)
       
  1047 {
       
  1048     int full_update, i;
       
  1049     uint32_t v, col, *palette;
       
  1050 
       
  1051     full_update = 0;
       
  1052     palette = s->last_palette;
       
  1053     for(i = 0; i < 16; i++) {
       
  1054         v = s->ar[i];
       
  1055         if (s->ar[0x10] & 0x80)
       
  1056             v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
       
  1057         else
       
  1058             v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
       
  1059         v = v * 3;
       
  1060         col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
       
  1061                               c6_to_8(s->palette[v + 1]),
       
  1062                               c6_to_8(s->palette[v + 2]));
       
  1063         if (col != palette[i]) {
       
  1064             full_update = 1;
       
  1065             palette[i] = col;
       
  1066         }
       
  1067     }
       
  1068     return full_update;
       
  1069 }
       
  1070 
       
  1071 /* return true if the palette was modified */
       
  1072 static int update_palette256(VGAState *s)
       
  1073 {
       
  1074     int full_update, i;
       
  1075     uint32_t v, col, *palette;
       
  1076 
       
  1077     full_update = 0;
       
  1078     palette = s->last_palette;
       
  1079     v = 0;
       
  1080     for(i = 0; i < 256; i++) {
       
  1081         if (s->dac_8bit) {
       
  1082           col = s->rgb_to_pixel(s->palette[v],
       
  1083                                 s->palette[v + 1],
       
  1084                                 s->palette[v + 2]);
       
  1085         } else {
       
  1086           col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
       
  1087                                 c6_to_8(s->palette[v + 1]),
       
  1088                                 c6_to_8(s->palette[v + 2]));
       
  1089         }
       
  1090         if (col != palette[i]) {
       
  1091             full_update = 1;
       
  1092             palette[i] = col;
       
  1093         }
       
  1094         v += 3;
       
  1095     }
       
  1096     return full_update;
       
  1097 }
       
  1098 
       
  1099 static void vga_get_offsets(VGAState *s,
       
  1100                             uint32_t *pline_offset,
       
  1101                             uint32_t *pstart_addr,
       
  1102                             uint32_t *pline_compare)
       
  1103 {
       
  1104     uint32_t start_addr, line_offset, line_compare;
       
  1105 #ifdef CONFIG_BOCHS_VBE
       
  1106     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
       
  1107         line_offset = s->vbe_line_offset;
       
  1108         start_addr = s->vbe_start_addr;
       
  1109         line_compare = 65535;
       
  1110     } else
       
  1111 #endif
       
  1112     {
       
  1113         /* compute line_offset in bytes */
       
  1114         line_offset = s->cr[0x13];
       
  1115         line_offset <<= 3;
       
  1116 
       
  1117         /* starting address */
       
  1118         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
       
  1119 
       
  1120         /* line compare */
       
  1121         line_compare = s->cr[0x18] |
       
  1122             ((s->cr[0x07] & 0x10) << 4) |
       
  1123             ((s->cr[0x09] & 0x40) << 3);
       
  1124     }
       
  1125     *pline_offset = line_offset;
       
  1126     *pstart_addr = start_addr;
       
  1127     *pline_compare = line_compare;
       
  1128 }
       
  1129 
       
  1130 /* update start_addr and line_offset. Return TRUE if modified */
       
  1131 static int update_basic_params(VGAState *s)
       
  1132 {
       
  1133     int full_update;
       
  1134     uint32_t start_addr, line_offset, line_compare;
       
  1135 
       
  1136     full_update = 0;
       
  1137 
       
  1138     s->get_offsets(s, &line_offset, &start_addr, &line_compare);
       
  1139 
       
  1140     if (line_offset != s->line_offset ||
       
  1141         start_addr != s->start_addr ||
       
  1142         line_compare != s->line_compare) {
       
  1143         s->line_offset = line_offset;
       
  1144         s->start_addr = start_addr;
       
  1145         s->line_compare = line_compare;
       
  1146         full_update = 1;
       
  1147     }
       
  1148     return full_update;
       
  1149 }
       
  1150 
       
  1151 #define NB_DEPTHS 7
       
  1152 
       
  1153 static inline int get_depth_index(DisplayState *s)
       
  1154 {
       
  1155     switch(ds_get_bits_per_pixel(s)) {
       
  1156     default:
       
  1157     case 8:
       
  1158         return 0;
       
  1159     case 15:
       
  1160         if (ds_get_bgr(s))
       
  1161             return 5;
       
  1162         else
       
  1163             return 1;
       
  1164     case 16:
       
  1165         if (ds_get_bgr(s))
       
  1166             return 6;
       
  1167         else
       
  1168             return 2;
       
  1169     case 32:
       
  1170         if (ds_get_bgr(s))
       
  1171             return 4;
       
  1172         else
       
  1173             return 3;
       
  1174     }
       
  1175 }
       
  1176 
       
  1177 static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
       
  1178     vga_draw_glyph8_8,
       
  1179     vga_draw_glyph8_16,
       
  1180     vga_draw_glyph8_16,
       
  1181     vga_draw_glyph8_32,
       
  1182     vga_draw_glyph8_32,
       
  1183     vga_draw_glyph8_16,
       
  1184     vga_draw_glyph8_16,
       
  1185 };
       
  1186 
       
  1187 static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
       
  1188     vga_draw_glyph16_8,
       
  1189     vga_draw_glyph16_16,
       
  1190     vga_draw_glyph16_16,
       
  1191     vga_draw_glyph16_32,
       
  1192     vga_draw_glyph16_32,
       
  1193     vga_draw_glyph16_16,
       
  1194     vga_draw_glyph16_16,
       
  1195 };
       
  1196 
       
  1197 static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
       
  1198     vga_draw_glyph9_8,
       
  1199     vga_draw_glyph9_16,
       
  1200     vga_draw_glyph9_16,
       
  1201     vga_draw_glyph9_32,
       
  1202     vga_draw_glyph9_32,
       
  1203     vga_draw_glyph9_16,
       
  1204     vga_draw_glyph9_16,
       
  1205 };
       
  1206 
       
  1207 static const uint8_t cursor_glyph[32 * 4] = {
       
  1208     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1209     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1210     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1211     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1212     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1213     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1214     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1215     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1216     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1217     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1218     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1219     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1220     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1221     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1222     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1223     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
       
  1224 };
       
  1225 
       
  1226 /*
       
  1227  * Text mode update
       
  1228  * Missing:
       
  1229  * - double scan
       
  1230  * - double width
       
  1231  * - underline
       
  1232  * - flashing
       
  1233  */
       
  1234 static void vga_draw_text(VGAState *s, int full_update)
       
  1235 {
       
  1236     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
       
  1237     int cx_min, cx_max, linesize, x_incr;
       
  1238     uint32_t offset, fgcol, bgcol, v, cursor_offset;
       
  1239     uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
       
  1240     const uint8_t *font_ptr, *font_base[2];
       
  1241     int dup9, line_offset, depth_index;
       
  1242     uint32_t *palette;
       
  1243     uint32_t *ch_attr_ptr;
       
  1244     vga_draw_glyph8_func *vga_draw_glyph8;
       
  1245     vga_draw_glyph9_func *vga_draw_glyph9;
       
  1246 
       
  1247     vga_dirty_log_stop(s);
       
  1248 
       
  1249     full_update |= update_palette16(s);
       
  1250     palette = s->last_palette;
       
  1251 
       
  1252     /* compute font data address (in plane 2) */
       
  1253     v = s->sr[3];
       
  1254     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
       
  1255     if (offset != s->font_offsets[0]) {
       
  1256         s->font_offsets[0] = offset;
       
  1257         full_update = 1;
       
  1258     }
       
  1259     font_base[0] = s->vram_ptr + offset;
       
  1260 
       
  1261     offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
       
  1262     font_base[1] = s->vram_ptr + offset;
       
  1263     if (offset != s->font_offsets[1]) {
       
  1264         s->font_offsets[1] = offset;
       
  1265         full_update = 1;
       
  1266     }
       
  1267     if (s->plane_updated & (1 << 2)) {
       
  1268         /* if the plane 2 was modified since the last display, it
       
  1269            indicates the font may have been modified */
       
  1270         s->plane_updated = 0;
       
  1271         full_update = 1;
       
  1272     }
       
  1273     full_update |= update_basic_params(s);
       
  1274 
       
  1275     line_offset = s->line_offset;
       
  1276     s1 = s->vram_ptr + (s->start_addr * 4);
       
  1277 
       
  1278     /* total width & height */
       
  1279     cheight = (s->cr[9] & 0x1f) + 1;
       
  1280     cw = 8;
       
  1281     if (!(s->sr[1] & 0x01))
       
  1282         cw = 9;
       
  1283     if (s->sr[1] & 0x08)
       
  1284         cw = 16; /* NOTE: no 18 pixel wide */
       
  1285     x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
       
  1286     width = (s->cr[0x01] + 1);
       
  1287     if (s->cr[0x06] == 100) {
       
  1288         /* ugly hack for CGA 160x100x16 - explain me the logic */
       
  1289         height = 100;
       
  1290     } else {
       
  1291         height = s->cr[0x12] |
       
  1292             ((s->cr[0x07] & 0x02) << 7) |
       
  1293             ((s->cr[0x07] & 0x40) << 3);
       
  1294         height = (height + 1) / cheight;
       
  1295     }
       
  1296     if ((height * width) > CH_ATTR_SIZE) {
       
  1297         /* better than nothing: exit if transient size is too big */
       
  1298         return;
       
  1299     }
       
  1300 
       
  1301     if (width != s->last_width || height != s->last_height ||
       
  1302         cw != s->last_cw || cheight != s->last_ch) {
       
  1303         s->last_scr_width = width * cw;
       
  1304         s->last_scr_height = height * cheight;
       
  1305         gui_resize_vt(s->ds, s->last_scr_width, s->last_scr_height);
       
  1306         s->last_width = width;
       
  1307         s->last_height = height;
       
  1308         s->last_ch = cheight;
       
  1309         s->last_cw = cw;
       
  1310         full_update = 1;
       
  1311     }
       
  1312     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
       
  1313     if (cursor_offset != s->cursor_offset ||
       
  1314         s->cr[0xa] != s->cursor_start ||
       
  1315         s->cr[0xb] != s->cursor_end) {
       
  1316       /* if the cursor position changed, we update the old and new
       
  1317          chars */
       
  1318         if (s->cursor_offset < CH_ATTR_SIZE)
       
  1319             s->last_ch_attr[s->cursor_offset] = -1;
       
  1320         if (cursor_offset < CH_ATTR_SIZE)
       
  1321             s->last_ch_attr[cursor_offset] = -1;
       
  1322         s->cursor_offset = cursor_offset;
       
  1323         s->cursor_start = s->cr[0xa];
       
  1324         s->cursor_end = s->cr[0xb];
       
  1325     }
       
  1326     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
       
  1327 
       
  1328     depth_index = get_depth_index(s->ds);
       
  1329     if (cw == 16)
       
  1330         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
       
  1331     else
       
  1332         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
       
  1333     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
       
  1334 
       
  1335     dest = ds_get_data(s->ds);
       
  1336     linesize = ds_get_linesize(s->ds);
       
  1337     ch_attr_ptr = s->last_ch_attr;
       
  1338     for(cy = 0; cy < height; cy++) {
       
  1339         d1 = dest;
       
  1340         src = s1;
       
  1341         cx_min = width;
       
  1342         cx_max = -1;
       
  1343         for(cx = 0; cx < width; cx++) {
       
  1344             ch_attr = *(uint16_t *)src;
       
  1345             if (full_update || ch_attr != *ch_attr_ptr) {
       
  1346                 if (cx < cx_min)
       
  1347                     cx_min = cx;
       
  1348                 if (cx > cx_max)
       
  1349                     cx_max = cx;
       
  1350                 *ch_attr_ptr = ch_attr;
       
  1351 #ifdef WORDS_BIGENDIAN
       
  1352                 ch = ch_attr >> 8;
       
  1353                 cattr = ch_attr & 0xff;
       
  1354 #else
       
  1355                 ch = ch_attr & 0xff;
       
  1356                 cattr = ch_attr >> 8;
       
  1357 #endif
       
  1358                 font_ptr = font_base[(cattr >> 3) & 1];
       
  1359                 font_ptr += 32 * 4 * ch;
       
  1360                 bgcol = palette[cattr >> 4];
       
  1361                 fgcol = palette[cattr & 0x0f];
       
  1362                 if (cw != 9) {
       
  1363                     vga_draw_glyph8(d1, linesize,
       
  1364                                     font_ptr, cheight, fgcol, bgcol);
       
  1365                 } else {
       
  1366                     dup9 = 0;
       
  1367                     if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
       
  1368                         dup9 = 1;
       
  1369                     vga_draw_glyph9(d1, linesize,
       
  1370                                     font_ptr, cheight, fgcol, bgcol, dup9);
       
  1371                 }
       
  1372                 if (src == cursor_ptr &&
       
  1373                     !(s->cr[0x0a] & 0x20)) {
       
  1374                     int line_start, line_last, h;
       
  1375                     /* draw the cursor */
       
  1376                     line_start = s->cr[0x0a] & 0x1f;
       
  1377                     line_last = s->cr[0x0b] & 0x1f;
       
  1378                     /* XXX: check that */
       
  1379                     if (line_last > cheight - 1)
       
  1380                         line_last = cheight - 1;
       
  1381                     if (line_last >= line_start && line_start < cheight) {
       
  1382                         h = line_last - line_start + 1;
       
  1383                         d = d1 + linesize * line_start;
       
  1384                         if (cw != 9) {
       
  1385                             vga_draw_glyph8(d, linesize,
       
  1386                                             cursor_glyph, h, fgcol, bgcol);
       
  1387                         } else {
       
  1388                             vga_draw_glyph9(d, linesize,
       
  1389                                             cursor_glyph, h, fgcol, bgcol, 1);
       
  1390                         }
       
  1391                     }
       
  1392                 }
       
  1393             }
       
  1394             d1 += x_incr;
       
  1395             src += 4;
       
  1396             ch_attr_ptr++;
       
  1397         }
       
  1398         if (cx_max != -1) {
       
  1399             dpy_update(s->ds, cx_min * cw, cy * cheight,
       
  1400                        (cx_max - cx_min + 1) * cw, cheight);
       
  1401         }
       
  1402         dest += linesize * cheight;
       
  1403         s1 += line_offset;
       
  1404     }
       
  1405 }
       
  1406 
       
  1407 enum {
       
  1408     VGA_DRAW_LINE2,
       
  1409     VGA_DRAW_LINE2D2,
       
  1410     VGA_DRAW_LINE4,
       
  1411     VGA_DRAW_LINE4D2,
       
  1412     VGA_DRAW_LINE8D2,
       
  1413     VGA_DRAW_LINE8,
       
  1414     VGA_DRAW_LINE15,
       
  1415     VGA_DRAW_LINE16,
       
  1416     VGA_DRAW_LINE24,
       
  1417     VGA_DRAW_LINE32,
       
  1418     VGA_DRAW_LINE_NB,
       
  1419 };
       
  1420 
       
  1421 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
       
  1422     vga_draw_line2_8,
       
  1423     vga_draw_line2_16,
       
  1424     vga_draw_line2_16,
       
  1425     vga_draw_line2_32,
       
  1426     vga_draw_line2_32,
       
  1427     vga_draw_line2_16,
       
  1428     vga_draw_line2_16,
       
  1429 
       
  1430     vga_draw_line2d2_8,
       
  1431     vga_draw_line2d2_16,
       
  1432     vga_draw_line2d2_16,
       
  1433     vga_draw_line2d2_32,
       
  1434     vga_draw_line2d2_32,
       
  1435     vga_draw_line2d2_16,
       
  1436     vga_draw_line2d2_16,
       
  1437 
       
  1438     vga_draw_line4_8,
       
  1439     vga_draw_line4_16,
       
  1440     vga_draw_line4_16,
       
  1441     vga_draw_line4_32,
       
  1442     vga_draw_line4_32,
       
  1443     vga_draw_line4_16,
       
  1444     vga_draw_line4_16,
       
  1445 
       
  1446     vga_draw_line4d2_8,
       
  1447     vga_draw_line4d2_16,
       
  1448     vga_draw_line4d2_16,
       
  1449     vga_draw_line4d2_32,
       
  1450     vga_draw_line4d2_32,
       
  1451     vga_draw_line4d2_16,
       
  1452     vga_draw_line4d2_16,
       
  1453 
       
  1454     vga_draw_line8d2_8,
       
  1455     vga_draw_line8d2_16,
       
  1456     vga_draw_line8d2_16,
       
  1457     vga_draw_line8d2_32,
       
  1458     vga_draw_line8d2_32,
       
  1459     vga_draw_line8d2_16,
       
  1460     vga_draw_line8d2_16,
       
  1461 
       
  1462     vga_draw_line8_8,
       
  1463     vga_draw_line8_16,
       
  1464     vga_draw_line8_16,
       
  1465     vga_draw_line8_32,
       
  1466     vga_draw_line8_32,
       
  1467     vga_draw_line8_16,
       
  1468     vga_draw_line8_16,
       
  1469 
       
  1470     vga_draw_line15_8,
       
  1471     vga_draw_line15_15,
       
  1472     vga_draw_line15_16,
       
  1473     vga_draw_line15_32,
       
  1474     vga_draw_line15_32bgr,
       
  1475     vga_draw_line15_15bgr,
       
  1476     vga_draw_line15_16bgr,
       
  1477 
       
  1478     vga_draw_line16_8,
       
  1479     vga_draw_line16_15,
       
  1480     vga_draw_line16_16,
       
  1481     vga_draw_line16_32,
       
  1482     vga_draw_line16_32bgr,
       
  1483     vga_draw_line16_15bgr,
       
  1484     vga_draw_line16_16bgr,
       
  1485 
       
  1486     vga_draw_line24_8,
       
  1487     vga_draw_line24_15,
       
  1488     vga_draw_line24_16,
       
  1489     vga_draw_line24_32,
       
  1490     vga_draw_line24_32bgr,
       
  1491     vga_draw_line24_15bgr,
       
  1492     vga_draw_line24_16bgr,
       
  1493 
       
  1494     vga_draw_line32_8,
       
  1495     vga_draw_line32_15,
       
  1496     vga_draw_line32_16,
       
  1497     vga_draw_line32_32,
       
  1498     vga_draw_line32_32bgr,
       
  1499     vga_draw_line32_15bgr,
       
  1500     vga_draw_line32_16bgr,
       
  1501 };
       
  1502 
       
  1503 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
       
  1504 
       
  1505 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
       
  1506     rgb_to_pixel8_dup,
       
  1507     rgb_to_pixel15_dup,
       
  1508     rgb_to_pixel16_dup,
       
  1509     rgb_to_pixel32_dup,
       
  1510     rgb_to_pixel32bgr_dup,
       
  1511     rgb_to_pixel15bgr_dup,
       
  1512     rgb_to_pixel16bgr_dup,
       
  1513 };
       
  1514 
       
  1515 static int vga_get_bpp(VGAState *s)
       
  1516 {
       
  1517     int ret;
       
  1518 #ifdef CONFIG_BOCHS_VBE
       
  1519     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
       
  1520         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
       
  1521     } else
       
  1522 #endif
       
  1523     {
       
  1524         ret = 0;
       
  1525     }
       
  1526     return ret;
       
  1527 }
       
  1528 
       
  1529 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
       
  1530 {
       
  1531     int width, height;
       
  1532 
       
  1533 #ifdef CONFIG_BOCHS_VBE
       
  1534     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
       
  1535         width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
       
  1536         height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
       
  1537     } else
       
  1538 #endif
       
  1539     {
       
  1540         width = (s->cr[0x01] + 1) * 8;
       
  1541         height = s->cr[0x12] |
       
  1542             ((s->cr[0x07] & 0x02) << 7) |
       
  1543             ((s->cr[0x07] & 0x40) << 3);
       
  1544         height = (height + 1);
       
  1545     }
       
  1546     *pwidth = width;
       
  1547     *pheight = height;
       
  1548 }
       
  1549 
       
  1550 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
       
  1551 {
       
  1552     int y;
       
  1553     if (y1 >= VGA_MAX_HEIGHT)
       
  1554         return;
       
  1555     if (y2 >= VGA_MAX_HEIGHT)
       
  1556         y2 = VGA_MAX_HEIGHT;
       
  1557     for(y = y1; y < y2; y++) {
       
  1558         s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
       
  1559     }
       
  1560 }
       
  1561 
       
  1562 static void vga_sync_dirty_bitmap(VGAState *s)
       
  1563 {
       
  1564     if (s->map_addr)
       
  1565         cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
       
  1566 
       
  1567     if (s->lfb_vram_mapped) {
       
  1568         cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
       
  1569         cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
       
  1570     }
       
  1571     vga_dirty_log_start(s);
       
  1572 }
       
  1573 
       
  1574 /*
       
  1575  * graphic modes
       
  1576  */
       
  1577 static void vga_draw_graphic(VGAState *s, int full_update)
       
  1578 {
       
  1579     int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
       
  1580     int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
       
  1581     int disp_width, multi_scan, multi_run;
       
  1582     uint8_t *d;
       
  1583     uint32_t v, addr1, addr;
       
  1584     vga_draw_line_func *vga_draw_line;
       
  1585 
       
  1586     full_update |= update_basic_params(s);
       
  1587 
       
  1588     if (!full_update)
       
  1589         vga_sync_dirty_bitmap(s);
       
  1590 
       
  1591     s->get_resolution(s, &width, &height);
       
  1592     disp_width = width;
       
  1593 
       
  1594     shift_control = (s->gr[0x05] >> 5) & 3;
       
  1595     double_scan = (s->cr[0x09] >> 7);
       
  1596     if (shift_control != 1) {
       
  1597         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
       
  1598     } else {
       
  1599         /* in CGA modes, multi_scan is ignored */
       
  1600         /* XXX: is it correct ? */
       
  1601         multi_scan = double_scan;
       
  1602     }
       
  1603     multi_run = multi_scan;
       
  1604     if (shift_control != s->shift_control ||
       
  1605         double_scan != s->double_scan) {
       
  1606         full_update = 1;
       
  1607         s->shift_control = shift_control;
       
  1608         s->double_scan = double_scan;
       
  1609     }
       
  1610 
       
  1611     if (shift_control == 0) {
       
  1612         full_update |= update_palette16(s);
       
  1613         if (s->sr[0x01] & 8) {
       
  1614             v = VGA_DRAW_LINE4D2;
       
  1615             disp_width <<= 1;
       
  1616         } else {
       
  1617             v = VGA_DRAW_LINE4;
       
  1618         }
       
  1619         bits = 4;
       
  1620     } else if (shift_control == 1) {
       
  1621         full_update |= update_palette16(s);
       
  1622         if (s->sr[0x01] & 8) {
       
  1623             v = VGA_DRAW_LINE2D2;
       
  1624             disp_width <<= 1;
       
  1625         } else {
       
  1626             v = VGA_DRAW_LINE2;
       
  1627         }
       
  1628         bits = 4;
       
  1629     } else {
       
  1630         switch(s->get_bpp(s)) {
       
  1631         default:
       
  1632         case 0:
       
  1633             full_update |= update_palette256(s);
       
  1634             v = VGA_DRAW_LINE8D2;
       
  1635             bits = 4;
       
  1636             break;
       
  1637         case 8:
       
  1638             full_update |= update_palette256(s);
       
  1639             v = VGA_DRAW_LINE8;
       
  1640             bits = 8;
       
  1641             break;
       
  1642         case 15:
       
  1643             v = VGA_DRAW_LINE15;
       
  1644             bits = 16;
       
  1645             break;
       
  1646         case 16:
       
  1647             v = VGA_DRAW_LINE16;
       
  1648             bits = 16;
       
  1649             break;
       
  1650         case 24:
       
  1651             v = VGA_DRAW_LINE24;
       
  1652             bits = 24;
       
  1653             break;
       
  1654         case 32:
       
  1655             v = VGA_DRAW_LINE32;
       
  1656             bits = 32;
       
  1657             break;
       
  1658         }
       
  1659     }
       
  1660     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
       
  1661 
       
  1662     if (disp_width != s->last_width ||
       
  1663         height != s->last_height) {
       
  1664         gui_resize_vt(s->ds, disp_width, height);
       
  1665         s->last_scr_width = disp_width;
       
  1666         s->last_scr_height = height;
       
  1667         s->last_width = disp_width;
       
  1668         s->last_height = height;
       
  1669         full_update = 1;
       
  1670     }
       
  1671     if (s->cursor_invalidate)
       
  1672         s->cursor_invalidate(s);
       
  1673 
       
  1674     line_offset = s->line_offset;
       
  1675 #if 0
       
  1676     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",
       
  1677            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
       
  1678 #endif
       
  1679     addr1 = (s->start_addr * 4);
       
  1680     bwidth = (width * bits + 7) / 8;
       
  1681     y_start = -1;
       
  1682     page_min = 0x7fffffff;
       
  1683     page_max = -1;
       
  1684     d = ds_get_data(s->ds);
       
  1685     linesize = ds_get_linesize(s->ds);
       
  1686     y1 = 0;
       
  1687     for(y = 0; y < height; y++) {
       
  1688         addr = addr1;
       
  1689         if (!(s->cr[0x17] & 1)) {
       
  1690             int shift;
       
  1691             /* CGA compatibility handling */
       
  1692             shift = 14 + ((s->cr[0x17] >> 6) & 1);
       
  1693             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
       
  1694         }
       
  1695         if (!(s->cr[0x17] & 2)) {
       
  1696             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
       
  1697         }
       
  1698         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
       
  1699         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
       
  1700         update = full_update |
       
  1701             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
       
  1702             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
       
  1703         if ((page1 - page0) > TARGET_PAGE_SIZE) {
       
  1704             /* if wide line, can use another page */
       
  1705             update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
       
  1706                                                     VGA_DIRTY_FLAG);
       
  1707         }
       
  1708         /* explicit invalidation for the hardware cursor */
       
  1709         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
       
  1710         if (update) {
       
  1711             if (y_start < 0)
       
  1712                 y_start = y;
       
  1713             if (page0 < page_min)
       
  1714                 page_min = page0;
       
  1715             if (page1 > page_max)
       
  1716                 page_max = page1;
       
  1717             vga_draw_line(s, d, s->vram_ptr + addr, width);
       
  1718             if (s->cursor_draw_line)
       
  1719                 s->cursor_draw_line(s, d, y);
       
  1720         } else {
       
  1721             if (y_start >= 0) {
       
  1722                 /* flush to display */
       
  1723                 dpy_update(s->ds, 0, y_start,
       
  1724                            disp_width, y - y_start);
       
  1725                 y_start = -1;
       
  1726             }
       
  1727         }
       
  1728         if (!multi_run) {
       
  1729             mask = (s->cr[0x17] & 3) ^ 3;
       
  1730             if ((y1 & mask) == mask)
       
  1731                 addr1 += line_offset;
       
  1732             y1++;
       
  1733             multi_run = multi_scan;
       
  1734         } else {
       
  1735             multi_run--;
       
  1736         }
       
  1737         /* line compare acts on the displayed lines */
       
  1738         if (y == s->line_compare)
       
  1739             addr1 = 0;
       
  1740         d += linesize;
       
  1741     }
       
  1742     if (y_start >= 0) {
       
  1743         /* flush to display */
       
  1744         dpy_update(s->ds, 0, y_start,
       
  1745                    disp_width, y - y_start);
       
  1746     }
       
  1747     /* reset modified pages */
       
  1748     if (page_max != -1) {
       
  1749         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
       
  1750                                         VGA_DIRTY_FLAG);
       
  1751     }
       
  1752     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
       
  1753 }
       
  1754 
       
  1755 static void vga_draw_blank(VGAState *s, int full_update)
       
  1756 {
       
  1757     int i, w, val;
       
  1758     uint8_t *d;
       
  1759 
       
  1760     if (!full_update)
       
  1761         return;
       
  1762     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
       
  1763         return;
       
  1764     vga_dirty_log_stop(s);
       
  1765 
       
  1766     if (ds_get_bits_per_pixel(s->ds) == 8)
       
  1767         val = s->rgb_to_pixel(0, 0, 0);
       
  1768     else
       
  1769         val = 0;
       
  1770     w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
       
  1771     d = ds_get_data(s->ds);
       
  1772     for(i = 0; i < s->last_scr_height; i++) {
       
  1773         memset(d, val, w);
       
  1774         d += ds_get_linesize(s->ds);
       
  1775     }
       
  1776     dpy_update(s->ds, 0, 0,
       
  1777                s->last_scr_width, s->last_scr_height);
       
  1778 }
       
  1779 
       
  1780 #define GMODE_TEXT     0
       
  1781 #define GMODE_GRAPH    1
       
  1782 #define GMODE_BLANK 2
       
  1783 
       
  1784 static void vga_update_display(void *opaque)
       
  1785 {
       
  1786     VGAState *s = (VGAState *)opaque;
       
  1787     int full_update, graphic_mode;
       
  1788 
       
  1789     if (ds_get_bits_per_pixel(s->ds) == 0) {
       
  1790         /* nothing to do */
       
  1791     } else {
       
  1792         s->rgb_to_pixel =
       
  1793             rgb_to_pixel_dup_table[get_depth_index(s->ds)];
       
  1794 
       
  1795         full_update = 0;
       
  1796         if (!(s->ar_index & 0x20)) {
       
  1797             graphic_mode = GMODE_BLANK;
       
  1798         } else {
       
  1799             graphic_mode = s->gr[6] & 1;
       
  1800         }
       
  1801         if (graphic_mode != s->graphic_mode) {
       
  1802             s->graphic_mode = graphic_mode;
       
  1803             full_update = 1;
       
  1804         }
       
  1805         switch(graphic_mode) {
       
  1806         case GMODE_TEXT:
       
  1807             vga_draw_text(s, full_update);
       
  1808             break;
       
  1809         case GMODE_GRAPH:
       
  1810             vga_draw_graphic(s, full_update);
       
  1811             break;
       
  1812         case GMODE_BLANK:
       
  1813         default:
       
  1814             vga_draw_blank(s, full_update);
       
  1815             break;
       
  1816         }
       
  1817     }
       
  1818 }
       
  1819 
       
  1820 /* force a full display refresh */
       
  1821 static void vga_invalidate_display(void *opaque)
       
  1822 {
       
  1823     VGAState *s = (VGAState *)opaque;
       
  1824 
       
  1825     s->last_width = -1;
       
  1826     s->last_height = -1;
       
  1827 }
       
  1828 
       
  1829 static void vga_reset(VGAState *s)
       
  1830 {
       
  1831     memset(s, 0, sizeof(VGAState));
       
  1832     s->graphic_mode = -1; /* force full update */
       
  1833 }
       
  1834 
       
  1835 #define TEXTMODE_X(x)	((x) % width)
       
  1836 #define TEXTMODE_Y(x)	((x) / width)
       
  1837 #define VMEM2CHTYPE(v)	((v & 0xff0007ff) | \
       
  1838         ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
       
  1839 /* relay text rendering to the display driver
       
  1840  * instead of doing a full vga_update_display() */
       
  1841 static void vga_update_text(void *opaque, console_ch_t *chardata)
       
  1842 {
       
  1843     VGAState *s = (VGAState *) opaque;
       
  1844     int graphic_mode, i, cursor_offset, cursor_visible;
       
  1845     int cw, cheight, width, height, size, c_min, c_max;
       
  1846     uint32_t *src;
       
  1847     console_ch_t *dst, val;
       
  1848     char msg_buffer[80];
       
  1849     int full_update = 0;
       
  1850 
       
  1851     if (!(s->ar_index & 0x20)) {
       
  1852         graphic_mode = GMODE_BLANK;
       
  1853     } else {
       
  1854         graphic_mode = s->gr[6] & 1;
       
  1855     }
       
  1856     if (graphic_mode != s->graphic_mode) {
       
  1857         s->graphic_mode = graphic_mode;
       
  1858         full_update = 1;
       
  1859     }
       
  1860     if (s->last_width == -1) {
       
  1861         s->last_width = 0;
       
  1862         full_update = 1;
       
  1863     }
       
  1864 
       
  1865     switch (graphic_mode) {
       
  1866     case GMODE_TEXT:
       
  1867         /* TODO: update palette */
       
  1868         full_update |= update_basic_params(s);
       
  1869 
       
  1870         /* total width & height */
       
  1871         cheight = (s->cr[9] & 0x1f) + 1;
       
  1872         cw = 8;
       
  1873         if (!(s->sr[1] & 0x01))
       
  1874             cw = 9;
       
  1875         if (s->sr[1] & 0x08)
       
  1876             cw = 16; /* NOTE: no 18 pixel wide */
       
  1877         width = (s->cr[0x01] + 1);
       
  1878         if (s->cr[0x06] == 100) {
       
  1879             /* ugly hack for CGA 160x100x16 - explain me the logic */
       
  1880             height = 100;
       
  1881         } else {
       
  1882             height = s->cr[0x12] | 
       
  1883                 ((s->cr[0x07] & 0x02) << 7) | 
       
  1884                 ((s->cr[0x07] & 0x40) << 3);
       
  1885             height = (height + 1) / cheight;
       
  1886         }
       
  1887 
       
  1888         size = (height * width);
       
  1889         if (size > CH_ATTR_SIZE) {
       
  1890             if (!full_update)
       
  1891                 return;
       
  1892 
       
  1893             snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
       
  1894                      width, height);
       
  1895             break;
       
  1896         }
       
  1897 
       
  1898         if (width != s->last_width || height != s->last_height ||
       
  1899             cw != s->last_cw || cheight != s->last_ch) {
       
  1900             s->last_scr_width = width * cw;
       
  1901             s->last_scr_height = height * cheight;
       
  1902             gui_resize_vt(s->ds, width, height);
       
  1903             s->last_width = width;
       
  1904             s->last_height = height;
       
  1905             s->last_ch = cheight;
       
  1906             s->last_cw = cw;
       
  1907             full_update = 1;
       
  1908         }
       
  1909 
       
  1910         /* Update "hardware" cursor */
       
  1911         cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
       
  1912         if (cursor_offset != s->cursor_offset ||
       
  1913             s->cr[0xa] != s->cursor_start ||
       
  1914             s->cr[0xb] != s->cursor_end || full_update) {
       
  1915             cursor_visible = !(s->cr[0xa] & 0x20);
       
  1916             if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
       
  1917                 dpy_cursor(s->ds,
       
  1918                            TEXTMODE_X(cursor_offset),
       
  1919                            TEXTMODE_Y(cursor_offset));
       
  1920             else
       
  1921                 dpy_cursor(s->ds, -1, -1);
       
  1922             s->cursor_offset = cursor_offset;
       
  1923             s->cursor_start = s->cr[0xa];
       
  1924             s->cursor_end = s->cr[0xb];
       
  1925         }
       
  1926 
       
  1927         src = (uint32_t *) s->vram_ptr + s->start_addr;
       
  1928         dst = chardata;
       
  1929 
       
  1930         if (full_update) {
       
  1931             for (i = 0; i < size; src ++, dst ++, i ++)
       
  1932                 console_write_ch(dst, VMEM2CHTYPE(*src));
       
  1933 
       
  1934             dpy_update(s->ds, 0, 0, width, height);
       
  1935         } else {
       
  1936             c_max = 0;
       
  1937 
       
  1938             for (i = 0; i < size; src ++, dst ++, i ++) {
       
  1939                 console_write_ch(&val, VMEM2CHTYPE(*src));
       
  1940                 if (*dst != val) {
       
  1941                     *dst = val;
       
  1942                     c_max = i;
       
  1943                     break;
       
  1944                 }
       
  1945             }
       
  1946             c_min = i;
       
  1947             for (; i < size; src ++, dst ++, i ++) {
       
  1948                 console_write_ch(&val, VMEM2CHTYPE(*src));
       
  1949                 if (*dst != val) {
       
  1950                     *dst = val;
       
  1951                     c_max = i;
       
  1952                 }
       
  1953             }
       
  1954 
       
  1955             if (c_min <= c_max) {
       
  1956                 i = TEXTMODE_Y(c_min);
       
  1957                 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
       
  1958             }
       
  1959         }
       
  1960 
       
  1961         return;
       
  1962     case GMODE_GRAPH:
       
  1963         if (!full_update)
       
  1964             return;
       
  1965 
       
  1966         s->get_resolution(s, &width, &height);
       
  1967         snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
       
  1968                  width, height);
       
  1969         break;
       
  1970     case GMODE_BLANK:
       
  1971     default:
       
  1972         if (!full_update)
       
  1973             return;
       
  1974 
       
  1975         snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
       
  1976         break;
       
  1977     }
       
  1978 
       
  1979     /* Display a message */
       
  1980     s->last_width = 60;
       
  1981     s->last_height = height = 3;
       
  1982     dpy_cursor(s->ds, -1, -1);
       
  1983     gui_resize_vt(s->ds, s->last_width, height);
       
  1984 
       
  1985     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
       
  1986         console_write_ch(dst ++, ' ');
       
  1987 
       
  1988     size = strlen(msg_buffer);
       
  1989     width = (s->last_width - size) / 2;
       
  1990     dst = chardata + s->last_width + width;
       
  1991     for (i = 0; i < size; i ++)
       
  1992         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
       
  1993 
       
  1994     dpy_update(s->ds, 0, 0, s->last_width, height);
       
  1995 }
       
  1996 
       
  1997 static CPUReadMemoryFunc *vga_mem_read[3] = {
       
  1998     vga_mem_readb,
       
  1999     vga_mem_readw,
       
  2000     vga_mem_readl,
       
  2001 };
       
  2002 
       
  2003 static CPUWriteMemoryFunc *vga_mem_write[3] = {
       
  2004     vga_mem_writeb,
       
  2005     vga_mem_writew,
       
  2006     vga_mem_writel,
       
  2007 };
       
  2008 
       
  2009 static void vga_save(QEMUFile *f, void *opaque)
       
  2010 {
       
  2011     VGAState *s = opaque;
       
  2012     int i;
       
  2013 
       
  2014     if (s->pci_dev)
       
  2015         pci_device_save(s->pci_dev, f);
       
  2016 
       
  2017     qemu_put_be32s(f, &s->latch);
       
  2018     qemu_put_8s(f, &s->sr_index);
       
  2019     qemu_put_buffer(f, s->sr, 8);
       
  2020     qemu_put_8s(f, &s->gr_index);
       
  2021     qemu_put_buffer(f, s->gr, 16);
       
  2022     qemu_put_8s(f, &s->ar_index);
       
  2023     qemu_put_buffer(f, s->ar, 21);
       
  2024     qemu_put_be32(f, s->ar_flip_flop);
       
  2025     qemu_put_8s(f, &s->cr_index);
       
  2026     qemu_put_buffer(f, s->cr, 256);
       
  2027     qemu_put_8s(f, &s->msr);
       
  2028     qemu_put_8s(f, &s->fcr);
       
  2029     qemu_put_byte(f, s->st00);
       
  2030     qemu_put_8s(f, &s->st01);
       
  2031 
       
  2032     qemu_put_8s(f, &s->dac_state);
       
  2033     qemu_put_8s(f, &s->dac_sub_index);
       
  2034     qemu_put_8s(f, &s->dac_read_index);
       
  2035     qemu_put_8s(f, &s->dac_write_index);
       
  2036     qemu_put_buffer(f, s->dac_cache, 3);
       
  2037     qemu_put_buffer(f, s->palette, 768);
       
  2038 
       
  2039     qemu_put_be32(f, s->bank_offset);
       
  2040 #ifdef CONFIG_BOCHS_VBE
       
  2041     qemu_put_byte(f, 1);
       
  2042     qemu_put_be16s(f, &s->vbe_index);
       
  2043     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
       
  2044         qemu_put_be16s(f, &s->vbe_regs[i]);
       
  2045     qemu_put_be32s(f, &s->vbe_start_addr);
       
  2046     qemu_put_be32s(f, &s->vbe_line_offset);
       
  2047     qemu_put_be32s(f, &s->vbe_bank_mask);
       
  2048 #else
       
  2049     qemu_put_byte(f, 0);
       
  2050 #endif
       
  2051 }
       
  2052 
       
  2053 static int vga_load(QEMUFile *f, void *opaque, int version_id)
       
  2054 {
       
  2055     VGAState *s = opaque;
       
  2056     int is_vbe, i, ret;
       
  2057 
       
  2058     if (version_id > 2)
       
  2059         return -EINVAL;
       
  2060 
       
  2061     if (s->pci_dev && version_id >= 2) {
       
  2062         ret = pci_device_load(s->pci_dev, f);
       
  2063         if (ret < 0)
       
  2064             return ret;
       
  2065     }
       
  2066 
       
  2067     qemu_get_be32s(f, &s->latch);
       
  2068     qemu_get_8s(f, &s->sr_index);
       
  2069     qemu_get_buffer(f, s->sr, 8);
       
  2070     qemu_get_8s(f, &s->gr_index);
       
  2071     qemu_get_buffer(f, s->gr, 16);
       
  2072     qemu_get_8s(f, &s->ar_index);
       
  2073     qemu_get_buffer(f, s->ar, 21);
       
  2074     s->ar_flip_flop=qemu_get_be32(f);
       
  2075     qemu_get_8s(f, &s->cr_index);
       
  2076     qemu_get_buffer(f, s->cr, 256);
       
  2077     qemu_get_8s(f, &s->msr);
       
  2078     qemu_get_8s(f, &s->fcr);
       
  2079     qemu_get_8s(f, &s->st00);
       
  2080     qemu_get_8s(f, &s->st01);
       
  2081 
       
  2082     qemu_get_8s(f, &s->dac_state);
       
  2083     qemu_get_8s(f, &s->dac_sub_index);
       
  2084     qemu_get_8s(f, &s->dac_read_index);
       
  2085     qemu_get_8s(f, &s->dac_write_index);
       
  2086     qemu_get_buffer(f, s->dac_cache, 3);
       
  2087     qemu_get_buffer(f, s->palette, 768);
       
  2088 
       
  2089     s->bank_offset=qemu_get_be32(f);
       
  2090     is_vbe = qemu_get_byte(f);
       
  2091 #ifdef CONFIG_BOCHS_VBE
       
  2092     if (!is_vbe)
       
  2093         return -EINVAL;
       
  2094     qemu_get_be16s(f, &s->vbe_index);
       
  2095     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
       
  2096         qemu_get_be16s(f, &s->vbe_regs[i]);
       
  2097     qemu_get_be32s(f, &s->vbe_start_addr);
       
  2098     qemu_get_be32s(f, &s->vbe_line_offset);
       
  2099     qemu_get_be32s(f, &s->vbe_bank_mask);
       
  2100 #else
       
  2101     if (is_vbe)
       
  2102         return -EINVAL;
       
  2103 #endif
       
  2104 
       
  2105     /* force refresh */
       
  2106     s->graphic_mode = -1;
       
  2107     return 0;
       
  2108 }
       
  2109 
       
  2110 typedef struct PCIVGAState {
       
  2111     PCIDevice dev;
       
  2112     VGAState vga_state;
       
  2113 } PCIVGAState;
       
  2114 
       
  2115 void vga_dirty_log_start(VGAState *s)
       
  2116 {
       
  2117     if (kvm_enabled() && s->map_addr)
       
  2118         kvm_log_start(s->map_addr, s->map_end - s->map_addr);
       
  2119 
       
  2120     if (kvm_enabled() && s->lfb_vram_mapped) {
       
  2121         kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
       
  2122         kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
       
  2123     }
       
  2124 }
       
  2125 
       
  2126 void vga_dirty_log_stop(VGAState *s)
       
  2127 {
       
  2128     if (kvm_enabled() && s->map_addr)
       
  2129         kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
       
  2130 
       
  2131     if (kvm_enabled() && s->lfb_vram_mapped) {
       
  2132         kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
       
  2133         kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
       
  2134     }
       
  2135 }
       
  2136 
       
  2137 static void vga_map(PCIDevice *pci_dev, int region_num,
       
  2138                     uint32_t addr, uint32_t size, int type)
       
  2139 {
       
  2140     PCIVGAState *d = (PCIVGAState *)pci_dev;
       
  2141     VGAState *s = &d->vga_state;
       
  2142     if (region_num == PCI_ROM_SLOT) {
       
  2143         cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
       
  2144     } else {
       
  2145         cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
       
  2146     }
       
  2147 
       
  2148     s->map_addr = addr;
       
  2149     s->map_end = addr + VGA_RAM_SIZE;
       
  2150 
       
  2151     vga_dirty_log_start(s);
       
  2152 }
       
  2153 
       
  2154 void vga_common_init(VGAState *s, /*DisplayState *ds, */uint8_t *vga_ram_base,
       
  2155                      ram_addr_t vga_ram_offset, int vga_ram_size)
       
  2156 {
       
  2157     int i, j, v, b;
       
  2158 
       
  2159     for(i = 0;i < 256; i++) {
       
  2160         v = 0;
       
  2161         for(j = 0; j < 8; j++) {
       
  2162             v |= ((i >> j) & 1) << (j * 4);
       
  2163         }
       
  2164         expand4[i] = v;
       
  2165 
       
  2166         v = 0;
       
  2167         for(j = 0; j < 4; j++) {
       
  2168             v |= ((i >> (2 * j)) & 3) << (j * 4);
       
  2169         }
       
  2170         expand2[i] = v;
       
  2171     }
       
  2172     for(i = 0; i < 16; i++) {
       
  2173         v = 0;
       
  2174         for(j = 0; j < 4; j++) {
       
  2175             b = ((i >> j) & 1);
       
  2176             v |= b << (2 * j);
       
  2177             v |= b << (2 * j + 1);
       
  2178         }
       
  2179         expand4to8[i] = v;
       
  2180     }
       
  2181 
       
  2182     vga_reset(s);
       
  2183 
       
  2184     s->vram_ptr = vga_ram_base;
       
  2185     s->vram_offset = vga_ram_offset;
       
  2186     s->vram_size = vga_ram_size;
       
  2187 //    s->ds = ds;
       
  2188     s->get_bpp = vga_get_bpp;
       
  2189     s->get_offsets = vga_get_offsets;
       
  2190     s->get_resolution = vga_get_resolution;
       
  2191     s->update = vga_update_display;
       
  2192     s->invalidate = vga_invalidate_display;
       
  2193     s->screen_dump = vga_screen_dump;
       
  2194     s->text_update = vga_update_text;
       
  2195     switch (vga_retrace_method) {
       
  2196     case VGA_RETRACE_DUMB:
       
  2197         s->retrace = vga_dumb_retrace;
       
  2198         s->update_retrace_info = vga_dumb_update_retrace_info;
       
  2199         break;
       
  2200 
       
  2201     case VGA_RETRACE_PRECISE:
       
  2202         s->retrace = vga_precise_retrace;
       
  2203         s->update_retrace_info = vga_precise_update_retrace_info;
       
  2204         memset(&s->retrace_info, 0, sizeof (s->retrace_info));
       
  2205         break;
       
  2206     }
       
  2207 }
       
  2208 
       
  2209 /* used by both ISA and PCI */
       
  2210 void vga_init(VGAState *s)
       
  2211 {
       
  2212     int vga_io_memory;
       
  2213 
       
  2214     register_savevm("vga", 0, 2, vga_save, vga_load, s);
       
  2215 
       
  2216     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
       
  2217 
       
  2218     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
       
  2219     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
       
  2220     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
       
  2221     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
       
  2222 
       
  2223     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
       
  2224 
       
  2225     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
       
  2226     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
       
  2227     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
       
  2228     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
       
  2229     s->bank_offset = 0;
       
  2230 
       
  2231 #ifdef CONFIG_BOCHS_VBE
       
  2232     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
       
  2233     s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
       
  2234 #if defined (TARGET_I386)
       
  2235     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
       
  2236     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
       
  2237 
       
  2238     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
       
  2239     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
       
  2240 
       
  2241     /* old Bochs IO ports */
       
  2242     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
       
  2243     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
       
  2244 
       
  2245     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
       
  2246     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
       
  2247 #else
       
  2248     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
       
  2249     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
       
  2250 
       
  2251     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
       
  2252     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
       
  2253 #endif
       
  2254 #endif /* CONFIG_BOCHS_VBE */
       
  2255 
       
  2256     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
       
  2257     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
       
  2258                                  vga_io_memory);
       
  2259     qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
       
  2260 }
       
  2261 
       
  2262 /* Memory mapped interface */
       
  2263 static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
       
  2264 {
       
  2265     VGAState *s = opaque;
       
  2266 
       
  2267     return vga_ioport_read(s, addr >> s->it_shift) & 0xff;
       
  2268 }
       
  2269 
       
  2270 static void vga_mm_writeb (void *opaque,
       
  2271                            target_phys_addr_t addr, uint32_t value)
       
  2272 {
       
  2273     VGAState *s = opaque;
       
  2274 
       
  2275     vga_ioport_write(s, addr >> s->it_shift, value & 0xff);
       
  2276 }
       
  2277 
       
  2278 static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
       
  2279 {
       
  2280     VGAState *s = opaque;
       
  2281 
       
  2282     return vga_ioport_read(s, addr >> s->it_shift) & 0xffff;
       
  2283 }
       
  2284 
       
  2285 static void vga_mm_writew (void *opaque,
       
  2286                            target_phys_addr_t addr, uint32_t value)
       
  2287 {
       
  2288     VGAState *s = opaque;
       
  2289 
       
  2290     vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
       
  2291 }
       
  2292 
       
  2293 static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
       
  2294 {
       
  2295     VGAState *s = opaque;
       
  2296 
       
  2297     return vga_ioport_read(s, addr >> s->it_shift);
       
  2298 }
       
  2299 
       
  2300 static void vga_mm_writel (void *opaque,
       
  2301                            target_phys_addr_t addr, uint32_t value)
       
  2302 {
       
  2303     VGAState *s = opaque;
       
  2304 
       
  2305     vga_ioport_write(s, addr >> s->it_shift, value);
       
  2306 }
       
  2307 
       
  2308 static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
       
  2309     &vga_mm_readb,
       
  2310     &vga_mm_readw,
       
  2311     &vga_mm_readl,
       
  2312 };
       
  2313 
       
  2314 static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
       
  2315     &vga_mm_writeb,
       
  2316     &vga_mm_writew,
       
  2317     &vga_mm_writel,
       
  2318 };
       
  2319 
       
  2320 static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
       
  2321                         target_phys_addr_t ctrl_base, int it_shift)
       
  2322 {
       
  2323     int s_ioport_ctrl, vga_io_memory;
       
  2324 
       
  2325     s->it_shift = it_shift;
       
  2326     s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
       
  2327     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
       
  2328 
       
  2329     register_savevm("vga", 0, 2, vga_save, vga_load, s);
       
  2330 
       
  2331     cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
       
  2332     s->bank_offset = 0;
       
  2333     cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
       
  2334     qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
       
  2335 }
       
  2336 
       
  2337 int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
       
  2338                  unsigned long vga_ram_offset, int vga_ram_size)
       
  2339 {
       
  2340     VGAState *s;
       
  2341 
       
  2342     s = qemu_mallocz(sizeof(VGAState));
       
  2343     if (!s)
       
  2344         return -1;
       
  2345 
       
  2346     vga_common_init(s, /*ds,*/ vga_ram_base, vga_ram_offset, vga_ram_size);
       
  2347     vga_init(s);
       
  2348 
       
  2349     s->ds = gui_get_graphic_console(NULL, s->update, s->invalidate,
       
  2350                                     s->screen_dump, /*s->text_update,*/ s); /* DFG TODO */
       
  2351 #ifdef CONFIG_BOCHS_VBE
       
  2352     /* XXX: use optimized standard vga accesses */
       
  2353     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
       
  2354                                  vga_ram_size, vga_ram_offset);
       
  2355 #endif
       
  2356     return 0;
       
  2357 }
       
  2358 
       
  2359 int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
       
  2360                     unsigned long vga_ram_offset, int vga_ram_size,
       
  2361                     target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
       
  2362                     int it_shift)
       
  2363 {
       
  2364     VGAState *s;
       
  2365 
       
  2366     s = qemu_mallocz(sizeof(VGAState));
       
  2367     if (!s)
       
  2368         return -1;
       
  2369 
       
  2370     vga_common_init(s, /*ds,*/ vga_ram_base, vga_ram_offset, vga_ram_size);
       
  2371     vga_mm_init(s, vram_base, ctrl_base, it_shift);
       
  2372 
       
  2373     s->ds = gui_get_graphic_console(NULL, s->update, s->invalidate,
       
  2374                                     s->screen_dump, /* s->text_update,*/ s); /* TODO DFG */
       
  2375 
       
  2376 #ifdef CONFIG_BOCHS_VBE
       
  2377     /* XXX: use optimized standard vga accesses */
       
  2378     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
       
  2379                                  vga_ram_size, vga_ram_offset);
       
  2380 #endif
       
  2381     return 0;
       
  2382 }
       
  2383 
       
  2384 int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
       
  2385                  unsigned long vga_ram_offset, int vga_ram_size,
       
  2386                  unsigned long vga_bios_offset, int vga_bios_size)
       
  2387 {
       
  2388     PCIVGAState *d;
       
  2389     VGAState *s;
       
  2390     uint8_t *pci_conf;
       
  2391 
       
  2392     d = (PCIVGAState *)pci_register_device(bus, "VGA",
       
  2393                                            sizeof(PCIVGAState),
       
  2394                                            -1, NULL, NULL);
       
  2395     if (!d)
       
  2396         return -1;
       
  2397     s = &d->vga_state;
       
  2398 
       
  2399     vga_common_init(s, /*ds,*/ vga_ram_base, vga_ram_offset, vga_ram_size);
       
  2400     vga_init(s);
       
  2401 
       
  2402     s->ds = gui_get_graphic_console(NULL, s->update, s->invalidate,
       
  2403                                     s->screen_dump, /* s->text_update,*/ s); /* DFG TODO */
       
  2404 
       
  2405     s->pci_dev = &d->dev;
       
  2406 
       
  2407     pci_conf = d->dev.config;
       
  2408     pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
       
  2409     pci_conf[0x01] = 0x12;
       
  2410     pci_conf[0x02] = 0x11;
       
  2411     pci_conf[0x03] = 0x11;
       
  2412     pci_conf[0x0a] = 0x00; // VGA controller
       
  2413     pci_conf[0x0b] = 0x03;
       
  2414     pci_conf[0x0e] = 0x00; // header_type
       
  2415 
       
  2416     /* XXX: vga_ram_size must be a power of two */
       
  2417     pci_register_io_region(&d->dev, 0, vga_ram_size,
       
  2418                            PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
       
  2419     if (vga_bios_size != 0) {
       
  2420         unsigned int bios_total_size;
       
  2421         s->bios_offset = vga_bios_offset;
       
  2422         s->bios_size = vga_bios_size;
       
  2423         /* must be a power of two */
       
  2424         bios_total_size = 1;
       
  2425         while (bios_total_size < vga_bios_size)
       
  2426             bios_total_size <<= 1;
       
  2427         pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
       
  2428                                PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
       
  2429     }
       
  2430     return 0;
       
  2431 }
       
  2432 
       
  2433 /********************************************************/
       
  2434 /* vga screen dump */
       
  2435 
       
  2436 static int vga_save_w, vga_save_h;
       
  2437 
       
  2438 static void vga_save_dpy_update(DisplayState *s,
       
  2439                                 int x, int y, int w, int h)
       
  2440 {
       
  2441 }
       
  2442 
       
  2443 #if 0
       
  2444     DFG TODO
       
  2445 static void vga_save_dpy_resize(DisplayState *s, int w, int h)
       
  2446 {
       
  2447     s->linesize = w * 4;
       
  2448     s->data = qemu_mallocz(h * s->linesize);
       
  2449     vga_save_w = w;
       
  2450     vga_save_h = h;
       
  2451 }
       
  2452 
       
  2453 static void vga_save_dpy_refresh(DisplayState *s)
       
  2454 {
       
  2455 }
       
  2456 #endif
       
  2457 
       
  2458 int ppm_save(const char *filename, uint8_t *data,
       
  2459              int w, int h, int linesize)
       
  2460 {
       
  2461     FILE *f;
       
  2462     uint8_t *d, *d1;
       
  2463     unsigned int v;
       
  2464     int y, x;
       
  2465 
       
  2466     f = fopen(filename, "wb");
       
  2467     if (!f)
       
  2468         return -1;
       
  2469     fprintf(f, "P6\n%d %d\n%d\n",
       
  2470             w, h, 255);
       
  2471     d1 = data;
       
  2472     for(y = 0; y < h; y++) {
       
  2473         d = d1;
       
  2474         for(x = 0; x < w; x++) {
       
  2475             v = *(uint32_t *)d;
       
  2476             fputc((v >> 16) & 0xff, f);
       
  2477             fputc((v >> 8) & 0xff, f);
       
  2478             fputc((v) & 0xff, f);
       
  2479             d += 4;
       
  2480         }
       
  2481         d1 += linesize;
       
  2482     }
       
  2483     fclose(f);
       
  2484     return 0;
       
  2485 }
       
  2486 
       
  2487 /* save the vga display in a PPM image even if no display is
       
  2488    available */
       
  2489 static void vga_screen_dump(void *opaque, const char *filename)
       
  2490 {
       
  2491 #if 0
       
  2492     DFG TODO
       
  2493     VGAState *s = (VGAState *)opaque;
       
  2494     DisplayState *saved_ds, ds1, *ds = &ds1;
       
  2495 
       
  2496     /* XXX: this is a little hackish */
       
  2497     vga_invalidate_display(s);
       
  2498     saved_ds = s->ds;
       
  2499 
       
  2500     memset(ds, 0, sizeof(DisplayState));
       
  2501     ds->dpy_update = vga_save_dpy_update;
       
  2502 #if 0
       
  2503     DFG TODO
       
  2504     ds->dpy_resize = vga_save_dpy_resize;
       
  2505     ds->dpy_refresh = vga_save_dpy_refresh;
       
  2506 #endif
       
  2507     ds->depth = 32;
       
  2508 
       
  2509     s->ds = ds;
       
  2510     s->graphic_mode = -1;
       
  2511     vga_update_display(s);
       
  2512 
       
  2513     if (ds_get_data(ds)) {
       
  2514         ppm_save(filename, ds_get_data(ds), vga_save_w, vga_save_h,
       
  2515                  ds_get_linesize(s->ds));
       
  2516         qemu_free(ds_get_data(ds));
       
  2517     }
       
  2518     s->ds = saved_ds;
       
  2519 #endif
       
  2520 }
       
  2521