]> git.proxmox.com Git - mirror_qemu.git/blame - hw/display/vga.c
Merge tag 'pull-target-arm-20240402' of https://git.linaro.org/people/pmaydell/qemu...
[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
f9b925fd
PB
1504 region_start = (s->params.start_addr * 4);
1505 region_end = region_start + (ram_addr_t)s->params.line_offset * height;
a89fe6c3 1506 region_end += width * depth / 8; /* scanline length */
f9b925fd 1507 region_end -= s->params.line_offset;
a89fe6c3
GH
1508 if (region_end > s->vbe_size || depth == 0 || depth == 15) {
1509 /*
1510 * We land here on:
1511 * - wraps around (can happen with cirrus vbe modes)
1512 * - depth == 0 (256 color palette video mode)
1513 * - depth == 15
1514 *
1515 * Take the safe and slow route:
1516 * - create a dirty bitmap snapshot for all vga memory.
1517 * - force shadowing (so all vga memory access goes
1518 * through vga_read_*() helpers).
1519 *
1520 * Given this affects only vga features which are pretty much
1521 * unused by modern guests there should be no performance
1522 * impact.
1523 */
28f77de2
GH
1524 region_start = 0;
1525 region_end = s->vbe_size;
1526 force_shadow = true;
1527 }
1528
37e7b867 1529 /* bits 5-6: 0 = 16-color mode, 1 = 4-color mode, 2 = 256-color mode. */
5e55efc9
BS
1530 shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1531 double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
37e7b867 1532 if (s->cr[VGA_CRTC_MODE] & 1) {
5e55efc9
BS
1533 multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1534 - 1;
799e709b
AL
1535 } else {
1536 /* in CGA modes, multi_scan is ignored */
1537 /* XXX: is it correct ? */
1538 multi_scan = double_scan;
1539 }
1540 multi_run = multi_scan;
17b0018b
FB
1541 if (shift_control != s->shift_control ||
1542 double_scan != s->double_scan) {
799e709b 1543 full_update = 1;
e89f66ec 1544 s->shift_control = shift_control;
17b0018b 1545 s->double_scan = double_scan;
e89f66ec 1546 }
3b46e624 1547
aba35a6c 1548 if (shift_control == 0) {
94ef4f33 1549 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
aba35a6c 1550 disp_width <<= 1;
1551 }
1552 } else if (shift_control == 1) {
94ef4f33 1553 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
aba35a6c 1554 disp_width <<= 1;
1555 }
1556 }
1557
49743df3
BH
1558 /*
1559 * Check whether we can share the surface with the backend
1560 * or whether we need a shadow surface. We share native
1561 * endian surfaces for 15bpp and above and byteswapped
1562 * surfaces for 24bpp and above.
1563 */
1564 format = qemu_default_pixman_format(depth, !byteswap);
1565 if (format) {
1566 share_surface = dpy_gfx_check_format(s->con, format)
28f77de2 1567 && !s->force_shadow && !force_shadow;
49743df3
BH
1568 } else {
1569 share_surface = false;
1570 }
6bc2fd57 1571
f9b925fd 1572 if (s->params.line_offset != s->last_line_offset ||
e3697092
AJ
1573 disp_width != s->last_width ||
1574 height != s->last_height ||
c3b10605 1575 s->last_depth != depth ||
55080993
BH
1576 s->last_byteswap != byteswap ||
1577 share_surface != is_buffer_shared(surface)) {
6bc2fd57
GH
1578 /* display parameters changed -> need new display surface */
1579 s->last_scr_width = disp_width;
1580 s->last_scr_height = height;
1581 s->last_width = disp_width;
1582 s->last_height = height;
f9b925fd 1583 s->last_line_offset = s->params.line_offset;
6bc2fd57
GH
1584 s->last_depth = depth;
1585 s->last_byteswap = byteswap;
973a724e
PB
1586 /* 16 extra pixels are needed for double-width planar modes. */
1587 s->panning_buf = g_realloc(s->panning_buf,
1588 (disp_width + 16) * sizeof(uint32_t));
6bc2fd57
GH
1589 full_update = 1;
1590 }
f9b925fd 1591 if (surface_data(surface) != s->vram_ptr + (s->params.start_addr * 4)
6bc2fd57
GH
1592 && is_buffer_shared(surface)) {
1593 /* base address changed (page flip) -> shared display surfaces
1594 * must be updated with the new base address */
1595 full_update = 1;
1596 }
1597
1598 if (full_update) {
55080993 1599 if (share_surface) {
da229ef3 1600 surface = qemu_create_displaysurface_from(disp_width,
f9b925fd
PB
1601 height, format, s->params.line_offset,
1602 s->vram_ptr + (s->params.start_addr * 4));
c78f7137 1603 dpy_gfx_replace_surface(s->con, surface);
e3697092 1604 } else {
c78f7137
GH
1605 qemu_console_resize(s->con, disp_width, height);
1606 surface = qemu_console_surface(s->con);
e3697092 1607 }
e3697092
AJ
1608 }
1609
799e709b 1610 if (shift_control == 0) {
17b0018b 1611 full_update |= update_palette16(s);
94ef4f33 1612 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
17b0018b 1613 v = VGA_DRAW_LINE4D2;
17b0018b
FB
1614 } else {
1615 v = VGA_DRAW_LINE4;
1616 }
15342721 1617 bits = 4;
799e709b 1618 } else if (shift_control == 1) {
17b0018b 1619 full_update |= update_palette16(s);
94ef4f33 1620 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
17b0018b 1621 v = VGA_DRAW_LINE2D2;
17b0018b
FB
1622 } else {
1623 v = VGA_DRAW_LINE2;
1624 }
15342721 1625 bits = 4;
17b0018b 1626 } else {
798b0c25
FB
1627 switch(s->get_bpp(s)) {
1628 default:
1629 case 0:
4fa0f5d2
FB
1630 full_update |= update_palette256(s);
1631 v = VGA_DRAW_LINE8D2;
15342721 1632 bits = 4;
798b0c25
FB
1633 break;
1634 case 8:
1635 full_update |= update_palette256(s);
1636 v = VGA_DRAW_LINE8;
15342721 1637 bits = 8;
798b0c25
FB
1638 break;
1639 case 15:
2c7d8736 1640 v = s->big_endian_fb ? VGA_DRAW_LINE15_BE : VGA_DRAW_LINE15_LE;
15342721 1641 bits = 16;
798b0c25
FB
1642 break;
1643 case 16:
2c7d8736 1644 v = s->big_endian_fb ? VGA_DRAW_LINE16_BE : VGA_DRAW_LINE16_LE;
15342721 1645 bits = 16;
798b0c25
FB
1646 break;
1647 case 24:
2c7d8736 1648 v = s->big_endian_fb ? VGA_DRAW_LINE24_BE : VGA_DRAW_LINE24_LE;
15342721 1649 bits = 24;
798b0c25
FB
1650 break;
1651 case 32:
2c7d8736 1652 v = s->big_endian_fb ? VGA_DRAW_LINE32_BE : VGA_DRAW_LINE32_LE;
15342721 1653 bits = 32;
798b0c25 1654 break;
4fa0f5d2 1655 }
17b0018b 1656 }
9e057c0b 1657 vga_draw_line = vga_draw_line_table[v];
17b0018b 1658
c78f7137 1659 if (!is_buffer_shared(surface) && s->cursor_invalidate) {
a8aa669b 1660 s->cursor_invalidate(s);
c78f7137 1661 }
3b46e624 1662
17b0018b 1663#if 0
f6c958c8 1664 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 1665 width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
f9b925fd 1666 s->params.line_compare, sr(s, VGA_SEQ_CLOCK_MODE));
17b0018b 1667#endif
973a724e 1668 hpel = bits <= 8 ? s->params.hpel : 0;
f9b925fd 1669 addr1 = (s->params.start_addr * 4);
2c23ce22 1670 bwidth = DIV_ROUND_UP(width * bits, 8);
973a724e
PB
1671 if (hpel) {
1672 bwidth += 4;
1673 }
39cf7803 1674 y_start = -1;
c78f7137
GH
1675 d = surface_data(surface);
1676 linesize = surface_stride(surface);
17b0018b 1677 y1 = 0;
fec5e8c9
GH
1678
1679 if (!full_update) {
f9b925fd 1680 if (s->params.line_compare < height) {
e6529415
GH
1681 /* split screen mode */
1682 region_start = 0;
1683 }
1684 snap = memory_region_snapshot_and_clear_dirty(&s->vram, region_start,
1685 region_end - region_start,
fec5e8c9
GH
1686 DIRTY_MEMORY_VGA);
1687 }
1688
e89f66ec
FB
1689 for(y = 0; y < height; y++) {
1690 addr = addr1;
5e55efc9 1691 if (!(s->cr[VGA_CRTC_MODE] & 1)) {
17b0018b 1692 int shift;
e89f66ec 1693 /* CGA compatibility handling */
5e55efc9 1694 shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
17b0018b 1695 addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
e89f66ec 1696 }
5e55efc9 1697 if (!(s->cr[VGA_CRTC_MODE] & 2)) {
17b0018b 1698 addr = (addr & ~0x8000) | ((y1 & 2) << 14);
e89f66ec 1699 }
28f77de2
GH
1700 page0 = addr & s->vbe_size_mask;
1701 page1 = (addr + bwidth - 1) & s->vbe_size_mask;
fec5e8c9
GH
1702 if (full_update) {
1703 update = 1;
28f77de2
GH
1704 } else if (page1 < page0) {
1705 /* scanline wraps from end of video memory to the start */
1706 assert(force_shadow);
1707 update = memory_region_snapshot_get_dirty(&s->vram, snap,
115788d7 1708 page0, s->vbe_size - page0);
28f77de2 1709 update |= memory_region_snapshot_get_dirty(&s->vram, snap,
115788d7 1710 0, page1);
fec5e8c9
GH
1711 } else {
1712 update = memory_region_snapshot_get_dirty(&s->vram, snap,
1713 page0, page1 - page0);
1714 }
f3289f6f
GH
1715 /* explicit invalidation for the hardware cursor (cirrus only) */
1716 update |= vga_scanline_invalidated(s, y);
e89f66ec 1717 if (update) {
39cf7803
FB
1718 if (y_start < 0)
1719 y_start = y;
c78f7137 1720 if (!(is_buffer_shared(surface))) {
973a724e
PB
1721 uint8_t *p;
1722 p = vga_draw_line(s, d, addr, width, hpel);
1723 if (p) {
1724 memcpy(d, p, disp_width * sizeof(uint32_t));
1725 }
7d957bd8
AL
1726 if (s->cursor_draw_line)
1727 s->cursor_draw_line(s, d, y);
1728 }
39cf7803
FB
1729 } else {
1730 if (y_start >= 0) {
1731 /* flush to display */
c78f7137 1732 dpy_gfx_update(s->con, 0, y_start,
a93a4a22 1733 disp_width, y - y_start);
39cf7803
FB
1734 y_start = -1;
1735 }
e89f66ec 1736 }
a07cf92a 1737 if (!multi_run) {
5e55efc9 1738 mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
f6c958c8 1739 if ((y1 & mask) == mask)
f9b925fd 1740 addr1 += s->params.line_offset;
f6c958c8 1741 y1++;
799e709b 1742 multi_run = multi_scan;
a07cf92a
FB
1743 } else {
1744 multi_run--;
e89f66ec 1745 }
f6c958c8 1746 /* line compare acts on the displayed lines */
973a724e
PB
1747 if (y == s->params.line_compare) {
1748 if (s->params.hpel_split) {
1749 hpel = VGA_HPEL_NEUTRAL;
1750 }
f6c958c8 1751 addr1 = 0;
973a724e 1752 }
e89f66ec
FB
1753 d += linesize;
1754 }
39cf7803
FB
1755 if (y_start >= 0) {
1756 /* flush to display */
c78f7137 1757 dpy_gfx_update(s->con, 0, y_start,
a93a4a22 1758 disp_width, y - y_start);
39cf7803 1759 }
fec5e8c9 1760 g_free(snap);
f3289f6f 1761 memset(s->invalidated_y_table, 0, sizeof(s->invalidated_y_table));
e89f66ec
FB
1762}
1763
cedd91d2 1764static void vga_draw_blank(VGACommonState *s, int full_update)
2aebb3eb 1765{
c78f7137 1766 DisplaySurface *surface = qemu_console_surface(s->con);
2c79f2a2 1767 int i, w;
2aebb3eb
FB
1768 uint8_t *d;
1769
1770 if (!full_update)
1771 return;
1772 if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1773 return;
2bec46dc 1774
c78f7137
GH
1775 w = s->last_scr_width * surface_bytes_per_pixel(surface);
1776 d = surface_data(surface);
2aebb3eb 1777 for(i = 0; i < s->last_scr_height; i++) {
2c79f2a2 1778 memset(d, 0, w);
c78f7137 1779 d += surface_stride(surface);
2aebb3eb 1780 }
91155f8b 1781 dpy_gfx_update_full(s->con);
2aebb3eb
FB
1782}
1783
799e709b
AL
1784#define GMODE_TEXT 0
1785#define GMODE_GRAPH 1
1786#define GMODE_BLANK 2
1787
95219897 1788static void vga_update_display(void *opaque)
e89f66ec 1789{
cedd91d2 1790 VGACommonState *s = opaque;
c78f7137 1791 DisplaySurface *surface = qemu_console_surface(s->con);
799e709b 1792 int full_update, graphic_mode;
e89f66ec 1793
e9a07334
JK
1794 qemu_flush_coalesced_mmio_buffer();
1795
c78f7137 1796 if (surface_bits_per_pixel(surface) == 0) {
0f35920c 1797 /* nothing to do */
59a983b9 1798 } else {
3098b9fd 1799 full_update = 0;
df800210 1800 if (!(s->ar_index & 0x20)) {
799e709b
AL
1801 graphic_mode = GMODE_BLANK;
1802 } else {
5e55efc9 1803 graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
799e709b
AL
1804 }
1805 if (graphic_mode != s->graphic_mode) {
1806 s->graphic_mode = graphic_mode;
bc72ad67 1807 s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
799e709b
AL
1808 full_update = 1;
1809 }
1810 switch(graphic_mode) {
2aebb3eb 1811 case GMODE_TEXT:
e89f66ec 1812 vga_draw_text(s, full_update);
2aebb3eb
FB
1813 break;
1814 case GMODE_GRAPH:
1815 vga_draw_graphic(s, full_update);
1816 break;
1817 case GMODE_BLANK:
1818 default:
1819 vga_draw_blank(s, full_update);
1820 break;
1821 }
e89f66ec
FB
1822 }
1823}
1824
a130a41e 1825/* force a full display refresh */
95219897 1826static void vga_invalidate_display(void *opaque)
a130a41e 1827{
cedd91d2 1828 VGACommonState *s = opaque;
3b46e624 1829
3098b9fd
AJ
1830 s->last_width = -1;
1831 s->last_height = -1;
a130a41e
FB
1832}
1833
03a3e7ba 1834void vga_common_reset(VGACommonState *s)
e89f66ec 1835{
6e6b7363
BS
1836 s->sr_index = 0;
1837 memset(s->sr, '\0', sizeof(s->sr));
94ef4f33 1838 memset(s->sr_vbe, '\0', sizeof(s->sr_vbe));
6e6b7363
BS
1839 s->gr_index = 0;
1840 memset(s->gr, '\0', sizeof(s->gr));
1841 s->ar_index = 0;
1842 memset(s->ar, '\0', sizeof(s->ar));
1843 s->ar_flip_flop = 0;
1844 s->cr_index = 0;
1845 memset(s->cr, '\0', sizeof(s->cr));
1846 s->msr = 0;
1847 s->fcr = 0;
1848 s->st00 = 0;
1849 s->st01 = 0;
1850 s->dac_state = 0;
1851 s->dac_sub_index = 0;
1852 s->dac_read_index = 0;
1853 s->dac_write_index = 0;
1854 memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1855 s->dac_8bit = 0;
1856 memset(s->palette, '\0', sizeof(s->palette));
1857 s->bank_offset = 0;
6e6b7363
BS
1858 s->vbe_index = 0;
1859 memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
af92284b 1860 s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
6e6b7363
BS
1861 s->vbe_start_addr = 0;
1862 s->vbe_line_offset = 0;
1863 s->vbe_bank_mask = (s->vram_size >> 16) - 1;
6e6b7363 1864 memset(s->font_offsets, '\0', sizeof(s->font_offsets));
799e709b 1865 s->graphic_mode = -1; /* force full update */
6e6b7363
BS
1866 s->shift_control = 0;
1867 s->double_scan = 0;
f9b925fd 1868 memset(&s->params, '\0', sizeof(s->params));
6e6b7363
BS
1869 s->plane_updated = 0;
1870 s->last_cw = 0;
1871 s->last_ch = 0;
1872 s->last_width = 0;
1873 s->last_height = 0;
1874 s->last_scr_width = 0;
1875 s->last_scr_height = 0;
1876 s->cursor_start = 0;
1877 s->cursor_end = 0;
1878 s->cursor_offset = 0;
c3b10605 1879 s->big_endian_fb = s->default_endian_fb;
6e6b7363
BS
1880 memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1881 memset(s->last_palette, '\0', sizeof(s->last_palette));
1882 memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1883 switch (vga_retrace_method) {
1884 case VGA_RETRACE_DUMB:
1885 break;
1886 case VGA_RETRACE_PRECISE:
1887 memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1888 break;
1889 }
80763888 1890 vga_update_memory_access(s);
e89f66ec
FB
1891}
1892
03a3e7ba
JQ
1893static void vga_reset(void *opaque)
1894{
cedd91d2 1895 VGACommonState *s = opaque;
03a3e7ba
JQ
1896 vga_common_reset(s);
1897}
1898
4d3b6f6e
AZ
1899#define TEXTMODE_X(x) ((x) % width)
1900#define TEXTMODE_Y(x) ((x) / width)
1901#define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
1902 ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1903/* relay text rendering to the display driver
1904 * instead of doing a full vga_update_display() */
c227f099 1905static void vga_update_text(void *opaque, console_ch_t *chardata)
4d3b6f6e 1906{
cedd91d2 1907 VGACommonState *s = opaque;
799e709b 1908 int graphic_mode, i, cursor_offset, cursor_visible;
4d3b6f6e
AZ
1909 int cw, cheight, width, height, size, c_min, c_max;
1910 uint32_t *src;
c227f099 1911 console_ch_t *dst, val;
4d3b6f6e 1912 char msg_buffer[80];
799e709b
AL
1913 int full_update = 0;
1914
e9a07334
JK
1915 qemu_flush_coalesced_mmio_buffer();
1916
799e709b
AL
1917 if (!(s->ar_index & 0x20)) {
1918 graphic_mode = GMODE_BLANK;
1919 } else {
5e55efc9 1920 graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
799e709b
AL
1921 }
1922 if (graphic_mode != s->graphic_mode) {
1923 s->graphic_mode = graphic_mode;
1924 full_update = 1;
1925 }
1926 if (s->last_width == -1) {
1927 s->last_width = 0;
1928 full_update = 1;
1929 }
4d3b6f6e 1930
799e709b 1931 switch (graphic_mode) {
4d3b6f6e
AZ
1932 case GMODE_TEXT:
1933 /* TODO: update palette */
799e709b 1934 full_update |= update_basic_params(s);
4d3b6f6e 1935
799e709b 1936 /* total width & height */
5e55efc9 1937 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
799e709b 1938 cw = 8;
94ef4f33 1939 if (!(sr(s, VGA_SEQ_CLOCK_MODE) & VGA_SR01_CHAR_CLK_8DOTS)) {
799e709b 1940 cw = 9;
5e55efc9 1941 }
94ef4f33 1942 if (sr(s, VGA_SEQ_CLOCK_MODE) & 0x08) {
799e709b 1943 cw = 16; /* NOTE: no 18 pixel wide */
5e55efc9
BS
1944 }
1945 width = (s->cr[VGA_CRTC_H_DISP] + 1);
1946 if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
799e709b
AL
1947 /* ugly hack for CGA 160x100x16 - explain me the logic */
1948 height = 100;
1949 } else {
5e55efc9
BS
1950 height = s->cr[VGA_CRTC_V_DISP_END] |
1951 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1952 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
799e709b 1953 height = (height + 1) / cheight;
4d3b6f6e
AZ
1954 }
1955
1956 size = (height * width);
1957 if (size > CH_ATTR_SIZE) {
1958 if (!full_update)
1959 return;
1960
363a37d5
BS
1961 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1962 width, height);
4d3b6f6e
AZ
1963 break;
1964 }
1965
799e709b
AL
1966 if (width != s->last_width || height != s->last_height ||
1967 cw != s->last_cw || cheight != s->last_ch) {
1968 s->last_scr_width = width * cw;
1969 s->last_scr_height = height * cheight;
c78f7137
GH
1970 qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
1971 dpy_text_resize(s->con, width, height);
9678aedd 1972 s->last_depth = 0;
799e709b
AL
1973 s->last_width = width;
1974 s->last_height = height;
1975 s->last_ch = cheight;
1976 s->last_cw = cw;
1977 full_update = 1;
1978 }
1979
9678aedd
GH
1980 if (full_update) {
1981 s->full_update_gfx = 1;
1982 }
1983 if (s->full_update_text) {
1984 s->full_update_text = 0;
1985 full_update |= 1;
1986 }
1987
4d3b6f6e 1988 /* Update "hardware" cursor */
5e55efc9 1989 cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
f9b925fd 1990 s->cr[VGA_CRTC_CURSOR_LO]) - s->params.start_addr;
4d3b6f6e 1991 if (cursor_offset != s->cursor_offset ||
5e55efc9
BS
1992 s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1993 s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
1994 cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
4d3b6f6e 1995 if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
c78f7137 1996 dpy_text_cursor(s->con,
bf2fde70
GH
1997 TEXTMODE_X(cursor_offset),
1998 TEXTMODE_Y(cursor_offset));
4d3b6f6e 1999 else
c78f7137 2000 dpy_text_cursor(s->con, -1, -1);
4d3b6f6e 2001 s->cursor_offset = cursor_offset;
5e55efc9
BS
2002 s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
2003 s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
4d3b6f6e
AZ
2004 }
2005
f9b925fd 2006 src = (uint32_t *) s->vram_ptr + s->params.start_addr;
4d3b6f6e
AZ
2007 dst = chardata;
2008
2009 if (full_update) {
2010 for (i = 0; i < size; src ++, dst ++, i ++)
9ae19b65 2011 console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
4d3b6f6e 2012
c78f7137 2013 dpy_text_update(s->con, 0, 0, width, height);
4d3b6f6e
AZ
2014 } else {
2015 c_max = 0;
2016
2017 for (i = 0; i < size; src ++, dst ++, i ++) {
9ae19b65 2018 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
4d3b6f6e
AZ
2019 if (*dst != val) {
2020 *dst = val;
2021 c_max = i;
2022 break;
2023 }
2024 }
2025 c_min = i;
2026 for (; i < size; src ++, dst ++, i ++) {
9ae19b65 2027 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
4d3b6f6e
AZ
2028 if (*dst != val) {
2029 *dst = val;
2030 c_max = i;
2031 }
2032 }
2033
2034 if (c_min <= c_max) {
2035 i = TEXTMODE_Y(c_min);
c78f7137 2036 dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
4d3b6f6e
AZ
2037 }
2038 }
2039
2040 return;
2041 case GMODE_GRAPH:
2042 if (!full_update)
2043 return;
2044
2045 s->get_resolution(s, &width, &height);
363a37d5
BS
2046 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2047 width, height);
4d3b6f6e
AZ
2048 break;
2049 case GMODE_BLANK:
2050 default:
2051 if (!full_update)
2052 return;
2053
363a37d5 2054 snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
4d3b6f6e
AZ
2055 break;
2056 }
2057
2058 /* Display a message */
5228c2d3
AZ
2059 s->last_width = 60;
2060 s->last_height = height = 3;
c78f7137
GH
2061 dpy_text_cursor(s->con, -1, -1);
2062 dpy_text_resize(s->con, s->last_width, height);
4d3b6f6e 2063
5228c2d3 2064 for (dst = chardata, i = 0; i < s->last_width * height; i ++)
4d3b6f6e
AZ
2065 console_write_ch(dst ++, ' ');
2066
2067 size = strlen(msg_buffer);
5228c2d3
AZ
2068 width = (s->last_width - size) / 2;
2069 dst = chardata + s->last_width + width;
4d3b6f6e 2070 for (i = 0; i < size; i ++)
4083733d
OH
2071 console_write_ch(dst ++, ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE,
2072 QEMU_COLOR_BLACK, 1));
4d3b6f6e 2073
c78f7137 2074 dpy_text_update(s->con, 0, 0, s->last_width, height);
4d3b6f6e
AZ
2075}
2076
a8170e5e 2077static uint64_t vga_mem_read(void *opaque, hwaddr addr,
b1950430
AK
2078 unsigned size)
2079{
2080 VGACommonState *s = opaque;
2081
b2a5e761 2082 return vga_mem_readb(s, addr);
b1950430 2083}
e89f66ec 2084
a8170e5e 2085static void vga_mem_write(void *opaque, hwaddr addr,
b1950430
AK
2086 uint64_t data, unsigned size)
2087{
2088 VGACommonState *s = opaque;
2089
e7ae771f 2090 vga_mem_writeb(s, addr, data);
b1950430
AK
2091}
2092
2093const MemoryRegionOps vga_mem_ops = {
2094 .read = vga_mem_read,
2095 .write = vga_mem_write,
2096 .endianness = DEVICE_LITTLE_ENDIAN,
b2a5e761
AK
2097 .impl = {
2098 .min_access_size = 1,
2099 .max_access_size = 1,
2100 },
e89f66ec
FB
2101};
2102
11b6b345 2103static int vga_common_post_load(void *opaque, int version_id)
b0a21b53 2104{
0d65ddc3 2105 VGACommonState *s = opaque;
11b6b345
JQ
2106
2107 /* force refresh */
2108 s->graphic_mode = -1;
94ef4f33 2109 vbe_update_vgaregs(s);
138bc2df 2110 vga_update_memory_access(s);
11b6b345
JQ
2111 return 0;
2112}
2113
c3b10605
BH
2114static bool vga_endian_state_needed(void *opaque)
2115{
2116 VGACommonState *s = opaque;
2117
2118 /*
2119 * Only send the endian state if it's different from the
2120 * default one, thus ensuring backward compatibility for
2121 * migration of the common case
2122 */
2123 return s->default_endian_fb != s->big_endian_fb;
2124}
2125
73d22caf 2126static const VMStateDescription vmstate_vga_endian = {
c3b10605
BH
2127 .name = "vga.endian",
2128 .version_id = 1,
2129 .minimum_version_id = 1,
5cd8cada 2130 .needed = vga_endian_state_needed,
f0613160 2131 .fields = (const VMStateField[]) {
c3b10605
BH
2132 VMSTATE_BOOL(big_endian_fb, VGACommonState),
2133 VMSTATE_END_OF_LIST()
2134 }
2135};
2136
11b6b345
JQ
2137const VMStateDescription vmstate_vga_common = {
2138 .name = "vga",
2139 .version_id = 2,
2140 .minimum_version_id = 2,
11b6b345 2141 .post_load = vga_common_post_load,
f0613160 2142 .fields = (const VMStateField[]) {
11b6b345
JQ
2143 VMSTATE_UINT32(latch, VGACommonState),
2144 VMSTATE_UINT8(sr_index, VGACommonState),
2145 VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2146 VMSTATE_UINT8(gr_index, VGACommonState),
2147 VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2148 VMSTATE_UINT8(ar_index, VGACommonState),
2149 VMSTATE_BUFFER(ar, VGACommonState),
2150 VMSTATE_INT32(ar_flip_flop, VGACommonState),
2151 VMSTATE_UINT8(cr_index, VGACommonState),
2152 VMSTATE_BUFFER(cr, VGACommonState),
2153 VMSTATE_UINT8(msr, VGACommonState),
2154 VMSTATE_UINT8(fcr, VGACommonState),
2155 VMSTATE_UINT8(st00, VGACommonState),
2156 VMSTATE_UINT8(st01, VGACommonState),
2157
2158 VMSTATE_UINT8(dac_state, VGACommonState),
2159 VMSTATE_UINT8(dac_sub_index, VGACommonState),
2160 VMSTATE_UINT8(dac_read_index, VGACommonState),
2161 VMSTATE_UINT8(dac_write_index, VGACommonState),
2162 VMSTATE_BUFFER(dac_cache, VGACommonState),
2163 VMSTATE_BUFFER(palette, VGACommonState),
2164
2165 VMSTATE_INT32(bank_offset, VGACommonState),
d2164ad3 2166 VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState, NULL),
11b6b345
JQ
2167 VMSTATE_UINT16(vbe_index, VGACommonState),
2168 VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2169 VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2170 VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2171 VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
11b6b345 2172 VMSTATE_END_OF_LIST()
c3b10605 2173 },
f0613160 2174 .subsections = (const VMStateDescription * const []) {
5cd8cada
JQ
2175 &vmstate_vga_endian,
2176 NULL
11b6b345
JQ
2177 }
2178};
2179
380cd056
GH
2180static const GraphicHwOps vga_ops = {
2181 .invalidate = vga_invalidate_display,
2182 .gfx_update = vga_update_display,
2183 .text_update = vga_update_text,
2184};
2185
619616ce
RK
2186static inline uint32_t uint_clamp(uint32_t val, uint32_t vmin, uint32_t vmax)
2187{
2188 if (val < vmin) {
2189 return vmin;
2190 }
2191 if (val > vmax) {
2192 return vmax;
2193 }
2194 return val;
2195}
2196
6832deb8 2197bool vga_common_init(VGACommonState *s, Object *obj, Error **errp)
e89f66ec 2198{
17b0018b 2199 int i, j, v, b;
6832deb8 2200 Error *local_err = NULL;
e89f66ec
FB
2201
2202 for(i = 0;i < 256; i++) {
2203 v = 0;
2204 for(j = 0; j < 8; j++) {
2205 v |= ((i >> j) & 1) << (j * 4);
2206 }
2207 expand4[i] = v;
2208
2209 v = 0;
2210 for(j = 0; j < 4; j++) {
2211 v |= ((i >> (2 * j)) & 3) << (j * 4);
2212 }
2213 expand2[i] = v;
2214 }
17b0018b
FB
2215 for(i = 0; i < 16; i++) {
2216 v = 0;
2217 for(j = 0; j < 4; j++) {
2218 b = ((i >> j) & 1);
2219 v |= b << (2 * j);
2220 v |= b << (2 * j + 1);
2221 }
2222 expand4to8[i] = v;
2223 }
e89f66ec 2224
619616ce
RK
2225 s->vram_size_mb = uint_clamp(s->vram_size_mb, 1, 512);
2226 s->vram_size_mb = pow2ceil(s->vram_size_mb);
f0353b0d 2227 s->vram_size = s->vram_size_mb * MiB;
619616ce 2228
54a85d46
GH
2229 if (!s->vbe_size) {
2230 s->vbe_size = s->vram_size;
2231 }
3d90c625 2232 s->vbe_size_mask = s->vbe_size - 1;
4a1e244e 2233
2a3138ab 2234 s->is_vbe_vmstate = 1;
9eb840a2
TH
2235
2236 if (s->global_vmstate && qemu_ram_block_by_name("vga.vram")) {
2237 error_setg(errp, "Only one global VGA device can be used at a time");
2238 return false;
2239 }
2240
1cfe48c1 2241 memory_region_init_ram_nomigrate(&s->vram, obj, "vga.vram", s->vram_size,
6832deb8
TH
2242 &local_err);
2243 if (local_err) {
2244 error_propagate(errp, local_err);
2245 return false;
2246 }
1fcfdc43 2247 vmstate_register_ram(&s->vram, s->global_vmstate ? NULL : DEVICE(obj));
c65adf9b 2248 xen_register_framebuffer(&s->vram);
b1950430 2249 s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
798b0c25 2250 s->get_bpp = vga_get_bpp;
f9b925fd 2251 s->get_params = vga_get_params;
a130a41e 2252 s->get_resolution = vga_get_resolution;
380cd056 2253 s->hw_ops = &vga_ops;
cb5a7aa8 2254 switch (vga_retrace_method) {
2255 case VGA_RETRACE_DUMB:
2256 s->retrace = vga_dumb_retrace;
2257 s->update_retrace_info = vga_dumb_update_retrace_info;
2258 break;
2259
2260 case VGA_RETRACE_PRECISE:
2261 s->retrace = vga_precise_retrace;
2262 s->update_retrace_info = vga_precise_update_retrace_info;
cb5a7aa8 2263 break;
2264 }
2c7d8736
BH
2265
2266 /*
c3b10605 2267 * Set default fb endian based on target, could probably be turned
2c7d8736
BH
2268 * into a device attribute set by the machine/platform to remove
2269 * all target endian dependencies from this file.
2270 */
9eb7e7e8
TH
2271 s->default_endian_fb = target_words_bigendian();
2272
b1950430 2273 vga_dirty_log_start(s);
6832deb8
TH
2274
2275 return true;
798b0c25
FB
2276}
2277
0a039dc7
RH
2278static const MemoryRegionPortio vga_portio_list[] = {
2279 { 0x04, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
2280 { 0x0a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
2281 { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
2282 { 0x24, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
2283 { 0x2a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
2284 PORTIO_END_OF_LIST(),
2285};
e89f66ec 2286
9eb7e7e8 2287static const MemoryRegionPortio vbe_portio_list_x86[] = {
0a039dc7 2288 { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
0a039dc7 2289 { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
9eb7e7e8
TH
2290 { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2291 PORTIO_END_OF_LIST(),
2292};
2293
2294static const MemoryRegionPortio vbe_portio_list_no_x86[] = {
2295 { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
df9ffb72 2296 { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
0a039dc7
RH
2297 PORTIO_END_OF_LIST(),
2298};
4fa0f5d2 2299
0a039dc7 2300/* Used by both ISA and PCI */
c84b28ee 2301MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
0a039dc7
RH
2302 const MemoryRegionPortio **vga_ports,
2303 const MemoryRegionPortio **vbe_ports)
2304{
2305 MemoryRegion *vga_mem;
9eb7e7e8
TH
2306 MachineState *ms = MACHINE(qdev_get_machine());
2307
2308 /*
2309 * We unfortunately need two VBE lists since non-x86 machines might
2310 * not be able to do 16-bit accesses at unaligned addresses (0x1cf)
2311 */
2312 if (object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) {
2313 *vbe_ports = vbe_portio_list_x86;
2314 } else {
2315 *vbe_ports = vbe_portio_list_no_x86;
2316 }
09a79b49 2317
0a039dc7 2318 *vga_ports = vga_portio_list;
4fa0f5d2 2319
7267c094 2320 vga_mem = g_malloc(sizeof(*vga_mem));
c84b28ee 2321 memory_region_init_io(vga_mem, obj, &vga_mem_ops, s,
b1950430 2322 "vga-lowmem", 0x20000);
bd8f2f5d 2323 memory_region_set_flush_coalesced(vga_mem);
b1950430
AK
2324
2325 return vga_mem;
7435b791
BS
2326}
2327
712f0cc7 2328void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
0a039dc7 2329 MemoryRegion *address_space_io, bool init_vga_ports)
7435b791 2330{
b1950430 2331 MemoryRegion *vga_io_memory;
0a039dc7 2332 const MemoryRegionPortio *vga_ports, *vbe_ports;
7435b791
BS
2333
2334 qemu_register_reset(vga_reset, s);
2335
2336 s->bank_offset = 0;
2337
80763888
JK
2338 s->legacy_address_space = address_space;
2339
c84b28ee 2340 vga_io_memory = vga_init_io(s, obj, &vga_ports, &vbe_ports);
be20f9e9 2341 memory_region_add_subregion_overlap(address_space,
b19c1c08 2342 0x000a0000,
b1950430
AK
2343 vga_io_memory,
2344 1);
2345 memory_region_set_coalescing(vga_io_memory);
0a039dc7 2346 if (init_vga_ports) {
848696bf
KB
2347 portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga");
2348 portio_list_set_flush_coalesced(&s->vga_port_list);
2349 portio_list_add(&s->vga_port_list, address_space_io, 0x3b0);
0a039dc7
RH
2350 }
2351 if (vbe_ports) {
848696bf
KB
2352 portio_list_init(&s->vbe_port_list, obj, vbe_ports, s, "vbe");
2353 portio_list_add(&s->vbe_port_list, address_space_io, 0x1ce);
0a039dc7 2354 }
d2269f6f 2355}