]> git.proxmox.com Git - mirror_qemu.git/blame - hw/display/vga.c
vga: move dirty memory region code together
[mirror_qemu.git] / hw / display / vga.c
CommitLineData
e89f66ec 1/*
4fa0f5d2 2 * QEMU VGA Emulator.
5fafdf24 3 *
e89f66ec 4 * Copyright (c) 2003 Fabrice Bellard
5fafdf24 5 *
e89f66ec
FB
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 */
71e8a915 24
47df5154 25#include "qemu/osdep.h"
f0353b0d 26#include "qemu/units.h"
71e8a915 27#include "sysemu/reset.h"
da34e65c 28#include "qapi/error.h"
9eb7e7e8 29#include "hw/core/cpu.h"
866e2b37 30#include "hw/display/vga.h"
9eb7e7e8 31#include "hw/i386/x86.h"
83c9f4ca 32#include "hw/pci/pci.h"
47b43a1f 33#include "vga_int.h"
d10d69e3 34#include "vga_regs.h"
28ecbaee 35#include "ui/pixel_ops.h"
28cf3960 36#include "ui/console.h"
1de7afc9 37#include "qemu/timer.h"
0d09e41a 38#include "hw/xen/xen.h"
d6454270 39#include "migration/vmstate.h"
72750018 40#include "trace.h"
e89f66ec 41
17b0018b 42//#define DEBUG_VGA_MEM
a41bc9af
FB
43//#define DEBUG_VGA_REG
44
48ecfbf1
GH
45bool have_vga = true;
46
9aa0ff0b
JK
47/* 16 state changes per vertical frame @60 Hz */
48#define VGA_TEXT_CURSOR_PERIOD_MS (1000 * 2 * 16 / 60)
49
9b53b95a
PB
50/* Address mask for non-VESA modes. */
51#define VGA_VRAM_SIZE (256 * KiB)
52
973a724e
PB
53/* This value corresponds to a shift of zero pixels
54 * in 9-dot text mode. In other modes, bit 3 is undefined;
55 * we just ignore it, so that 8 corresponds to zero pixels
56 * in all modes.
57 */
58#define VGA_HPEL_NEUTRAL 8
59
47c012e2
BS
60/*
61 * Video Graphics Array (VGA)
62 *
63 * Chipset docs for original IBM VGA:
64 * http://www.mcamafia.de/pdf/ibm_vgaxga_trm2.pdf
65 *
66 * FreeVGA site:
67 * http://www.osdever.net/FreeVGA/home.htm
68 *
69 * Standard VGA features and Bochs VBE extensions are implemented.
70 */
71
e89f66ec 72/* force some bits to zero */
798b0c25 73const uint8_t sr_mask[8] = {
9e622b15
BS
74 0x03,
75 0x3d,
76 0x0f,
77 0x3f,
78 0x0e,
79 0x00,
80 0x00,
81 0xff,
e89f66ec
FB
82};
83
798b0c25 84const uint8_t gr_mask[16] = {
9e622b15
BS
85 0x0f, /* 0x00 */
86 0x0f, /* 0x01 */
87 0x0f, /* 0x02 */
88 0x1f, /* 0x03 */
89 0x03, /* 0x04 */
90 0x7b, /* 0x05 */
91 0x0f, /* 0x06 */
92 0x0f, /* 0x07 */
93 0xff, /* 0x08 */
94 0x00, /* 0x09 */
95 0x00, /* 0x0a */
96 0x00, /* 0x0b */
97 0x00, /* 0x0c */
98 0x00, /* 0x0d */
99 0x00, /* 0x0e */
100 0x00, /* 0x0f */
e89f66ec
FB
101};
102
937de9a9 103#define GET_PLANE(data, p) ((cpu_to_le32(data) >> ((p) * 8)) & 0xff)
b8ed223b 104
e89f66ec 105static const uint32_t mask16[16] = {
937de9a9
PB
106 const_le32(0x00000000),
107 const_le32(0x000000ff),
108 const_le32(0x0000ff00),
109 const_le32(0x0000ffff),
110 const_le32(0x00ff0000),
111 const_le32(0x00ff00ff),
112 const_le32(0x00ffff00),
113 const_le32(0x00ffffff),
114 const_le32(0xff000000),
115 const_le32(0xff0000ff),
116 const_le32(0xff00ff00),
117 const_le32(0xff00ffff),
118 const_le32(0xffff0000),
119 const_le32(0xffff00ff),
120 const_le32(0xffffff00),
121 const_le32(0xffffffff),
e89f66ec
FB
122};
123
e89f66ec
FB
124static uint32_t expand4[256];
125static uint16_t expand2[256];
17b0018b 126static uint8_t expand4to8[16];
e89f66ec 127
fd3c136b
GH
128static void vbe_update_vgaregs(VGACommonState *s);
129
bfa0f151
GH
130static inline bool vbe_enabled(VGACommonState *s)
131{
132 return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED;
133}
134
94ef4f33
GH
135static inline uint8_t sr(VGACommonState *s, int idx)
136{
137 return vbe_enabled(s) ? s->sr_vbe[idx] : s->sr[idx];
138}
139
80763888
JK
140static void vga_update_memory_access(VGACommonState *s)
141{
a8170e5e 142 hwaddr base, offset, size;
80763888 143
63e3e24d
GH
144 if (s->legacy_address_space == NULL) {
145 return;
146 }
147
ad37168c
PB
148 if (s->has_chain4_alias) {
149 memory_region_del_subregion(s->legacy_address_space, &s->chain4_alias);
d8d95814 150 object_unparent(OBJECT(&s->chain4_alias));
ad37168c
PB
151 s->has_chain4_alias = false;
152 s->plane_updated = 0xf;
153 }
94ef4f33
GH
154 if ((sr(s, VGA_SEQ_PLANE_WRITE) & VGA_SR02_ALL_PLANES) ==
155 VGA_SR02_ALL_PLANES && sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
80763888 156 offset = 0;
5e55efc9 157 switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) {
80763888
JK
158 case 0:
159 base = 0xa0000;
160 size = 0x20000;
161 break;
162 case 1:
163 base = 0xa0000;
164 size = 0x10000;
165 offset = s->bank_offset;
166 break;
167 case 2:
168 base = 0xb0000;
169 size = 0x8000;
170 break;
171 case 3:
f065aa0a 172 default:
80763888
JK
173 base = 0xb8000;
174 size = 0x8000;
175 break;
176 }
3bf18170 177 assert(offset + size <= s->vram_size);
ad37168c 178 memory_region_init_alias(&s->chain4_alias, memory_region_owner(&s->vram),
42e038fe 179 "vga.chain4", &s->vram, offset, size);
80763888 180 memory_region_add_subregion_overlap(s->legacy_address_space, base,
ad37168c
PB
181 &s->chain4_alias, 2);
182 s->has_chain4_alias = true;
80763888
JK
183 }
184}
185
cedd91d2 186static void vga_dumb_update_retrace_info(VGACommonState *s)
cb5a7aa8 187{
188 (void) s;
189}
190
cedd91d2 191static void vga_precise_update_retrace_info(VGACommonState *s)
cb5a7aa8 192{
193 int htotal_chars;
194 int hretr_start_char;
195 int hretr_skew_chars;
196 int hretr_end_char;
197
198 int vtotal_lines;
199 int vretr_start_line;
200 int vretr_end_line;
201
7f5b7d3e
BS
202 int dots;
203#if 0
204 int div2, sldiv2;
205#endif
cb5a7aa8 206 int clocking_mode;
207 int clock_sel;
b0f74c87 208 const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
cb5a7aa8 209 int64_t chars_per_sec;
210 struct vga_precise_retrace *r = &s->retrace_info.precise;
211
5e55efc9
BS
212 htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
213 hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
214 hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
215 hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
cb5a7aa8 216
5e55efc9
BS
217 vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] |
218 (((s->cr[VGA_CRTC_OVERFLOW] & 1) |
219 ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2;
220 vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] |
221 ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) |
222 ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
223 vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
cb5a7aa8 224
94ef4f33 225 clocking_mode = (sr(s, VGA_SEQ_CLOCK_MODE) >> 3) & 1;
cb5a7aa8 226 clock_sel = (s->msr >> 2) & 3;
f87fc09b 227 dots = (s->msr & 1) ? 8 : 9;
cb5a7aa8 228
b0f74c87 229 chars_per_sec = clk_hz[clock_sel] / dots;
cb5a7aa8 230
231 htotal_chars <<= clocking_mode;
232
233 r->total_chars = vtotal_lines * htotal_chars;
cb5a7aa8 234 if (r->freq) {
73bcb24d 235 r->ticks_per_char = NANOSECONDS_PER_SECOND / (r->total_chars * r->freq);
cb5a7aa8 236 } else {
73bcb24d 237 r->ticks_per_char = NANOSECONDS_PER_SECOND / chars_per_sec;
cb5a7aa8 238 }
239
240 r->vstart = vretr_start_line;
241 r->vend = r->vstart + vretr_end_line + 1;
242
243 r->hstart = hretr_start_char + hretr_skew_chars;
244 r->hend = r->hstart + hretr_end_char + 1;
245 r->htotal = htotal_chars;
246
f87fc09b 247#if 0
5e55efc9
BS
248 div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1;
249 sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1;
cb5a7aa8 250 printf (
f87fc09b 251 "hz=%f\n"
cb5a7aa8 252 "htotal = %d\n"
253 "hretr_start = %d\n"
254 "hretr_skew = %d\n"
255 "hretr_end = %d\n"
256 "vtotal = %d\n"
257 "vretr_start = %d\n"
258 "vretr_end = %d\n"
259 "div2 = %d sldiv2 = %d\n"
260 "clocking_mode = %d\n"
261 "clock_sel = %d %d\n"
262 "dots = %d\n"
0bfcd599 263 "ticks/char = %" PRId64 "\n"
cb5a7aa8 264 "\n",
73bcb24d 265 (double) NANOSECONDS_PER_SECOND / (r->ticks_per_char * r->total_chars),
cb5a7aa8 266 htotal_chars,
267 hretr_start_char,
268 hretr_skew_chars,
269 hretr_end_char,
270 vtotal_lines,
271 vretr_start_line,
272 vretr_end_line,
273 div2, sldiv2,
274 clocking_mode,
275 clock_sel,
b0f74c87 276 clk_hz[clock_sel],
cb5a7aa8 277 dots,
278 r->ticks_per_char
279 );
280#endif
281}
282
cedd91d2 283static uint8_t vga_precise_retrace(VGACommonState *s)
cb5a7aa8 284{
285 struct vga_precise_retrace *r = &s->retrace_info.precise;
286 uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
287
288 if (r->total_chars) {
289 int cur_line, cur_line_char, cur_char;
290 int64_t cur_tick;
291
bc72ad67 292 cur_tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
cb5a7aa8 293
294 cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
295 cur_line = cur_char / r->htotal;
296
297 if (cur_line >= r->vstart && cur_line <= r->vend) {
298 val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
f87fc09b 299 } else {
300 cur_line_char = cur_char % r->htotal;
301 if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
302 val |= ST01_DISP_ENABLE;
303 }
cb5a7aa8 304 }
305
306 return val;
307 } else {
308 return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
309 }
310}
311
cedd91d2 312static uint8_t vga_dumb_retrace(VGACommonState *s)
cb5a7aa8 313{
314 return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
315}
316
25a18cbd
JQ
317int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
318{
5e55efc9 319 if (s->msr & VGA_MIS_COLOR) {
25a18cbd
JQ
320 /* Color */
321 return (addr >= 0x3b0 && addr <= 0x3bf);
322 } else {
323 /* Monochrome */
324 return (addr >= 0x3d0 && addr <= 0x3df);
325 }
326}
327
43bf782b 328uint32_t vga_ioport_read(void *opaque, uint32_t addr)
e89f66ec 329{
43bf782b 330 VGACommonState *s = opaque;
e89f66ec
FB
331 int val, index;
332
25a18cbd 333 if (vga_ioport_invalid(s, addr)) {
e89f66ec
FB
334 val = 0xff;
335 } else {
336 switch(addr) {
5e55efc9 337 case VGA_ATT_W:
e89f66ec
FB
338 if (s->ar_flip_flop == 0) {
339 val = s->ar_index;
340 } else {
341 val = 0;
342 }
343 break;
5e55efc9 344 case VGA_ATT_R:
e89f66ec 345 index = s->ar_index & 0x1f;
5e55efc9 346 if (index < VGA_ATT_C) {
e89f66ec 347 val = s->ar[index];
5e55efc9 348 } else {
e89f66ec 349 val = 0;
5e55efc9 350 }
e89f66ec 351 break;
5e55efc9 352 case VGA_MIS_W:
e89f66ec
FB
353 val = s->st00;
354 break;
5e55efc9 355 case VGA_SEQ_I:
e89f66ec
FB
356 val = s->sr_index;
357 break;
5e55efc9 358 case VGA_SEQ_D:
e89f66ec 359 val = s->sr[s->sr_index];
a41bc9af
FB
360#ifdef DEBUG_VGA_REG
361 printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
362#endif
e89f66ec 363 break;
5e55efc9 364 case VGA_PEL_IR:
e89f66ec
FB
365 val = s->dac_state;
366 break;
5e55efc9 367 case VGA_PEL_IW:
e9b43ea3
JQ
368 val = s->dac_write_index;
369 break;
5e55efc9 370 case VGA_PEL_D:
e89f66ec
FB
371 val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
372 if (++s->dac_sub_index == 3) {
373 s->dac_sub_index = 0;
374 s->dac_read_index++;
375 }
376 break;
5e55efc9 377 case VGA_FTC_R:
e89f66ec
FB
378 val = s->fcr;
379 break;
5e55efc9 380 case VGA_MIS_R:
e89f66ec
FB
381 val = s->msr;
382 break;
5e55efc9 383 case VGA_GFX_I:
e89f66ec
FB
384 val = s->gr_index;
385 break;
5e55efc9 386 case VGA_GFX_D:
e89f66ec 387 val = s->gr[s->gr_index];
a41bc9af
FB
388#ifdef DEBUG_VGA_REG
389 printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
390#endif
e89f66ec 391 break;
5e55efc9
BS
392 case VGA_CRT_IM:
393 case VGA_CRT_IC:
e89f66ec
FB
394 val = s->cr_index;
395 break;
5e55efc9
BS
396 case VGA_CRT_DM:
397 case VGA_CRT_DC:
e89f66ec 398 val = s->cr[s->cr_index];
a41bc9af
FB
399#ifdef DEBUG_VGA_REG
400 printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
a41bc9af 401#endif
e89f66ec 402 break;
5e55efc9
BS
403 case VGA_IS1_RM:
404 case VGA_IS1_RC:
e89f66ec 405 /* just toggle to fool polling */
cb5a7aa8 406 val = s->st01 = s->retrace(s);
e89f66ec
FB
407 s->ar_flip_flop = 0;
408 break;
409 default:
410 val = 0x00;
411 break;
412 }
413 }
cf7dabee 414 trace_vga_std_read_io(addr, val);
e89f66ec
FB
415 return val;
416}
417
43bf782b 418void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
e89f66ec 419{
43bf782b 420 VGACommonState *s = opaque;
5467a722 421 int index;
e89f66ec
FB
422
423 /* check port range access depending on color/monochrome mode */
25a18cbd 424 if (vga_ioport_invalid(s, addr)) {
e89f66ec 425 return;
25a18cbd 426 }
cf7dabee 427 trace_vga_std_write_io(addr, val);
e89f66ec
FB
428
429 switch(addr) {
5e55efc9 430 case VGA_ATT_W:
e89f66ec
FB
431 if (s->ar_flip_flop == 0) {
432 val &= 0x3f;
433 s->ar_index = val;
434 } else {
435 index = s->ar_index & 0x1f;
436 switch(index) {
5e55efc9 437 case VGA_ATC_PALETTE0 ... VGA_ATC_PALETTEF:
e89f66ec
FB
438 s->ar[index] = val & 0x3f;
439 break;
5e55efc9 440 case VGA_ATC_MODE:
e89f66ec
FB
441 s->ar[index] = val & ~0x10;
442 break;
5e55efc9 443 case VGA_ATC_OVERSCAN:
e89f66ec
FB
444 s->ar[index] = val;
445 break;
5e55efc9 446 case VGA_ATC_PLANE_ENABLE:
e89f66ec
FB
447 s->ar[index] = val & ~0xc0;
448 break;
5e55efc9 449 case VGA_ATC_PEL:
e89f66ec
FB
450 s->ar[index] = val & ~0xf0;
451 break;
5e55efc9 452 case VGA_ATC_COLOR_PAGE:
e89f66ec
FB
453 s->ar[index] = val & ~0xf0;
454 break;
455 default:
456 break;
457 }
458 }
459 s->ar_flip_flop ^= 1;
460 break;
5e55efc9 461 case VGA_MIS_W:
e89f66ec 462 s->msr = val & ~0x10;
cb5a7aa8 463 s->update_retrace_info(s);
e89f66ec 464 break;
5e55efc9 465 case VGA_SEQ_I:
e89f66ec
FB
466 s->sr_index = val & 7;
467 break;
5e55efc9 468 case VGA_SEQ_D:
a41bc9af
FB
469#ifdef DEBUG_VGA_REG
470 printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
471#endif
e89f66ec 472 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
5e55efc9
BS
473 if (s->sr_index == VGA_SEQ_CLOCK_MODE) {
474 s->update_retrace_info(s);
475 }
80763888 476 vga_update_memory_access(s);
e89f66ec 477 break;
5e55efc9 478 case VGA_PEL_IR:
e89f66ec
FB
479 s->dac_read_index = val;
480 s->dac_sub_index = 0;
481 s->dac_state = 3;
482 break;
5e55efc9 483 case VGA_PEL_IW:
e89f66ec
FB
484 s->dac_write_index = val;
485 s->dac_sub_index = 0;
486 s->dac_state = 0;
487 break;
5e55efc9 488 case VGA_PEL_D:
e89f66ec
FB
489 s->dac_cache[s->dac_sub_index] = val;
490 if (++s->dac_sub_index == 3) {
491 memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
492 s->dac_sub_index = 0;
493 s->dac_write_index++;
494 }
495 break;
5e55efc9 496 case VGA_GFX_I:
e89f66ec
FB
497 s->gr_index = val & 0x0f;
498 break;
5e55efc9 499 case VGA_GFX_D:
a41bc9af
FB
500#ifdef DEBUG_VGA_REG
501 printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
502#endif
e89f66ec 503 s->gr[s->gr_index] = val & gr_mask[s->gr_index];
fd3c136b 504 vbe_update_vgaregs(s);
80763888 505 vga_update_memory_access(s);
e89f66ec 506 break;
5e55efc9
BS
507 case VGA_CRT_IM:
508 case VGA_CRT_IC:
e89f66ec
FB
509 s->cr_index = val;
510 break;
5e55efc9
BS
511 case VGA_CRT_DM:
512 case VGA_CRT_DC:
a41bc9af
FB
513#ifdef DEBUG_VGA_REG
514 printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
515#endif
e89f66ec 516 /* handle CR0-7 protection */
df800210 517 if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) &&
518 s->cr_index <= VGA_CRTC_OVERFLOW) {
519 /* can always write bit 4 of CR7 */
520 if (s->cr_index == VGA_CRTC_OVERFLOW) {
521 s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |
522 (val & 0x10);
fd3c136b 523 vbe_update_vgaregs(s);
5e55efc9 524 }
df800210 525 return;
e89f66ec 526 }
a46007a0 527 s->cr[s->cr_index] = val;
fd3c136b 528 vbe_update_vgaregs(s);
cb5a7aa8 529
530 switch(s->cr_index) {
5e55efc9
BS
531 case VGA_CRTC_H_TOTAL:
532 case VGA_CRTC_H_SYNC_START:
533 case VGA_CRTC_H_SYNC_END:
534 case VGA_CRTC_V_TOTAL:
535 case VGA_CRTC_OVERFLOW:
536 case VGA_CRTC_V_SYNC_END:
537 case VGA_CRTC_MODE:
cb5a7aa8 538 s->update_retrace_info(s);
539 break;
540 }
e89f66ec 541 break;
5e55efc9
BS
542 case VGA_IS1_RM:
543 case VGA_IS1_RC:
e89f66ec
FB
544 s->fcr = val & 0x10;
545 break;
546 }
547}
548
c1b886c4
GH
549/*
550 * Sanity check vbe register writes.
551 *
552 * As we don't have a way to signal errors to the guest in the bochs
553 * dispi interface we'll go adjust the registers to the closest valid
554 * value.
555 */
556static void vbe_fixup_regs(VGACommonState *s)
557{
558 uint16_t *r = s->vbe_regs;
559 uint32_t bits, linelength, maxy, offset;
560
bfa0f151 561 if (!vbe_enabled(s)) {
c1b886c4
GH
562 /* vbe is turned off -- nothing to do */
563 return;
564 }
565
566 /* check depth */
567 switch (r[VBE_DISPI_INDEX_BPP]) {
568 case 4:
569 case 8:
570 case 16:
571 case 24:
572 case 32:
573 bits = r[VBE_DISPI_INDEX_BPP];
574 break;
575 case 15:
576 bits = 16;
577 break;
578 default:
579 bits = r[VBE_DISPI_INDEX_BPP] = 8;
580 break;
581 }
582
583 /* check width */
584 r[VBE_DISPI_INDEX_XRES] &= ~7u;
585 if (r[VBE_DISPI_INDEX_XRES] == 0) {
586 r[VBE_DISPI_INDEX_XRES] = 8;
587 }
588 if (r[VBE_DISPI_INDEX_XRES] > VBE_DISPI_MAX_XRES) {
589 r[VBE_DISPI_INDEX_XRES] = VBE_DISPI_MAX_XRES;
590 }
591 r[VBE_DISPI_INDEX_VIRT_WIDTH] &= ~7u;
592 if (r[VBE_DISPI_INDEX_VIRT_WIDTH] > VBE_DISPI_MAX_XRES) {
593 r[VBE_DISPI_INDEX_VIRT_WIDTH] = VBE_DISPI_MAX_XRES;
594 }
595 if (r[VBE_DISPI_INDEX_VIRT_WIDTH] < r[VBE_DISPI_INDEX_XRES]) {
596 r[VBE_DISPI_INDEX_VIRT_WIDTH] = r[VBE_DISPI_INDEX_XRES];
597 }
598
599 /* check height */
600 linelength = r[VBE_DISPI_INDEX_VIRT_WIDTH] * bits / 8;
601 maxy = s->vbe_size / linelength;
602 if (r[VBE_DISPI_INDEX_YRES] == 0) {
603 r[VBE_DISPI_INDEX_YRES] = 1;
604 }
605 if (r[VBE_DISPI_INDEX_YRES] > VBE_DISPI_MAX_YRES) {
606 r[VBE_DISPI_INDEX_YRES] = VBE_DISPI_MAX_YRES;
607 }
608 if (r[VBE_DISPI_INDEX_YRES] > maxy) {
609 r[VBE_DISPI_INDEX_YRES] = maxy;
610 }
611
612 /* check offset */
613 if (r[VBE_DISPI_INDEX_X_OFFSET] > VBE_DISPI_MAX_XRES) {
614 r[VBE_DISPI_INDEX_X_OFFSET] = VBE_DISPI_MAX_XRES;
615 }
616 if (r[VBE_DISPI_INDEX_Y_OFFSET] > VBE_DISPI_MAX_YRES) {
617 r[VBE_DISPI_INDEX_Y_OFFSET] = VBE_DISPI_MAX_YRES;
618 }
619 offset = r[VBE_DISPI_INDEX_X_OFFSET] * bits / 8;
620 offset += r[VBE_DISPI_INDEX_Y_OFFSET] * linelength;
621 if (offset + r[VBE_DISPI_INDEX_YRES] * linelength > s->vbe_size) {
622 r[VBE_DISPI_INDEX_Y_OFFSET] = 0;
623 offset = r[VBE_DISPI_INDEX_X_OFFSET] * bits / 8;
624 if (offset + r[VBE_DISPI_INDEX_YRES] * linelength > s->vbe_size) {
625 r[VBE_DISPI_INDEX_X_OFFSET] = 0;
626 offset = 0;
627 }
628 }
629
630 /* update vga state */
631 r[VBE_DISPI_INDEX_VIRT_HEIGHT] = maxy;
632 s->vbe_line_offset = linelength;
633 s->vbe_start_addr = offset / 4;
634}
635
7fa5c2c5
GH
636/* we initialize the VGA graphic mode */
637static void vbe_update_vgaregs(VGACommonState *s)
638{
639 int h, shift_control;
640
641 if (!vbe_enabled(s)) {
642 /* vbe is turned off -- nothing to do */
643 return;
644 }
645
646 /* graphic mode + memory map 1 */
647 s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
648 VGA_GR06_GRAPHICS_MODE;
649 s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
650 s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
651 /* width */
652 s->cr[VGA_CRTC_H_DISP] =
653 (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
654 /* height (only meaningful if < 1024) */
655 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
656 s->cr[VGA_CRTC_V_DISP_END] = h;
657 s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
658 ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
659 /* line compare to 1023 */
660 s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
661 s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
662 s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
663
664 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
665 shift_control = 0;
94ef4f33 666 s->sr_vbe[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
7fa5c2c5
GH
667 } else {
668 shift_control = 2;
669 /* set chain 4 mode */
94ef4f33 670 s->sr_vbe[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
7fa5c2c5 671 /* activate all planes */
94ef4f33 672 s->sr_vbe[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
7fa5c2c5
GH
673 }
674 s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
675 (shift_control << 5);
676 s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
677}
678
09a79b49 679static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
4fa0f5d2 680{
cedd91d2 681 VGACommonState *s = opaque;
9be38598 682 return s->vbe_index;
09a79b49 683}
4fa0f5d2 684
803ff052 685uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
09a79b49 686{
cedd91d2 687 VGACommonState *s = opaque;
09a79b49
FB
688 uint32_t val;
689
af92284b 690 if (s->vbe_index < VBE_DISPI_INDEX_NB) {
8454df8b
FB
691 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
692 switch(s->vbe_index) {
693 /* XXX: do not hardcode ? */
694 case VBE_DISPI_INDEX_XRES:
695 val = VBE_DISPI_MAX_XRES;
696 break;
697 case VBE_DISPI_INDEX_YRES:
698 val = VBE_DISPI_MAX_YRES;
699 break;
700 case VBE_DISPI_INDEX_BPP:
701 val = VBE_DISPI_MAX_BPP;
702 break;
703 default:
5fafdf24 704 val = s->vbe_regs[s->vbe_index];
8454df8b
FB
705 break;
706 }
707 } else {
5fafdf24 708 val = s->vbe_regs[s->vbe_index];
8454df8b 709 }
af92284b 710 } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
f0353b0d 711 val = s->vbe_size / (64 * KiB);
8454df8b 712 } else {
09a79b49 713 val = 0;
8454df8b 714 }
cf7dabee 715 trace_vga_vbe_read(s->vbe_index, val);
4fa0f5d2
FB
716 return val;
717}
718
803ff052 719void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
09a79b49 720{
cedd91d2 721 VGACommonState *s = opaque;
09a79b49
FB
722 s->vbe_index = val;
723}
724
803ff052 725void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
4fa0f5d2 726{
cedd91d2 727 VGACommonState *s = opaque;
4fa0f5d2 728
09a79b49 729 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
cf7dabee 730 trace_vga_vbe_write(s->vbe_index, val);
4fa0f5d2
FB
731 switch(s->vbe_index) {
732 case VBE_DISPI_INDEX_ID:
cae61cef
FB
733 if (val == VBE_DISPI_ID0 ||
734 val == VBE_DISPI_ID1 ||
37dd208d
FB
735 val == VBE_DISPI_ID2 ||
736 val == VBE_DISPI_ID3 ||
05ece98f
DW
737 val == VBE_DISPI_ID4 ||
738 val == VBE_DISPI_ID5) {
cae61cef
FB
739 s->vbe_regs[s->vbe_index] = val;
740 }
4fa0f5d2
FB
741 break;
742 case VBE_DISPI_INDEX_XRES:
4fa0f5d2 743 case VBE_DISPI_INDEX_YRES:
4fa0f5d2 744 case VBE_DISPI_INDEX_BPP:
c1b886c4
GH
745 case VBE_DISPI_INDEX_VIRT_WIDTH:
746 case VBE_DISPI_INDEX_X_OFFSET:
747 case VBE_DISPI_INDEX_Y_OFFSET:
748 s->vbe_regs[s->vbe_index] = val;
749 vbe_fixup_regs(s);
2068192d 750 vbe_update_vgaregs(s);
4fa0f5d2
FB
751 break;
752 case VBE_DISPI_INDEX_BANK:
3bf18170 753 val &= s->vbe_bank_mask;
cae61cef 754 s->vbe_regs[s->vbe_index] = val;
26aa7d72 755 s->bank_offset = (val << 16);
80763888 756 vga_update_memory_access(s);
4fa0f5d2
FB
757 break;
758 case VBE_DISPI_INDEX_ENABLE:
8454df8b
FB
759 if ((val & VBE_DISPI_ENABLED) &&
760 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
4fa0f5d2 761
c1b886c4 762 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 0;
4fa0f5d2
FB
763 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
764 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
c1b886c4
GH
765 s->vbe_regs[VBE_DISPI_INDEX_ENABLE] |= VBE_DISPI_ENABLED;
766 vbe_fixup_regs(s);
7fa5c2c5 767 vbe_update_vgaregs(s);
8454df8b 768
ace89b8f 769 /* clear the screen */
4fa0f5d2 770 if (!(val & VBE_DISPI_NOCLEARMEM)) {
5fafdf24 771 memset(s->vram_ptr, 0,
4fa0f5d2
FB
772 s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
773 }
cae61cef 774 } else {
26aa7d72 775 s->bank_offset = 0;
cae61cef 776 }
37dd208d 777 s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
141253b2 778 s->vbe_regs[s->vbe_index] = val;
80763888 779 vga_update_memory_access(s);
cae61cef 780 break;
4fa0f5d2
FB
781 default:
782 break;
783 }
4fa0f5d2
FB
784 }
785}
4fa0f5d2 786
e89f66ec 787/* called for accesses between 0xa0000 and 0xc0000 */
a8170e5e 788uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
e89f66ec 789{
e89f66ec
FB
790 int memory_map_mode, plane;
791 uint32_t ret;
3b46e624 792
e89f66ec 793 /* convert to VGA memory offset */
5e55efc9 794 memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
26aa7d72 795 addr &= 0x1ffff;
e89f66ec
FB
796 switch(memory_map_mode) {
797 case 0:
e89f66ec
FB
798 break;
799 case 1:
26aa7d72 800 if (addr >= 0x10000)
e89f66ec 801 return 0xff;
cae61cef 802 addr += s->bank_offset;
e89f66ec
FB
803 break;
804 case 2:
26aa7d72 805 addr -= 0x10000;
e89f66ec
FB
806 if (addr >= 0x8000)
807 return 0xff;
808 break;
809 default:
810 case 3:
26aa7d72 811 addr -= 0x18000;
c92b2e84
FB
812 if (addr >= 0x8000)
813 return 0xff;
e89f66ec
FB
814 break;
815 }
3b46e624 816
94ef4f33 817 if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
43526260
PB
818 /* chain4 mode */
819 plane = addr & 3;
820 addr &= ~3;
821 } else if (s->gr[VGA_GFX_MODE] & VGA_GR05_HOST_ODD_EVEN) {
e89f66ec 822 /* odd/even mode (aka text mode mapping) */
5e55efc9 823 plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
3f834350
PB
824 } else {
825 /* standard VGA latched access */
826 plane = s->gr[VGA_GFX_PLANE_READ];
ae9d71a0 827 }
e89f66ec 828
43526260
PB
829 if (s->gr[VGA_GFX_MISC] & VGA_GR06_CHAIN_ODD_EVEN) {
830 addr &= ~1;
831 }
832
833 /* Doubleword/word mode. See comment in vga_mem_writeb */
834 if (s->cr[VGA_CRTC_UNDERLINE] & VGA_CR14_DW) {
835 addr >>= 2;
836 } else if ((s->gr[VGA_GFX_MODE] & VGA_GR05_HOST_ODD_EVEN) &&
837 (s->cr[VGA_CRTC_MODE] & VGA_CR17_WORD_BYTE) == 0) {
838 addr >>= 1;
839 }
840
ae9d71a0
PB
841 if (addr * sizeof(uint32_t) >= s->vram_size) {
842 return 0xff;
843 }
43526260
PB
844
845 if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
846 /* chain 4 mode: simplified access (but it should use the same
847 * algorithms as below, see e.g. vga_mem_writeb's plane mask check).
848 */
849 return s->vram_ptr[(addr << 2) | plane];
850 }
851
ae9d71a0
PB
852 s->latch = ((uint32_t *)s->vram_ptr)[addr];
853 if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
854 /* read mode 0 */
855 ret = GET_PLANE(s->latch, plane);
856 } else {
857 /* read mode 1 */
858 ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) &
859 mask16[s->gr[VGA_GFX_COMPARE_MASK]];
860 ret |= ret >> 16;
861 ret |= ret >> 8;
862 ret = (~ret) & 0xff;
e89f66ec 863 }
ae9d71a0 864
e89f66ec
FB
865 return ret;
866}
867
e89f66ec 868/* called for accesses between 0xa0000 and 0xc0000 */
a8170e5e 869void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
e89f66ec 870{
43526260 871 int memory_map_mode, write_mode, b, func_select, mask;
e89f66ec 872 uint32_t write_mask, bit_mask, set_mask;
43526260 873 int plane = 0;
e89f66ec 874
17b0018b 875#ifdef DEBUG_VGA_MEM
883f2c59 876 printf("vga: [0x" HWADDR_FMT_plx "] = 0x%02x\n", addr, val);
e89f66ec
FB
877#endif
878 /* convert to VGA memory offset */
5e55efc9 879 memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
26aa7d72 880 addr &= 0x1ffff;
e89f66ec
FB
881 switch(memory_map_mode) {
882 case 0:
e89f66ec
FB
883 break;
884 case 1:
26aa7d72 885 if (addr >= 0x10000)
e89f66ec 886 return;
cae61cef 887 addr += s->bank_offset;
e89f66ec
FB
888 break;
889 case 2:
26aa7d72 890 addr -= 0x10000;
e89f66ec
FB
891 if (addr >= 0x8000)
892 return;
893 break;
894 default:
895 case 3:
26aa7d72 896 addr -= 0x18000;
c92b2e84
FB
897 if (addr >= 0x8000)
898 return;
e89f66ec
FB
899 break;
900 }
3b46e624 901
3f834350 902 mask = sr(s, VGA_SEQ_PLANE_WRITE);
94ef4f33 903 if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
e89f66ec
FB
904 /* chain 4 mode : simplest access */
905 plane = addr & 3;
3f834350 906 mask &= (1 << plane);
43526260
PB
907 addr &= ~3;
908 } else {
909 if ((sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_SEQ_MODE) == 0) {
910 mask &= (addr & 1) ? 0x0a : 0x05;
911 }
912 if (s->gr[VGA_GFX_MISC] & VGA_GR06_CHAIN_ODD_EVEN) {
913 addr &= ~1;
914 }
915 }
916
917 /* Doubleword/word mode. These should be honored when displaying,
918 * not when reading/writing to memory! For example, chain4 modes
919 * use double-word mode and, on real hardware, would fetch bytes
920 * 0,1,2,3, 16,17,18,19, 32,33,34,35, etc. Text modes use word
921 * mode and, on real hardware, would fetch bytes 0,1, 8,9, etc.
922 *
923 * QEMU instead shifted addresses on memory accesses because it
924 * allows more optimizations (e.g. chain4_alias) and simplifies
925 * the draw_line handlers. Unfortunately, there is one case where
926 * the difference shows. When fetching font data, accesses are
927 * always in consecutive bytes, even if the text/attribute pairs
928 * are done in word mode. Hence, doing a right shift when operating
929 * on font data is wrong. So check the odd/even mode bits together with
930 * word mode bit. The odd/even read bit is 0 when reading font data,
931 * and the odd/even write bit is 1 when writing it.
932 */
933 if (s->cr[VGA_CRTC_UNDERLINE] & VGA_CR14_DW) {
934 addr >>= 2;
935 } else if ((sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_SEQ_MODE) == 0 &&
936 (s->cr[VGA_CRTC_MODE] & VGA_CR17_WORD_BYTE) == 0) {
937 addr >>= 1;
938 }
939
940 if (addr * sizeof(uint32_t) >= s->vram_size) {
941 return;
942 }
943
944 if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
3f834350 945 if (mask) {
43526260 946 s->vram_ptr[(addr << 2) | plane] = val;
17b0018b 947#ifdef DEBUG_VGA_MEM
883f2c59 948 printf("vga: chain4: [0x" HWADDR_FMT_plx "]\n", addr);
e89f66ec 949#endif
546fa6ab 950 s->plane_updated |= mask; /* only used to detect font change */
fd4aa979 951 memory_region_set_dirty(&s->vram, addr, 1);
e89f66ec 952 }
ae9d71a0
PB
953 return;
954 }
955
ae9d71a0
PB
956 /* standard VGA latched access */
957 write_mode = s->gr[VGA_GFX_MODE] & 3;
958 switch(write_mode) {
959 default:
960 case 0:
961 /* rotate */
962 b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
963 val = ((val >> b) | (val << (8 - b))) & 0xff;
964 val |= val << 8;
965 val |= val << 16;
966
967 /* apply set/reset mask */
968 set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]];
969 val = (val & ~set_mask) |
970 (mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask);
971 bit_mask = s->gr[VGA_GFX_BIT_MASK];
972 break;
973 case 1:
974 val = s->latch;
975 goto do_write;
976 case 2:
977 val = mask16[val & 0x0f];
978 bit_mask = s->gr[VGA_GFX_BIT_MASK];
979 break;
980 case 3:
981 /* rotate */
982 b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
983 val = (val >> b) | (val << (8 - b));
e89f66ec 984
ae9d71a0
PB
985 bit_mask = s->gr[VGA_GFX_BIT_MASK] & val;
986 val = mask16[s->gr[VGA_GFX_SR_VALUE]];
987 break;
988 }
989
990 /* apply logical operation */
991 func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3;
992 switch(func_select) {
993 case 0:
994 default:
995 /* nothing to do */
996 break;
997 case 1:
998 /* and */
999 val &= s->latch;
1000 break;
1001 case 2:
1002 /* or */
1003 val |= s->latch;
1004 break;
1005 case 3:
1006 /* xor */
1007 val ^= s->latch;
1008 break;
1009 }
1010
1011 /* apply bit mask */
1012 bit_mask |= bit_mask << 8;
1013 bit_mask |= bit_mask << 16;
1014 val = (val & bit_mask) | (s->latch & ~bit_mask);
1015
1016do_write:
1017 /* mask data according to sr[2] */
1018 s->plane_updated |= mask; /* only used to detect font change */
1019 write_mask = mask16[mask];
ae9d71a0
PB
1020 ((uint32_t *)s->vram_ptr)[addr] =
1021 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
1022 (val & write_mask);
17b0018b 1023#ifdef DEBUG_VGA_MEM
ae9d71a0
PB
1024 printf("vga: latch: [0x" HWADDR_FMT_plx "] mask=0x%08x val=0x%08x\n",
1025 addr * 4, write_mask, val);
e89f66ec 1026#endif
ae9d71a0 1027 memory_region_set_dirty(&s->vram, addr << 2, sizeof(uint32_t));
e89f66ec
FB
1028}
1029
973a724e
PB
1030typedef void *vga_draw_line_func(VGACommonState *s1, uint8_t *d,
1031 uint32_t srcaddr, int width, int hpel);
e89f66ec 1032
145e543e 1033#include "vga-access.h"
e657d8ef 1034#include "vga-helpers.h"
e89f66ec 1035
e89f66ec 1036/* return true if the palette was modified */
cedd91d2 1037static int update_palette16(VGACommonState *s)
e89f66ec 1038{
17b0018b 1039 int full_update, i;
e89f66ec 1040 uint32_t v, col, *palette;
e89f66ec
FB
1041
1042 full_update = 0;
1043 palette = s->last_palette;
1044 for(i = 0; i < 16; i++) {
1045 v = s->ar[i];
5e55efc9
BS
1046 if (s->ar[VGA_ATC_MODE] & 0x80) {
1047 v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf);
1048 } else {
1049 v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
1050 }
e89f66ec 1051 v = v * 3;
d3c2343a
BH
1052 col = rgb_to_pixel32(c6_to_8(s->palette[v]),
1053 c6_to_8(s->palette[v + 1]),
1054 c6_to_8(s->palette[v + 2]));
17b0018b
FB
1055 if (col != palette[i]) {
1056 full_update = 1;
1057 palette[i] = col;
e89f66ec 1058 }
17b0018b
FB
1059 }
1060 return full_update;
1061}
1062
1063/* return true if the palette was modified */
cedd91d2 1064static int update_palette256(VGACommonState *s)
17b0018b
FB
1065{
1066 int full_update, i;
1067 uint32_t v, col, *palette;
1068
1069 full_update = 0;
1070 palette = s->last_palette;
1071 v = 0;
1072 for(i = 0; i < 256; i++) {
37dd208d 1073 if (s->dac_8bit) {
d3c2343a
BH
1074 col = rgb_to_pixel32(s->palette[v],
1075 s->palette[v + 1],
1076 s->palette[v + 2]);
37dd208d 1077 } else {
d3c2343a
BH
1078 col = rgb_to_pixel32(c6_to_8(s->palette[v]),
1079 c6_to_8(s->palette[v + 1]),
1080 c6_to_8(s->palette[v + 2]));
37dd208d 1081 }
e89f66ec
FB
1082 if (col != palette[i]) {
1083 full_update = 1;
1084 palette[i] = col;
1085 }
17b0018b 1086 v += 3;
e89f66ec
FB
1087 }
1088 return full_update;
1089}
1090
f9b925fd
PB
1091static void vga_get_params(VGACommonState *s,
1092 VGADisplayParams *params)
e89f66ec 1093{
bfa0f151 1094 if (vbe_enabled(s)) {
f9b925fd
PB
1095 params->line_offset = s->vbe_line_offset;
1096 params->start_addr = s->vbe_start_addr;
1097 params->line_compare = 65535;
973a724e
PB
1098 params->hpel = VGA_HPEL_NEUTRAL;
1099 params->hpel_split = false;
a96d8bea 1100 } else {
4fa0f5d2 1101 /* compute line_offset in bytes */
f9b925fd 1102 params->line_offset = s->cr[VGA_CRTC_OFFSET] << 3;
08e48902 1103
4fa0f5d2 1104 /* starting address */
f9b925fd 1105 params->start_addr = s->cr[VGA_CRTC_START_LO] |
5e55efc9 1106 (s->cr[VGA_CRTC_START_HI] << 8);
83acc96b
FB
1107
1108 /* line compare */
f9b925fd 1109 params->line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
5e55efc9
BS
1110 ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
1111 ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
973a724e
PB
1112
1113 params->hpel = s->ar[VGA_ATC_PEL];
1114 params->hpel_split = s->ar[VGA_ATC_MODE] & 0x20;
4fa0f5d2 1115 }
798b0c25
FB
1116}
1117
1118/* update start_addr and line_offset. Return TRUE if modified */
cedd91d2 1119static int update_basic_params(VGACommonState *s)
798b0c25
FB
1120{
1121 int full_update;
f9b925fd 1122 VGADisplayParams current;
3b46e624 1123
798b0c25
FB
1124 full_update = 0;
1125
f9b925fd 1126 s->get_params(s, &current);
e89f66ec 1127
f9b925fd
PB
1128 if (memcmp(&current, &s->params, sizeof(current))) {
1129 s->params = current;
e89f66ec
FB
1130 full_update = 1;
1131 }
1132 return full_update;
1133}
1134
3b46e624 1135
e89f66ec
FB
1136static const uint8_t cursor_glyph[32 * 4] = {
1137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1138 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1140 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1141 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1142 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1143 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1144 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1148 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1149 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1150 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1152 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3b46e624 1153};
e89f66ec 1154
cedd91d2 1155static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
4c5e8c5c
BS
1156 int *pcwidth, int *pcheight)
1157{
1158 int width, cwidth, height, cheight;
1159
1160 /* total width & height */
5e55efc9 1161 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
4c5e8c5c 1162 cwidth = 8;
94ef4f33 1163 if (!(sr(s, VGA_SEQ_CLOCK_MODE) & VGA_SR01_CHAR_CLK_8DOTS)) {
4c5e8c5c 1164 cwidth = 9;
5e55efc9 1165 }
94ef4f33 1166 if (sr(s, VGA_SEQ_CLOCK_MODE) & 0x08) {
4c5e8c5c 1167 cwidth = 16; /* NOTE: no 18 pixel wide */
5e55efc9
BS
1168 }
1169 width = (s->cr[VGA_CRTC_H_DISP] + 1);
1170 if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
4c5e8c5c
BS
1171 /* ugly hack for CGA 160x100x16 - explain me the logic */
1172 height = 100;
1173 } else {
5e55efc9
BS
1174 height = s->cr[VGA_CRTC_V_DISP_END] |
1175 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1176 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
4c5e8c5c
BS
1177 height = (height + 1) / cheight;
1178 }
1179
1180 *pwidth = width;
1181 *pheight = height;
1182 *pcwidth = cwidth;
1183 *pcheight = cheight;
1184}
1185
5fafdf24
TS
1186/*
1187 * Text mode update
e89f66ec
FB
1188 * Missing:
1189 * - double scan
5fafdf24 1190 * - double width
e89f66ec
FB
1191 * - underline
1192 * - flashing
1193 */
cedd91d2 1194static void vga_draw_text(VGACommonState *s, int full_update)
e89f66ec 1195{
c78f7137 1196 DisplaySurface *surface = qemu_console_surface(s->con);
e89f66ec 1197 int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
cae334cd 1198 int cx_min, cx_max, linesize, x_incr, line, line1;
e89f66ec 1199 uint32_t offset, fgcol, bgcol, v, cursor_offset;
d1984194 1200 uint8_t *d1, *d, *src, *dest, *cursor_ptr;
e89f66ec 1201 const uint8_t *font_ptr, *font_base[2];
9e057c0b 1202 int dup9, line_offset;
e89f66ec
FB
1203 uint32_t *palette;
1204 uint32_t *ch_attr_ptr;
bc72ad67 1205 int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
e89f66ec 1206
e89f66ec 1207 /* compute font data address (in plane 2) */
94ef4f33 1208 v = sr(s, VGA_SEQ_CHARACTER_MAP);
1078f663 1209 offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
e89f66ec
FB
1210 if (offset != s->font_offsets[0]) {
1211 s->font_offsets[0] = offset;
1212 full_update = 1;
1213 }
1214 font_base[0] = s->vram_ptr + offset;
1215
1078f663 1216 offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
e89f66ec
FB
1217 font_base[1] = s->vram_ptr + offset;
1218 if (offset != s->font_offsets[1]) {
1219 s->font_offsets[1] = offset;
1220 full_update = 1;
1221 }
ad37168c 1222 if (s->plane_updated & (1 << 2) || s->has_chain4_alias) {
546fa6ab
FB
1223 /* if the plane 2 was modified since the last display, it
1224 indicates the font may have been modified */
1225 s->plane_updated = 0;
1226 full_update = 1;
1227 }
799e709b 1228 full_update |= update_basic_params(s);
e89f66ec 1229
f9b925fd 1230 line_offset = s->params.line_offset;
e89f66ec 1231
4c5e8c5c 1232 vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1b296044
SW
1233 if ((height * width) <= 1) {
1234 /* better than nothing: exit if transient size is too small */
1235 return;
1236 }
3294b949
FB
1237 if ((height * width) > CH_ATTR_SIZE) {
1238 /* better than nothing: exit if transient size is too big */
1239 return;
1240 }
1241
799e709b
AL
1242 if (width != s->last_width || height != s->last_height ||
1243 cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1244 s->last_scr_width = width * cw;
1245 s->last_scr_height = height * cheight;
c78f7137
GH
1246 qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
1247 surface = qemu_console_surface(s->con);
1248 dpy_text_resize(s->con, width, height);
799e709b
AL
1249 s->last_depth = 0;
1250 s->last_width = width;
1251 s->last_height = height;
1252 s->last_ch = cheight;
1253 s->last_cw = cw;
1254 full_update = 1;
1255 }
7d957bd8
AL
1256 full_update |= update_palette16(s);
1257 palette = s->last_palette;
c78f7137 1258 x_incr = cw * surface_bytes_per_pixel(surface);
7d957bd8 1259
9678aedd
GH
1260 if (full_update) {
1261 s->full_update_text = 1;
1262 }
1263 if (s->full_update_gfx) {
1264 s->full_update_gfx = 0;
1265 full_update |= 1;
1266 }
1267
5e55efc9 1268 cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
f9b925fd 1269 s->cr[VGA_CRTC_CURSOR_LO]) - s->params.start_addr;
e89f66ec 1270 if (cursor_offset != s->cursor_offset ||
5e55efc9
BS
1271 s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1272 s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
e89f66ec
FB
1273 /* if the cursor position changed, we update the old and new
1274 chars */
1275 if (s->cursor_offset < CH_ATTR_SIZE)
1276 s->last_ch_attr[s->cursor_offset] = -1;
1277 if (cursor_offset < CH_ATTR_SIZE)
1278 s->last_ch_attr[cursor_offset] = -1;
1279 s->cursor_offset = cursor_offset;
5e55efc9
BS
1280 s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1281 s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
e89f66ec 1282 }
f9b925fd 1283 cursor_ptr = s->vram_ptr + (s->params.start_addr + cursor_offset) * 4;
9aa0ff0b
JK
1284 if (now >= s->cursor_blink_time) {
1285 s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
1286 s->cursor_visible_phase = !s->cursor_visible_phase;
1287 }
3b46e624 1288
c78f7137
GH
1289 dest = surface_data(surface);
1290 linesize = surface_stride(surface);
e89f66ec 1291 ch_attr_ptr = s->last_ch_attr;
d1984194 1292 line = 0;
f9b925fd 1293 offset = s->params.start_addr * 4;
e89f66ec
FB
1294 for(cy = 0; cy < height; cy++) {
1295 d1 = dest;
d1984194 1296 src = s->vram_ptr + offset;
e89f66ec
FB
1297 cx_min = width;
1298 cx_max = -1;
1299 for(cx = 0; cx < width; cx++) {
191f59dc 1300 if (src + sizeof(uint16_t) > s->vram_ptr + s->vram_size) {
1301 break;
1302 }
e89f66ec 1303 ch_attr = *(uint16_t *)src;
9aa0ff0b 1304 if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
e89f66ec
FB
1305 if (cx < cx_min)
1306 cx_min = cx;
1307 if (cx > cx_max)
1308 cx_max = cx;
1309 *ch_attr_ptr = ch_attr;
e03b5686 1310#if HOST_BIG_ENDIAN
e89f66ec
FB
1311 ch = ch_attr >> 8;
1312 cattr = ch_attr & 0xff;
1313#else
1314 ch = ch_attr & 0xff;
1315 cattr = ch_attr >> 8;
1316#endif
1317 font_ptr = font_base[(cattr >> 3) & 1];
1318 font_ptr += 32 * 4 * ch;
1319 bgcol = palette[cattr >> 4];
1320 fgcol = palette[cattr & 0x0f];
9e057c0b 1321 if (cw == 16) {
d2e043a8
BH
1322 vga_draw_glyph16(d1, linesize,
1323 font_ptr, cheight, fgcol, bgcol);
9e057c0b 1324 } else if (cw != 9) {
d2e043a8
BH
1325 vga_draw_glyph8(d1, linesize,
1326 font_ptr, cheight, fgcol, bgcol);
e89f66ec
FB
1327 } else {
1328 dup9 = 0;
5e55efc9
BS
1329 if (ch >= 0xb0 && ch <= 0xdf &&
1330 (s->ar[VGA_ATC_MODE] & 0x04)) {
e89f66ec 1331 dup9 = 1;
5e55efc9 1332 }
d2e043a8
BH
1333 vga_draw_glyph9(d1, linesize,
1334 font_ptr, cheight, fgcol, bgcol, dup9);
e89f66ec
FB
1335 }
1336 if (src == cursor_ptr &&
9aa0ff0b
JK
1337 !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
1338 s->cursor_visible_phase) {
e89f66ec
FB
1339 int line_start, line_last, h;
1340 /* draw the cursor */
5e55efc9
BS
1341 line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
1342 line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
e89f66ec
FB
1343 /* XXX: check that */
1344 if (line_last > cheight - 1)
1345 line_last = cheight - 1;
1346 if (line_last >= line_start && line_start < cheight) {
1347 h = line_last - line_start + 1;
1348 d = d1 + linesize * line_start;
9e057c0b 1349 if (cw == 16) {
d2e043a8
BH
1350 vga_draw_glyph16(d, linesize,
1351 cursor_glyph, h, fgcol, bgcol);
9e057c0b 1352 } else if (cw != 9) {
d2e043a8
BH
1353 vga_draw_glyph8(d, linesize,
1354 cursor_glyph, h, fgcol, bgcol);
e89f66ec 1355 } else {
d2e043a8
BH
1356 vga_draw_glyph9(d, linesize,
1357 cursor_glyph, h, fgcol, bgcol, 1);
e89f66ec
FB
1358 }
1359 }
1360 }
1361 }
1362 d1 += x_incr;
1363 src += 4;
1364 ch_attr_ptr++;
1365 }
1366 if (cx_max != -1) {
c78f7137 1367 dpy_gfx_update(s->con, cx_min * cw, cy * cheight,
a93a4a22 1368 (cx_max - cx_min + 1) * cw, cheight);
e89f66ec
FB
1369 }
1370 dest += linesize * cheight;
cae334cd 1371 line1 = line + cheight;
1372 offset += line_offset;
f9b925fd 1373 if (line < s->params.line_compare && line1 >= s->params.line_compare) {
d1984194 1374 offset = 0;
1375 }
cae334cd 1376 line = line1;
e89f66ec
FB
1377 }
1378}
1379
17b0018b
FB
1380enum {
1381 VGA_DRAW_LINE2,
1382 VGA_DRAW_LINE2D2,
1383 VGA_DRAW_LINE4,
1384 VGA_DRAW_LINE4D2,
1385 VGA_DRAW_LINE8D2,
1386 VGA_DRAW_LINE8,
46c3a8c8
BH
1387 VGA_DRAW_LINE15_LE,
1388 VGA_DRAW_LINE16_LE,
1389 VGA_DRAW_LINE24_LE,
1390 VGA_DRAW_LINE32_LE,
1391 VGA_DRAW_LINE15_BE,
1392 VGA_DRAW_LINE16_BE,
1393 VGA_DRAW_LINE24_BE,
1394 VGA_DRAW_LINE32_BE,
17b0018b
FB
1395 VGA_DRAW_LINE_NB,
1396};
1397
9e057c0b 1398static vga_draw_line_func * const vga_draw_line_table[VGA_DRAW_LINE_NB] = {
d2e043a8
BH
1399 vga_draw_line2,
1400 vga_draw_line2d2,
1401 vga_draw_line4,
1402 vga_draw_line4d2,
1403 vga_draw_line8d2,
1404 vga_draw_line8,
46c3a8c8
BH
1405 vga_draw_line15_le,
1406 vga_draw_line16_le,
1407 vga_draw_line24_le,
1408 vga_draw_line32_le,
1409 vga_draw_line15_be,
1410 vga_draw_line16_be,
1411 vga_draw_line24_be,
1412 vga_draw_line32_be,
d3079cd2
FB
1413};
1414
cedd91d2 1415static int vga_get_bpp(VGACommonState *s)
798b0c25
FB
1416{
1417 int ret;
a96d8bea 1418
bfa0f151 1419 if (vbe_enabled(s)) {
798b0c25 1420 ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
a96d8bea 1421 } else {
798b0c25
FB
1422 ret = 0;
1423 }
1424 return ret;
1425}
1426
cedd91d2 1427static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
a130a41e
FB
1428{
1429 int width, height;
3b46e624 1430
bfa0f151 1431 if (vbe_enabled(s)) {
8454df8b
FB
1432 width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1433 height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
a96d8bea 1434 } else {
5e55efc9
BS
1435 width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
1436 height = s->cr[VGA_CRTC_V_DISP_END] |
1437 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1438 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
8454df8b
FB
1439 height = (height + 1);
1440 }
a130a41e
FB
1441 *pwidth = width;
1442 *pheight = height;
1443}
1444
cedd91d2 1445void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
a8aa669b
FB
1446{
1447 int y;
1448 if (y1 >= VGA_MAX_HEIGHT)
1449 return;
1450 if (y2 >= VGA_MAX_HEIGHT)
1451 y2 = VGA_MAX_HEIGHT;
1452 for(y = y1; y < y2; y++) {
1453 s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1454 }
1455}
1456
f3289f6f
GH
1457static bool vga_scanline_invalidated(VGACommonState *s, int y)
1458{
1459 if (y >= VGA_MAX_HEIGHT) {
1460 return false;
1461 }
1462 return s->invalidated_y_table[y >> 5] & (1 << (y & 0x1f));
1463}
1464
50af3246
JQ
1465void vga_dirty_log_start(VGACommonState *s)
1466{
b1950430 1467 memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
b5cc6e32
AL
1468}
1469
1470void vga_dirty_log_stop(VGACommonState *s)
1471{
b1950430 1472 memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
b5cc6e32
AL
1473}
1474
799e709b
AL
1475/*
1476 * graphic modes
1477 */
cedd91d2 1478static void vga_draw_graphic(VGACommonState *s, int full_update)
e89f66ec 1479{
c78f7137 1480 DisplaySurface *surface = qemu_console_surface(s->con);
12c7e75a 1481 int y1, y, update, linesize, y_start, double_scan, mask, depth;
362f8117 1482 int width, height, shift_control, bwidth, bits;
28f77de2 1483 ram_addr_t page0, page1, region_start, region_end;
fec5e8c9 1484 DirtyBitmapSnapshot *snap = NULL;
a07cf92a 1485 int disp_width, multi_scan, multi_run;
973a724e 1486 int hpel;
799e709b
AL
1487 uint8_t *d;
1488 uint32_t v, addr1, addr;
2c7d8736 1489 vga_draw_line_func *vga_draw_line = NULL;
28f77de2 1490 bool share_surface, force_shadow = false;
49743df3 1491 pixman_format_code_t format;
e03b5686 1492#if HOST_BIG_ENDIAN
2c7d8736 1493 bool byteswap = !s->big_endian_fb;
46c3a8c8 1494#else
2c7d8736 1495 bool byteswap = s->big_endian_fb;
b1424e03 1496#endif
799e709b
AL
1497
1498 full_update |= update_basic_params(s);
1499
a130a41e 1500 s->get_resolution(s, &width, &height);
17b0018b 1501 disp_width = width;
a89fe6c3 1502 depth = s->get_bpp(s);
09a79b49 1503
37e7b867 1504 /* bits 5-6: 0 = 16-color mode, 1 = 4-color mode, 2 = 256-color mode. */
5e55efc9
BS
1505 shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1506 double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
37e7b867 1507 if (s->cr[VGA_CRTC_MODE] & 1) {
5e55efc9
BS
1508 multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1509 - 1;
799e709b
AL
1510 } else {
1511 /* in CGA modes, multi_scan is ignored */
1512 /* XXX: is it correct ? */
1513 multi_scan = double_scan;
1514 }
1515 multi_run = multi_scan;
17b0018b
FB
1516 if (shift_control != s->shift_control ||
1517 double_scan != s->double_scan) {
799e709b 1518 full_update = 1;
e89f66ec 1519 s->shift_control = shift_control;
17b0018b 1520 s->double_scan = double_scan;
e89f66ec 1521 }
3b46e624 1522
aba35a6c 1523 if (shift_control == 0) {
5c00aceb 1524 full_update |= update_palette16(s);
94ef4f33 1525 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
aba35a6c 1526 disp_width <<= 1;
5c00aceb
PB
1527 v = VGA_DRAW_LINE4D2;
1528 } else {
1529 v = VGA_DRAW_LINE4;
aba35a6c 1530 }
5c00aceb
PB
1531 bits = 4;
1532
aba35a6c 1533 } else if (shift_control == 1) {
5c00aceb 1534 full_update |= update_palette16(s);
94ef4f33 1535 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
aba35a6c 1536 disp_width <<= 1;
5c00aceb
PB
1537 v = VGA_DRAW_LINE2D2;
1538 } else {
1539 v = VGA_DRAW_LINE2;
1540 }
1541 bits = 4;
1542
1543 } else {
1544 switch (depth) {
1545 default:
1546 case 0:
1547 full_update |= update_palette256(s);
1548 v = VGA_DRAW_LINE8D2;
1549 bits = 4;
1550 break;
1551 case 8:
1552 full_update |= update_palette256(s);
1553 v = VGA_DRAW_LINE8;
1554 bits = 8;
1555 break;
1556 case 15:
1557 v = s->big_endian_fb ? VGA_DRAW_LINE15_BE : VGA_DRAW_LINE15_LE;
1558 bits = 16;
1559 break;
1560 case 16:
1561 v = s->big_endian_fb ? VGA_DRAW_LINE16_BE : VGA_DRAW_LINE16_LE;
1562 bits = 16;
1563 break;
1564 case 24:
1565 v = s->big_endian_fb ? VGA_DRAW_LINE24_BE : VGA_DRAW_LINE24_LE;
1566 bits = 24;
1567 break;
1568 case 32:
1569 v = s->big_endian_fb ? VGA_DRAW_LINE32_BE : VGA_DRAW_LINE32_LE;
1570 bits = 32;
1571 break;
aba35a6c 1572 }
1573 }
1d1ee7e0
PB
1574
1575 /* Horizontal pel panning bit 3 is only used in text mode. */
1576 hpel = bits <= 8 ? s->params.hpel & 7 : 0;
ab75ecb7 1577 bwidth = DIV_ROUND_UP(width * bits, 8); /* scanline length */
3b6d2b19 1578 if (hpel) {
ab75ecb7 1579 bwidth += 4;
3b6d2b19 1580 }
ab75ecb7
PB
1581
1582 region_start = (s->params.start_addr * 4);
1583 region_end = region_start + (ram_addr_t)s->params.line_offset * (height - 1) + bwidth;
1584 if (region_end > s->vbe_size) {
3826a372 1585 /*
ab75ecb7 1586 * On wrap around take the safe and slow route:
3826a372
PB
1587 * - create a dirty bitmap snapshot for all vga memory.
1588 * - force shadowing (so all vga memory access goes
1589 * through vga_read_*() helpers).
1590 *
1591 * Given this affects only vga features which are pretty much
1592 * unused by modern guests there should be no performance
1593 * impact.
1594 */
1595 region_start = 0;
1596 region_end = s->vbe_size;
1597 force_shadow = true;
1598 }
f89761d3
PB
1599 if (s->params.line_compare < height) {
1600 /* split screen mode */
1601 region_start = 0;
1602 }
3826a372 1603
49743df3
BH
1604 /*
1605 * Check whether we can share the surface with the backend
1606 * or whether we need a shadow surface. We share native
1607 * endian surfaces for 15bpp and above and byteswapped
1608 * surfaces for 24bpp and above.
1609 */
1610 format = qemu_default_pixman_format(depth, !byteswap);
1611 if (format) {
1612 share_surface = dpy_gfx_check_format(s->con, format)
28f77de2 1613 && !s->force_shadow && !force_shadow;
49743df3
BH
1614 } else {
1615 share_surface = false;
1616 }
6bc2fd57 1617
f9b925fd 1618 if (s->params.line_offset != s->last_line_offset ||
e3697092
AJ
1619 disp_width != s->last_width ||
1620 height != s->last_height ||
c3b10605 1621 s->last_depth != depth ||
55080993
BH
1622 s->last_byteswap != byteswap ||
1623 share_surface != is_buffer_shared(surface)) {
6bc2fd57
GH
1624 /* display parameters changed -> need new display surface */
1625 s->last_scr_width = disp_width;
1626 s->last_scr_height = height;
1627 s->last_width = disp_width;
1628 s->last_height = height;
f9b925fd 1629 s->last_line_offset = s->params.line_offset;
6bc2fd57
GH
1630 s->last_depth = depth;
1631 s->last_byteswap = byteswap;
973a724e
PB
1632 /* 16 extra pixels are needed for double-width planar modes. */
1633 s->panning_buf = g_realloc(s->panning_buf,
1634 (disp_width + 16) * sizeof(uint32_t));
6bc2fd57
GH
1635 full_update = 1;
1636 }
f9b925fd 1637 if (surface_data(surface) != s->vram_ptr + (s->params.start_addr * 4)
6bc2fd57
GH
1638 && is_buffer_shared(surface)) {
1639 /* base address changed (page flip) -> shared display surfaces
1640 * must be updated with the new base address */
1641 full_update = 1;
1642 }
1643
1644 if (full_update) {
55080993 1645 if (share_surface) {
da229ef3 1646 surface = qemu_create_displaysurface_from(disp_width,
f9b925fd
PB
1647 height, format, s->params.line_offset,
1648 s->vram_ptr + (s->params.start_addr * 4));
c78f7137 1649 dpy_gfx_replace_surface(s->con, surface);
e3697092 1650 } else {
c78f7137
GH
1651 qemu_console_resize(s->con, disp_width, height);
1652 surface = qemu_console_surface(s->con);
e3697092 1653 }
e3697092
AJ
1654 }
1655
9e057c0b 1656 vga_draw_line = vga_draw_line_table[v];
17b0018b 1657
c78f7137 1658 if (!is_buffer_shared(surface) && s->cursor_invalidate) {
a8aa669b 1659 s->cursor_invalidate(s);
c78f7137 1660 }
3b46e624 1661
17b0018b 1662#if 0
f6c958c8 1663 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",
5e55efc9 1664 width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
f9b925fd 1665 s->params.line_compare, sr(s, VGA_SEQ_CLOCK_MODE));
17b0018b 1666#endif
f9b925fd 1667 addr1 = (s->params.start_addr * 4);
39cf7803 1668 y_start = -1;
c78f7137
GH
1669 d = surface_data(surface);
1670 linesize = surface_stride(surface);
17b0018b 1671 y1 = 0;
fec5e8c9
GH
1672
1673 if (!full_update) {
e6529415
GH
1674 snap = memory_region_snapshot_and_clear_dirty(&s->vram, region_start,
1675 region_end - region_start,
fec5e8c9
GH
1676 DIRTY_MEMORY_VGA);
1677 }
1678
e89f66ec
FB
1679 for(y = 0; y < height; y++) {
1680 addr = addr1;
5e55efc9 1681 if (!(s->cr[VGA_CRTC_MODE] & 1)) {
17b0018b 1682 int shift;
e89f66ec 1683 /* CGA compatibility handling */
5e55efc9 1684 shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
17b0018b 1685 addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
e89f66ec 1686 }
5e55efc9 1687 if (!(s->cr[VGA_CRTC_MODE] & 2)) {
17b0018b 1688 addr = (addr & ~0x8000) | ((y1 & 2) << 14);
e89f66ec 1689 }
28f77de2
GH
1690 page0 = addr & s->vbe_size_mask;
1691 page1 = (addr + bwidth - 1) & s->vbe_size_mask;
fec5e8c9
GH
1692 if (full_update) {
1693 update = 1;
28f77de2
GH
1694 } else if (page1 < page0) {
1695 /* scanline wraps from end of video memory to the start */
1696 assert(force_shadow);
1697 update = memory_region_snapshot_get_dirty(&s->vram, snap,
115788d7 1698 page0, s->vbe_size - page0);
28f77de2 1699 update |= memory_region_snapshot_get_dirty(&s->vram, snap,
115788d7 1700 0, page1);
fec5e8c9
GH
1701 } else {
1702 update = memory_region_snapshot_get_dirty(&s->vram, snap,
1703 page0, page1 - page0);
1704 }
f3289f6f
GH
1705 /* explicit invalidation for the hardware cursor (cirrus only) */
1706 update |= vga_scanline_invalidated(s, y);
e89f66ec 1707 if (update) {
39cf7803
FB
1708 if (y_start < 0)
1709 y_start = y;
c78f7137 1710 if (!(is_buffer_shared(surface))) {
973a724e
PB
1711 uint8_t *p;
1712 p = vga_draw_line(s, d, addr, width, hpel);
1713 if (p) {
1714 memcpy(d, p, disp_width * sizeof(uint32_t));
1715 }
7d957bd8
AL
1716 if (s->cursor_draw_line)
1717 s->cursor_draw_line(s, d, y);
1718 }
39cf7803
FB
1719 } else {
1720 if (y_start >= 0) {
1721 /* flush to display */
c78f7137 1722 dpy_gfx_update(s->con, 0, y_start,
a93a4a22 1723 disp_width, y - y_start);
39cf7803
FB
1724 y_start = -1;
1725 }
e89f66ec 1726 }
a07cf92a 1727 if (!multi_run) {
5e55efc9 1728 mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
f6c958c8 1729 if ((y1 & mask) == mask)
f9b925fd 1730 addr1 += s->params.line_offset;
f6c958c8 1731 y1++;
799e709b 1732 multi_run = multi_scan;
a07cf92a
FB
1733 } else {
1734 multi_run--;
e89f66ec 1735 }
f6c958c8 1736 /* line compare acts on the displayed lines */
973a724e
PB
1737 if (y == s->params.line_compare) {
1738 if (s->params.hpel_split) {
1739 hpel = VGA_HPEL_NEUTRAL;
1740 }
f6c958c8 1741 addr1 = 0;
973a724e 1742 }
e89f66ec
FB
1743 d += linesize;
1744 }
39cf7803
FB
1745 if (y_start >= 0) {
1746 /* flush to display */
c78f7137 1747 dpy_gfx_update(s->con, 0, y_start,
a93a4a22 1748 disp_width, y - y_start);
39cf7803 1749 }
fec5e8c9 1750 g_free(snap);
f3289f6f 1751 memset(s->invalidated_y_table, 0, sizeof(s->invalidated_y_table));
e89f66ec
FB
1752}
1753
cedd91d2 1754static void vga_draw_blank(VGACommonState *s, int full_update)
2aebb3eb 1755{
c78f7137 1756 DisplaySurface *surface = qemu_console_surface(s->con);
2c79f2a2 1757 int i, w;
2aebb3eb
FB
1758 uint8_t *d;
1759
1760 if (!full_update)
1761 return;
1762 if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1763 return;
2bec46dc 1764
c78f7137
GH
1765 w = s->last_scr_width * surface_bytes_per_pixel(surface);
1766 d = surface_data(surface);
2aebb3eb 1767 for(i = 0; i < s->last_scr_height; i++) {
2c79f2a2 1768 memset(d, 0, w);
c78f7137 1769 d += surface_stride(surface);
2aebb3eb 1770 }
91155f8b 1771 dpy_gfx_update_full(s->con);
2aebb3eb
FB
1772}
1773
799e709b
AL
1774#define GMODE_TEXT 0
1775#define GMODE_GRAPH 1
1776#define GMODE_BLANK 2
1777
95219897 1778static void vga_update_display(void *opaque)
e89f66ec 1779{
cedd91d2 1780 VGACommonState *s = opaque;
c78f7137 1781 DisplaySurface *surface = qemu_console_surface(s->con);
799e709b 1782 int full_update, graphic_mode;
e89f66ec 1783
e9a07334
JK
1784 qemu_flush_coalesced_mmio_buffer();
1785
c78f7137 1786 if (surface_bits_per_pixel(surface) == 0) {
0f35920c 1787 /* nothing to do */
59a983b9 1788 } else {
3098b9fd 1789 full_update = 0;
df800210 1790 if (!(s->ar_index & 0x20)) {
799e709b
AL
1791 graphic_mode = GMODE_BLANK;
1792 } else {
5e55efc9 1793 graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
799e709b
AL
1794 }
1795 if (graphic_mode != s->graphic_mode) {
1796 s->graphic_mode = graphic_mode;
bc72ad67 1797 s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
799e709b
AL
1798 full_update = 1;
1799 }
1800 switch(graphic_mode) {
2aebb3eb 1801 case GMODE_TEXT:
e89f66ec 1802 vga_draw_text(s, full_update);
2aebb3eb
FB
1803 break;
1804 case GMODE_GRAPH:
1805 vga_draw_graphic(s, full_update);
1806 break;
1807 case GMODE_BLANK:
1808 default:
1809 vga_draw_blank(s, full_update);
1810 break;
1811 }
e89f66ec
FB
1812 }
1813}
1814
a130a41e 1815/* force a full display refresh */
95219897 1816static void vga_invalidate_display(void *opaque)
a130a41e 1817{
cedd91d2 1818 VGACommonState *s = opaque;
3b46e624 1819
3098b9fd
AJ
1820 s->last_width = -1;
1821 s->last_height = -1;
a130a41e
FB
1822}
1823
03a3e7ba 1824void vga_common_reset(VGACommonState *s)
e89f66ec 1825{
6e6b7363
BS
1826 s->sr_index = 0;
1827 memset(s->sr, '\0', sizeof(s->sr));
94ef4f33 1828 memset(s->sr_vbe, '\0', sizeof(s->sr_vbe));
6e6b7363
BS
1829 s->gr_index = 0;
1830 memset(s->gr, '\0', sizeof(s->gr));
1831 s->ar_index = 0;
1832 memset(s->ar, '\0', sizeof(s->ar));
1833 s->ar_flip_flop = 0;
1834 s->cr_index = 0;
1835 memset(s->cr, '\0', sizeof(s->cr));
1836 s->msr = 0;
1837 s->fcr = 0;
1838 s->st00 = 0;
1839 s->st01 = 0;
1840 s->dac_state = 0;
1841 s->dac_sub_index = 0;
1842 s->dac_read_index = 0;
1843 s->dac_write_index = 0;
1844 memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1845 s->dac_8bit = 0;
1846 memset(s->palette, '\0', sizeof(s->palette));
1847 s->bank_offset = 0;
6e6b7363
BS
1848 s->vbe_index = 0;
1849 memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
af92284b 1850 s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
6e6b7363
BS
1851 s->vbe_start_addr = 0;
1852 s->vbe_line_offset = 0;
1853 s->vbe_bank_mask = (s->vram_size >> 16) - 1;
6e6b7363 1854 memset(s->font_offsets, '\0', sizeof(s->font_offsets));
799e709b 1855 s->graphic_mode = -1; /* force full update */
6e6b7363
BS
1856 s->shift_control = 0;
1857 s->double_scan = 0;
f9b925fd 1858 memset(&s->params, '\0', sizeof(s->params));
6e6b7363
BS
1859 s->plane_updated = 0;
1860 s->last_cw = 0;
1861 s->last_ch = 0;
1862 s->last_width = 0;
1863 s->last_height = 0;
1864 s->last_scr_width = 0;
1865 s->last_scr_height = 0;
1866 s->cursor_start = 0;
1867 s->cursor_end = 0;
1868 s->cursor_offset = 0;
c3b10605 1869 s->big_endian_fb = s->default_endian_fb;
6e6b7363
BS
1870 memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1871 memset(s->last_palette, '\0', sizeof(s->last_palette));
1872 memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1873 switch (vga_retrace_method) {
1874 case VGA_RETRACE_DUMB:
1875 break;
1876 case VGA_RETRACE_PRECISE:
1877 memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1878 break;
1879 }
80763888 1880 vga_update_memory_access(s);
e89f66ec
FB
1881}
1882
03a3e7ba
JQ
1883static void vga_reset(void *opaque)
1884{
cedd91d2 1885 VGACommonState *s = opaque;
03a3e7ba
JQ
1886 vga_common_reset(s);
1887}
1888
4d3b6f6e
AZ
1889#define TEXTMODE_X(x) ((x) % width)
1890#define TEXTMODE_Y(x) ((x) / width)
1891#define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
1892 ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1893/* relay text rendering to the display driver
1894 * instead of doing a full vga_update_display() */
c227f099 1895static void vga_update_text(void *opaque, console_ch_t *chardata)
4d3b6f6e 1896{
cedd91d2 1897 VGACommonState *s = opaque;
799e709b 1898 int graphic_mode, i, cursor_offset, cursor_visible;
4d3b6f6e
AZ
1899 int cw, cheight, width, height, size, c_min, c_max;
1900 uint32_t *src;
c227f099 1901 console_ch_t *dst, val;
4d3b6f6e 1902 char msg_buffer[80];
799e709b
AL
1903 int full_update = 0;
1904
e9a07334
JK
1905 qemu_flush_coalesced_mmio_buffer();
1906
799e709b
AL
1907 if (!(s->ar_index & 0x20)) {
1908 graphic_mode = GMODE_BLANK;
1909 } else {
5e55efc9 1910 graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
799e709b
AL
1911 }
1912 if (graphic_mode != s->graphic_mode) {
1913 s->graphic_mode = graphic_mode;
1914 full_update = 1;
1915 }
1916 if (s->last_width == -1) {
1917 s->last_width = 0;
1918 full_update = 1;
1919 }
4d3b6f6e 1920
799e709b 1921 switch (graphic_mode) {
4d3b6f6e
AZ
1922 case GMODE_TEXT:
1923 /* TODO: update palette */
799e709b 1924 full_update |= update_basic_params(s);
4d3b6f6e 1925
799e709b 1926 /* total width & height */
5e55efc9 1927 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
799e709b 1928 cw = 8;
94ef4f33 1929 if (!(sr(s, VGA_SEQ_CLOCK_MODE) & VGA_SR01_CHAR_CLK_8DOTS)) {
799e709b 1930 cw = 9;
5e55efc9 1931 }
94ef4f33 1932 if (sr(s, VGA_SEQ_CLOCK_MODE) & 0x08) {
799e709b 1933 cw = 16; /* NOTE: no 18 pixel wide */
5e55efc9
BS
1934 }
1935 width = (s->cr[VGA_CRTC_H_DISP] + 1);
1936 if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
799e709b
AL
1937 /* ugly hack for CGA 160x100x16 - explain me the logic */
1938 height = 100;
1939 } else {
5e55efc9
BS
1940 height = s->cr[VGA_CRTC_V_DISP_END] |
1941 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1942 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
799e709b 1943 height = (height + 1) / cheight;
4d3b6f6e
AZ
1944 }
1945
1946 size = (height * width);
1947 if (size > CH_ATTR_SIZE) {
1948 if (!full_update)
1949 return;
1950
363a37d5
BS
1951 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1952 width, height);
4d3b6f6e
AZ
1953 break;
1954 }
1955
799e709b
AL
1956 if (width != s->last_width || height != s->last_height ||
1957 cw != s->last_cw || cheight != s->last_ch) {
1958 s->last_scr_width = width * cw;
1959 s->last_scr_height = height * cheight;
c78f7137
GH
1960 qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
1961 dpy_text_resize(s->con, width, height);
9678aedd 1962 s->last_depth = 0;
799e709b
AL
1963 s->last_width = width;
1964 s->last_height = height;
1965 s->last_ch = cheight;
1966 s->last_cw = cw;
1967 full_update = 1;
1968 }
1969
9678aedd
GH
1970 if (full_update) {
1971 s->full_update_gfx = 1;
1972 }
1973 if (s->full_update_text) {
1974 s->full_update_text = 0;
1975 full_update |= 1;
1976 }
1977
4d3b6f6e 1978 /* Update "hardware" cursor */
5e55efc9 1979 cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
f9b925fd 1980 s->cr[VGA_CRTC_CURSOR_LO]) - s->params.start_addr;
4d3b6f6e 1981 if (cursor_offset != s->cursor_offset ||
5e55efc9
BS
1982 s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1983 s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
1984 cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
4d3b6f6e 1985 if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
c78f7137 1986 dpy_text_cursor(s->con,
bf2fde70
GH
1987 TEXTMODE_X(cursor_offset),
1988 TEXTMODE_Y(cursor_offset));
4d3b6f6e 1989 else
c78f7137 1990 dpy_text_cursor(s->con, -1, -1);
4d3b6f6e 1991 s->cursor_offset = cursor_offset;
5e55efc9
BS
1992 s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1993 s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
4d3b6f6e
AZ
1994 }
1995
f9b925fd 1996 src = (uint32_t *) s->vram_ptr + s->params.start_addr;
4d3b6f6e
AZ
1997 dst = chardata;
1998
1999 if (full_update) {
2000 for (i = 0; i < size; src ++, dst ++, i ++)
9ae19b65 2001 console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
4d3b6f6e 2002
c78f7137 2003 dpy_text_update(s->con, 0, 0, width, height);
4d3b6f6e
AZ
2004 } else {
2005 c_max = 0;
2006
2007 for (i = 0; i < size; src ++, dst ++, i ++) {
9ae19b65 2008 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
4d3b6f6e
AZ
2009 if (*dst != val) {
2010 *dst = val;
2011 c_max = i;
2012 break;
2013 }
2014 }
2015 c_min = i;
2016 for (; i < size; src ++, dst ++, i ++) {
9ae19b65 2017 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
4d3b6f6e
AZ
2018 if (*dst != val) {
2019 *dst = val;
2020 c_max = i;
2021 }
2022 }
2023
2024 if (c_min <= c_max) {
2025 i = TEXTMODE_Y(c_min);
c78f7137 2026 dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
4d3b6f6e
AZ
2027 }
2028 }
2029
2030 return;
2031 case GMODE_GRAPH:
2032 if (!full_update)
2033 return;
2034
2035 s->get_resolution(s, &width, &height);
363a37d5
BS
2036 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2037 width, height);
4d3b6f6e
AZ
2038 break;
2039 case GMODE_BLANK:
2040 default:
2041 if (!full_update)
2042 return;
2043
363a37d5 2044 snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
4d3b6f6e
AZ
2045 break;
2046 }
2047
2048 /* Display a message */
5228c2d3
AZ
2049 s->last_width = 60;
2050 s->last_height = height = 3;
c78f7137
GH
2051 dpy_text_cursor(s->con, -1, -1);
2052 dpy_text_resize(s->con, s->last_width, height);
4d3b6f6e 2053
5228c2d3 2054 for (dst = chardata, i = 0; i < s->last_width * height; i ++)
4d3b6f6e
AZ
2055 console_write_ch(dst ++, ' ');
2056
2057 size = strlen(msg_buffer);
5228c2d3
AZ
2058 width = (s->last_width - size) / 2;
2059 dst = chardata + s->last_width + width;
4d3b6f6e 2060 for (i = 0; i < size; i ++)
4083733d
OH
2061 console_write_ch(dst ++, ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE,
2062 QEMU_COLOR_BLACK, 1));
4d3b6f6e 2063
c78f7137 2064 dpy_text_update(s->con, 0, 0, s->last_width, height);
4d3b6f6e
AZ
2065}
2066
a8170e5e 2067static uint64_t vga_mem_read(void *opaque, hwaddr addr,
b1950430
AK
2068 unsigned size)
2069{
2070 VGACommonState *s = opaque;
2071
b2a5e761 2072 return vga_mem_readb(s, addr);
b1950430 2073}
e89f66ec 2074
a8170e5e 2075static void vga_mem_write(void *opaque, hwaddr addr,
b1950430
AK
2076 uint64_t data, unsigned size)
2077{
2078 VGACommonState *s = opaque;
2079
e7ae771f 2080 vga_mem_writeb(s, addr, data);
b1950430
AK
2081}
2082
2083const MemoryRegionOps vga_mem_ops = {
2084 .read = vga_mem_read,
2085 .write = vga_mem_write,
2086 .endianness = DEVICE_LITTLE_ENDIAN,
b2a5e761
AK
2087 .impl = {
2088 .min_access_size = 1,
2089 .max_access_size = 1,
2090 },
e89f66ec
FB
2091};
2092
11b6b345 2093static int vga_common_post_load(void *opaque, int version_id)
b0a21b53 2094{
0d65ddc3 2095 VGACommonState *s = opaque;
11b6b345
JQ
2096
2097 /* force refresh */
2098 s->graphic_mode = -1;
94ef4f33 2099 vbe_update_vgaregs(s);
138bc2df 2100 vga_update_memory_access(s);
11b6b345
JQ
2101 return 0;
2102}
2103
c3b10605
BH
2104static bool vga_endian_state_needed(void *opaque)
2105{
2106 VGACommonState *s = opaque;
2107
2108 /*
2109 * Only send the endian state if it's different from the
2110 * default one, thus ensuring backward compatibility for
2111 * migration of the common case
2112 */
2113 return s->default_endian_fb != s->big_endian_fb;
2114}
2115
73d22caf 2116static const VMStateDescription vmstate_vga_endian = {
c3b10605
BH
2117 .name = "vga.endian",
2118 .version_id = 1,
2119 .minimum_version_id = 1,
5cd8cada 2120 .needed = vga_endian_state_needed,
f0613160 2121 .fields = (const VMStateField[]) {
c3b10605
BH
2122 VMSTATE_BOOL(big_endian_fb, VGACommonState),
2123 VMSTATE_END_OF_LIST()
2124 }
2125};
2126
11b6b345
JQ
2127const VMStateDescription vmstate_vga_common = {
2128 .name = "vga",
2129 .version_id = 2,
2130 .minimum_version_id = 2,
11b6b345 2131 .post_load = vga_common_post_load,
f0613160 2132 .fields = (const VMStateField[]) {
11b6b345
JQ
2133 VMSTATE_UINT32(latch, VGACommonState),
2134 VMSTATE_UINT8(sr_index, VGACommonState),
2135 VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2136 VMSTATE_UINT8(gr_index, VGACommonState),
2137 VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2138 VMSTATE_UINT8(ar_index, VGACommonState),
2139 VMSTATE_BUFFER(ar, VGACommonState),
2140 VMSTATE_INT32(ar_flip_flop, VGACommonState),
2141 VMSTATE_UINT8(cr_index, VGACommonState),
2142 VMSTATE_BUFFER(cr, VGACommonState),
2143 VMSTATE_UINT8(msr, VGACommonState),
2144 VMSTATE_UINT8(fcr, VGACommonState),
2145 VMSTATE_UINT8(st00, VGACommonState),
2146 VMSTATE_UINT8(st01, VGACommonState),
2147
2148 VMSTATE_UINT8(dac_state, VGACommonState),
2149 VMSTATE_UINT8(dac_sub_index, VGACommonState),
2150 VMSTATE_UINT8(dac_read_index, VGACommonState),
2151 VMSTATE_UINT8(dac_write_index, VGACommonState),
2152 VMSTATE_BUFFER(dac_cache, VGACommonState),
2153 VMSTATE_BUFFER(palette, VGACommonState),
2154
2155 VMSTATE_INT32(bank_offset, VGACommonState),
d2164ad3 2156 VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState, NULL),
11b6b345
JQ
2157 VMSTATE_UINT16(vbe_index, VGACommonState),
2158 VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2159 VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2160 VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2161 VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
11b6b345 2162 VMSTATE_END_OF_LIST()
c3b10605 2163 },
f0613160 2164 .subsections = (const VMStateDescription * const []) {
5cd8cada
JQ
2165 &vmstate_vga_endian,
2166 NULL
11b6b345
JQ
2167 }
2168};
2169
380cd056
GH
2170static const GraphicHwOps vga_ops = {
2171 .invalidate = vga_invalidate_display,
2172 .gfx_update = vga_update_display,
2173 .text_update = vga_update_text,
2174};
2175
619616ce
RK
2176static inline uint32_t uint_clamp(uint32_t val, uint32_t vmin, uint32_t vmax)
2177{
2178 if (val < vmin) {
2179 return vmin;
2180 }
2181 if (val > vmax) {
2182 return vmax;
2183 }
2184 return val;
2185}
2186
6832deb8 2187bool vga_common_init(VGACommonState *s, Object *obj, Error **errp)
e89f66ec 2188{
17b0018b 2189 int i, j, v, b;
6832deb8 2190 Error *local_err = NULL;
e89f66ec
FB
2191
2192 for(i = 0;i < 256; i++) {
2193 v = 0;
2194 for(j = 0; j < 8; j++) {
2195 v |= ((i >> j) & 1) << (j * 4);
2196 }
2197 expand4[i] = v;
2198
2199 v = 0;
2200 for(j = 0; j < 4; j++) {
2201 v |= ((i >> (2 * j)) & 3) << (j * 4);
2202 }
2203 expand2[i] = v;
2204 }
17b0018b
FB
2205 for(i = 0; i < 16; i++) {
2206 v = 0;
2207 for(j = 0; j < 4; j++) {
2208 b = ((i >> j) & 1);
2209 v |= b << (2 * j);
2210 v |= b << (2 * j + 1);
2211 }
2212 expand4to8[i] = v;
2213 }
e89f66ec 2214
619616ce
RK
2215 s->vram_size_mb = uint_clamp(s->vram_size_mb, 1, 512);
2216 s->vram_size_mb = pow2ceil(s->vram_size_mb);
f0353b0d 2217 s->vram_size = s->vram_size_mb * MiB;
619616ce 2218
54a85d46
GH
2219 if (!s->vbe_size) {
2220 s->vbe_size = s->vram_size;
2221 }
3d90c625 2222 s->vbe_size_mask = s->vbe_size - 1;
4a1e244e 2223
2a3138ab 2224 s->is_vbe_vmstate = 1;
9eb840a2
TH
2225
2226 if (s->global_vmstate && qemu_ram_block_by_name("vga.vram")) {
2227 error_setg(errp, "Only one global VGA device can be used at a time");
2228 return false;
2229 }
2230
1cfe48c1 2231 memory_region_init_ram_nomigrate(&s->vram, obj, "vga.vram", s->vram_size,
6832deb8
TH
2232 &local_err);
2233 if (local_err) {
2234 error_propagate(errp, local_err);
2235 return false;
2236 }
1fcfdc43 2237 vmstate_register_ram(&s->vram, s->global_vmstate ? NULL : DEVICE(obj));
c65adf9b 2238 xen_register_framebuffer(&s->vram);
b1950430 2239 s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
798b0c25 2240 s->get_bpp = vga_get_bpp;
f9b925fd 2241 s->get_params = vga_get_params;
a130a41e 2242 s->get_resolution = vga_get_resolution;
380cd056 2243 s->hw_ops = &vga_ops;
cb5a7aa8 2244 switch (vga_retrace_method) {
2245 case VGA_RETRACE_DUMB:
2246 s->retrace = vga_dumb_retrace;
2247 s->update_retrace_info = vga_dumb_update_retrace_info;
2248 break;
2249
2250 case VGA_RETRACE_PRECISE:
2251 s->retrace = vga_precise_retrace;
2252 s->update_retrace_info = vga_precise_update_retrace_info;
cb5a7aa8 2253 break;
2254 }
2c7d8736
BH
2255
2256 /*
c3b10605 2257 * Set default fb endian based on target, could probably be turned
2c7d8736
BH
2258 * into a device attribute set by the machine/platform to remove
2259 * all target endian dependencies from this file.
2260 */
9eb7e7e8
TH
2261 s->default_endian_fb = target_words_bigendian();
2262
b1950430 2263 vga_dirty_log_start(s);
6832deb8
TH
2264
2265 return true;
798b0c25
FB
2266}
2267
0a039dc7
RH
2268static const MemoryRegionPortio vga_portio_list[] = {
2269 { 0x04, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
2270 { 0x0a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
2271 { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
2272 { 0x24, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
2273 { 0x2a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
2274 PORTIO_END_OF_LIST(),
2275};
e89f66ec 2276
9eb7e7e8 2277static const MemoryRegionPortio vbe_portio_list_x86[] = {
0a039dc7 2278 { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
0a039dc7 2279 { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
9eb7e7e8
TH
2280 { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2281 PORTIO_END_OF_LIST(),
2282};
2283
2284static const MemoryRegionPortio vbe_portio_list_no_x86[] = {
2285 { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
df9ffb72 2286 { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
0a039dc7
RH
2287 PORTIO_END_OF_LIST(),
2288};
4fa0f5d2 2289
0a039dc7 2290/* Used by both ISA and PCI */
c84b28ee 2291MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
0a039dc7
RH
2292 const MemoryRegionPortio **vga_ports,
2293 const MemoryRegionPortio **vbe_ports)
2294{
2295 MemoryRegion *vga_mem;
9eb7e7e8
TH
2296 MachineState *ms = MACHINE(qdev_get_machine());
2297
2298 /*
2299 * We unfortunately need two VBE lists since non-x86 machines might
2300 * not be able to do 16-bit accesses at unaligned addresses (0x1cf)
2301 */
2302 if (object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) {
2303 *vbe_ports = vbe_portio_list_x86;
2304 } else {
2305 *vbe_ports = vbe_portio_list_no_x86;
2306 }
09a79b49 2307
0a039dc7 2308 *vga_ports = vga_portio_list;
4fa0f5d2 2309
7267c094 2310 vga_mem = g_malloc(sizeof(*vga_mem));
c84b28ee 2311 memory_region_init_io(vga_mem, obj, &vga_mem_ops, s,
b1950430 2312 "vga-lowmem", 0x20000);
bd8f2f5d 2313 memory_region_set_flush_coalesced(vga_mem);
b1950430
AK
2314
2315 return vga_mem;
7435b791
BS
2316}
2317
712f0cc7 2318void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
0a039dc7 2319 MemoryRegion *address_space_io, bool init_vga_ports)
7435b791 2320{
b1950430 2321 MemoryRegion *vga_io_memory;
0a039dc7 2322 const MemoryRegionPortio *vga_ports, *vbe_ports;
7435b791
BS
2323
2324 qemu_register_reset(vga_reset, s);
2325
2326 s->bank_offset = 0;
2327
80763888
JK
2328 s->legacy_address_space = address_space;
2329
c84b28ee 2330 vga_io_memory = vga_init_io(s, obj, &vga_ports, &vbe_ports);
be20f9e9 2331 memory_region_add_subregion_overlap(address_space,
b19c1c08 2332 0x000a0000,
b1950430
AK
2333 vga_io_memory,
2334 1);
2335 memory_region_set_coalescing(vga_io_memory);
0a039dc7 2336 if (init_vga_ports) {
848696bf
KB
2337 portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga");
2338 portio_list_set_flush_coalesced(&s->vga_port_list);
2339 portio_list_add(&s->vga_port_list, address_space_io, 0x3b0);
0a039dc7
RH
2340 }
2341 if (vbe_ports) {
848696bf
KB
2342 portio_list_init(&s->vbe_port_list, obj, vbe_ports, s, "vbe");
2343 portio_list_add(&s->vbe_port_list, address_space_io, 0x1ce);
0a039dc7 2344 }
d2269f6f 2345}