Annotation of qemu/hw/vga.c, revision 1.1.1.17

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.