ati-vga: Fix cursor color with guest_hwcursor=true
[qemu/ar7.git] / hw / display / ati.c
blobd372e346ffd956ac5c89c2f206a19a3978d8672b
1 /*
2 * QEMU ATI SVGA emulation
4 * Copyright (c) 2019 BALATON Zoltan
6 * This work is licensed under the GNU GPL license version 2 or later.
7 */
9 /*
10 * WARNING:
11 * This is very incomplete and only enough for Linux console and some
12 * unaccelerated X output at the moment.
13 * Currently it's little more than a frame buffer with minimal functions,
14 * other more advanced features of the hardware are yet to be implemented.
15 * We only aim for Rage 128 Pro (and some RV100) and 2D only at first,
16 * No 3D at all yet (maybe after 2D works, but feel free to improve it)
19 #include "qemu/osdep.h"
20 #include "ati_int.h"
21 #include "ati_regs.h"
22 #include "hw/qdev-properties.h"
23 #include "vga_regs.h"
24 #include "qemu/log.h"
25 #include "qemu/module.h"
26 #include "qemu/error-report.h"
27 #include "qapi/error.h"
28 #include "ui/console.h"
29 #include "hw/display/i2c-ddc.h"
30 #include "trace.h"
32 #define ATI_DEBUG_HW_CURSOR 0
34 static const struct {
35 const char *name;
36 uint16_t dev_id;
37 } ati_model_aliases[] = {
38 { "rage128p", PCI_DEVICE_ID_ATI_RAGE128_PF },
39 { "rv100", PCI_DEVICE_ID_ATI_RADEON_QY },
42 enum { VGA_MODE, EXT_MODE };
44 static void ati_vga_switch_mode(ATIVGAState *s)
46 DPRINTF("%d -> %d\n",
47 s->mode, !!(s->regs.crtc_gen_cntl & CRTC2_EXT_DISP_EN));
48 if (s->regs.crtc_gen_cntl & CRTC2_EXT_DISP_EN) {
49 /* Extended mode enabled */
50 s->mode = EXT_MODE;
51 if (s->regs.crtc_gen_cntl & CRTC2_EN) {
52 /* CRT controller enabled, use CRTC values */
53 uint32_t offs = s->regs.crtc_offset & 0x07ffffff;
54 int stride = (s->regs.crtc_pitch & 0x7ff) * 8;
55 int bpp = 0;
56 int h, v;
58 if (s->regs.crtc_h_total_disp == 0) {
59 s->regs.crtc_h_total_disp = ((640 / 8) - 1) << 16;
61 if (s->regs.crtc_v_total_disp == 0) {
62 s->regs.crtc_v_total_disp = (480 - 1) << 16;
64 h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8;
65 v = (s->regs.crtc_v_total_disp >> 16) + 1;
66 switch (s->regs.crtc_gen_cntl & CRTC_PIX_WIDTH_MASK) {
67 case CRTC_PIX_WIDTH_4BPP:
68 bpp = 4;
69 break;
70 case CRTC_PIX_WIDTH_8BPP:
71 bpp = 8;
72 break;
73 case CRTC_PIX_WIDTH_15BPP:
74 bpp = 15;
75 break;
76 case CRTC_PIX_WIDTH_16BPP:
77 bpp = 16;
78 break;
79 case CRTC_PIX_WIDTH_24BPP:
80 bpp = 24;
81 break;
82 case CRTC_PIX_WIDTH_32BPP:
83 bpp = 32;
84 break;
85 default:
86 qemu_log_mask(LOG_UNIMP, "Unsupported bpp value\n");
88 assert(bpp != 0);
89 DPRINTF("Switching to %dx%d %d %d @ %x\n", h, v, stride, bpp, offs);
90 vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
91 vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
92 s->vga.big_endian_fb = false;
93 /* reset VBE regs then set up mode */
94 s->vga.vbe_regs[VBE_DISPI_INDEX_XRES] = h;
95 s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] = v;
96 s->vga.vbe_regs[VBE_DISPI_INDEX_BPP] = bpp;
97 /* enable mode via ioport so it updates vga regs */
98 vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
99 vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_ENABLED |
100 VBE_DISPI_LFB_ENABLED | VBE_DISPI_NOCLEARMEM |
101 (s->regs.dac_cntl & DAC_8BIT_EN ? VBE_DISPI_8BIT_DAC : 0));
102 /* now set offset and stride after enable as that resets these */
103 if (stride) {
104 vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_VIRT_WIDTH);
105 vbe_ioport_write_data(&s->vga, 0, stride);
106 if (offs % stride == 0) {
107 vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_Y_OFFSET);
108 vbe_ioport_write_data(&s->vga, 0, offs / stride);
109 } else {
110 /* FIXME what to do with this? */
111 error_report("VGA offset is not multiple of pitch, "
112 "expect bad picture");
116 } else {
117 /* VGA mode enabled */
118 s->mode = VGA_MODE;
119 vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
120 vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
124 /* Used by host side hardware cursor */
125 static void ati_cursor_define(ATIVGAState *s)
127 uint8_t data[1024];
128 uint8_t *src;
129 int i, j, idx = 0;
131 if ((s->regs.cur_offset & BIT(31)) || s->cursor_guest_mode) {
132 return; /* Do not update cursor if locked or rendered by guest */
134 /* FIXME handle cur_hv_offs correctly */
135 src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) +
136 s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
137 (s->regs.cur_hv_offs & 0xffff) * 16;
138 for (i = 0; i < 64; i++) {
139 for (j = 0; j < 8; j++, idx++) {
140 data[idx] = src[i * 16 + j];
141 data[512 + idx] = src[i * 16 + j + 8];
144 if (!s->cursor) {
145 s->cursor = cursor_alloc(64, 64);
147 cursor_set_mono(s->cursor, s->regs.cur_color1, s->regs.cur_color0,
148 &data[512], 1, &data[0]);
149 dpy_cursor_define(s->vga.con, s->cursor);
152 /* Alternatively support guest rendered hardware cursor */
153 static void ati_cursor_invalidate(VGACommonState *vga)
155 ATIVGAState *s = container_of(vga, ATIVGAState, vga);
156 int size = (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) ? 64 : 0;
158 if (s->regs.cur_offset & BIT(31)) {
159 return; /* Do not update cursor if locked */
161 if (s->cursor_size != size ||
162 vga->hw_cursor_x != s->regs.cur_hv_pos >> 16 ||
163 vga->hw_cursor_y != (s->regs.cur_hv_pos & 0xffff) ||
164 s->cursor_offset != s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
165 (s->regs.cur_hv_offs & 0xffff) * 16) {
166 /* Remove old cursor then update and show new one if needed */
167 vga_invalidate_scanlines(vga, vga->hw_cursor_y, vga->hw_cursor_y + 63);
168 vga->hw_cursor_x = s->regs.cur_hv_pos >> 16;
169 vga->hw_cursor_y = s->regs.cur_hv_pos & 0xffff;
170 s->cursor_offset = s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
171 (s->regs.cur_hv_offs & 0xffff) * 16;
172 s->cursor_size = size;
173 if (size) {
174 vga_invalidate_scanlines(vga,
175 vga->hw_cursor_y, vga->hw_cursor_y + 63);
180 static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y)
182 ATIVGAState *s = container_of(vga, ATIVGAState, vga);
183 uint8_t *src;
184 uint32_t *dp = (uint32_t *)d;
185 int i, j, h;
187 if (!(s->regs.crtc_gen_cntl & CRTC2_CUR_EN) ||
188 scr_y < vga->hw_cursor_y || scr_y >= vga->hw_cursor_y + 64 ||
189 scr_y > s->regs.crtc_v_total_disp >> 16) {
190 return;
192 /* FIXME handle cur_hv_offs correctly */
193 src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) +
194 s->cursor_offset + (scr_y - vga->hw_cursor_y) * 16;
195 dp = &dp[vga->hw_cursor_x];
196 h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8;
197 for (i = 0; i < 8; i++) {
198 uint32_t color;
199 uint8_t abits = src[i];
200 uint8_t xbits = src[i + 8];
201 for (j = 0; j < 8; j++, abits <<= 1, xbits <<= 1) {
202 if (abits & BIT(7)) {
203 if (xbits & BIT(7)) {
204 color = dp[i * 8 + j] ^ 0xffffffff; /* complement */
205 } else {
206 continue; /* transparent, no change */
208 } else {
209 color = (xbits & BIT(7) ? s->regs.cur_color1 :
210 s->regs.cur_color0) | 0xff000000;
212 if (vga->hw_cursor_x + i * 8 + j >= h) {
213 return; /* end of screen, don't span to next line */
215 dp[i * 8 + j] = color;
220 static uint64_t ati_i2c(bitbang_i2c_interface *i2c, uint64_t data, int base)
222 bool c = (data & BIT(base + 17) ? !!(data & BIT(base + 1)) : 1);
223 bool d = (data & BIT(base + 16) ? !!(data & BIT(base)) : 1);
225 bitbang_i2c_set(i2c, BITBANG_I2C_SCL, c);
226 d = bitbang_i2c_set(i2c, BITBANG_I2C_SDA, d);
228 data &= ~0xf00ULL;
229 if (c) {
230 data |= BIT(base + 9);
232 if (d) {
233 data |= BIT(base + 8);
235 return data;
238 static inline uint64_t ati_reg_read_offs(uint32_t reg, int offs,
239 unsigned int size)
241 if (offs == 0 && size == 4) {
242 return reg;
243 } else {
244 return extract32(reg, offs * BITS_PER_BYTE, size * BITS_PER_BYTE);
248 static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
250 ATIVGAState *s = opaque;
251 uint64_t val = 0;
253 switch (addr) {
254 case MM_INDEX:
255 val = s->regs.mm_index;
256 break;
257 case MM_DATA ... MM_DATA + 3:
258 /* indexed access to regs or memory */
259 if (s->regs.mm_index & BIT(31)) {
260 uint32_t idx = s->regs.mm_index & ~BIT(31);
261 if (idx <= s->vga.vram_size - size) {
262 val = ldn_le_p(s->vga.vram_ptr + idx, size);
264 } else {
265 val = ati_mm_read(s, s->regs.mm_index + addr - MM_DATA, size);
267 break;
268 case BIOS_0_SCRATCH ... BUS_CNTL - 1:
270 int i = (addr - BIOS_0_SCRATCH) / 4;
271 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF && i > 3) {
272 break;
274 val = ati_reg_read_offs(s->regs.bios_scratch[i],
275 addr - (BIOS_0_SCRATCH + i * 4), size);
276 break;
278 case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
279 val = ati_reg_read_offs(s->regs.crtc_gen_cntl,
280 addr - CRTC_GEN_CNTL, size);
281 break;
282 case CRTC_EXT_CNTL ... CRTC_EXT_CNTL + 3:
283 val = ati_reg_read_offs(s->regs.crtc_ext_cntl,
284 addr - CRTC_EXT_CNTL, size);
285 break;
286 case DAC_CNTL:
287 val = s->regs.dac_cntl;
288 break;
289 case GPIO_VGA_DDC:
290 val = s->regs.gpio_vga_ddc;
291 break;
292 case GPIO_DVI_DDC:
293 val = s->regs.gpio_dvi_ddc;
294 break;
295 case GPIO_MONID ... GPIO_MONID + 3:
296 val = ati_reg_read_offs(s->regs.gpio_monid,
297 addr - GPIO_MONID, size);
298 break;
299 case PALETTE_INDEX:
300 /* FIXME unaligned access */
301 val = vga_ioport_read(&s->vga, VGA_PEL_IR) << 16;
302 val |= vga_ioport_read(&s->vga, VGA_PEL_IW) & 0xff;
303 break;
304 case PALETTE_DATA:
305 val = vga_ioport_read(&s->vga, VGA_PEL_D);
306 break;
307 case CNFG_MEMSIZE:
308 val = s->vga.vram_size;
309 break;
310 case CONFIG_APER_0_BASE:
311 case CONFIG_APER_1_BASE:
312 val = pci_default_read_config(&s->dev,
313 PCI_BASE_ADDRESS_0, size) & 0xfffffff0;
314 break;
315 case CONFIG_APER_SIZE:
316 val = s->vga.vram_size;
317 break;
318 case CONFIG_REG_1_BASE:
319 val = pci_default_read_config(&s->dev,
320 PCI_BASE_ADDRESS_2, size) & 0xfffffff0;
321 break;
322 case CONFIG_REG_APER_SIZE:
323 val = memory_region_size(&s->mm);
324 break;
325 case MC_STATUS:
326 val = 5;
327 break;
328 case RBBM_STATUS:
329 case GUI_STAT:
330 val = 64; /* free CMDFIFO entries */
331 break;
332 case CRTC_H_TOTAL_DISP:
333 val = s->regs.crtc_h_total_disp;
334 break;
335 case CRTC_H_SYNC_STRT_WID:
336 val = s->regs.crtc_h_sync_strt_wid;
337 break;
338 case CRTC_V_TOTAL_DISP:
339 val = s->regs.crtc_v_total_disp;
340 break;
341 case CRTC_V_SYNC_STRT_WID:
342 val = s->regs.crtc_v_sync_strt_wid;
343 break;
344 case CRTC_OFFSET:
345 val = s->regs.crtc_offset;
346 break;
347 case CRTC_OFFSET_CNTL:
348 val = s->regs.crtc_offset_cntl;
349 break;
350 case CRTC_PITCH:
351 val = s->regs.crtc_pitch;
352 break;
353 case 0xf00 ... 0xfff:
354 val = pci_default_read_config(&s->dev, addr - 0xf00, size);
355 break;
356 case CUR_OFFSET:
357 val = s->regs.cur_offset;
358 break;
359 case CUR_HORZ_VERT_POSN:
360 val = s->regs.cur_hv_pos;
361 val |= s->regs.cur_offset & BIT(31);
362 break;
363 case CUR_HORZ_VERT_OFF:
364 val = s->regs.cur_hv_offs;
365 val |= s->regs.cur_offset & BIT(31);
366 break;
367 case CUR_CLR0:
368 val = s->regs.cur_color0;
369 break;
370 case CUR_CLR1:
371 val = s->regs.cur_color1;
372 break;
373 case DST_OFFSET:
374 val = s->regs.dst_offset;
375 break;
376 case DST_PITCH:
377 val = s->regs.dst_pitch;
378 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
379 val &= s->regs.dst_tile << 16;
381 break;
382 case DST_WIDTH:
383 val = s->regs.dst_width;
384 break;
385 case DST_HEIGHT:
386 val = s->regs.dst_height;
387 break;
388 case SRC_X:
389 val = s->regs.src_x;
390 break;
391 case SRC_Y:
392 val = s->regs.src_y;
393 break;
394 case DST_X:
395 val = s->regs.dst_x;
396 break;
397 case DST_Y:
398 val = s->regs.dst_y;
399 break;
400 case DP_GUI_MASTER_CNTL:
401 val = s->regs.dp_gui_master_cntl;
402 break;
403 case SRC_OFFSET:
404 val = s->regs.src_offset;
405 break;
406 case SRC_PITCH:
407 val = s->regs.src_pitch;
408 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
409 val &= s->regs.src_tile << 16;
411 break;
412 case DP_BRUSH_BKGD_CLR:
413 val = s->regs.dp_brush_bkgd_clr;
414 break;
415 case DP_BRUSH_FRGD_CLR:
416 val = s->regs.dp_brush_frgd_clr;
417 break;
418 case DP_SRC_FRGD_CLR:
419 val = s->regs.dp_src_frgd_clr;
420 break;
421 case DP_SRC_BKGD_CLR:
422 val = s->regs.dp_src_bkgd_clr;
423 break;
424 case DP_CNTL:
425 val = s->regs.dp_cntl;
426 break;
427 case DP_DATATYPE:
428 val = s->regs.dp_datatype;
429 break;
430 case DP_MIX:
431 val = s->regs.dp_mix;
432 break;
433 case DP_WRITE_MASK:
434 val = s->regs.dp_write_mask;
435 break;
436 case DEFAULT_OFFSET:
437 val = s->regs.default_offset;
438 if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
439 val >>= 10;
440 val |= s->regs.default_pitch << 16;
441 val |= s->regs.default_tile << 30;
443 break;
444 case DEFAULT_PITCH:
445 val = s->regs.default_pitch;
446 val |= s->regs.default_tile << 16;
447 break;
448 case DEFAULT_SC_BOTTOM_RIGHT:
449 val = s->regs.default_sc_bottom_right;
450 break;
451 default:
452 break;
454 if (addr < CUR_OFFSET || addr > CUR_CLR1 || ATI_DEBUG_HW_CURSOR) {
455 trace_ati_mm_read(size, addr, ati_reg_name(addr & ~3ULL), val);
457 return val;
460 static inline void ati_reg_write_offs(uint32_t *reg, int offs,
461 uint64_t data, unsigned int size)
463 if (offs == 0 && size == 4) {
464 *reg = data;
465 } else {
466 *reg = deposit32(*reg, offs * BITS_PER_BYTE, size * BITS_PER_BYTE,
467 data);
471 static void ati_mm_write(void *opaque, hwaddr addr,
472 uint64_t data, unsigned int size)
474 ATIVGAState *s = opaque;
476 if (addr < CUR_OFFSET || addr > CUR_CLR1 || ATI_DEBUG_HW_CURSOR) {
477 trace_ati_mm_write(size, addr, ati_reg_name(addr & ~3ULL), data);
479 switch (addr) {
480 case MM_INDEX:
481 s->regs.mm_index = data;
482 break;
483 case MM_DATA ... MM_DATA + 3:
484 /* indexed access to regs or memory */
485 if (s->regs.mm_index & BIT(31)) {
486 uint32_t idx = s->regs.mm_index & ~BIT(31);
487 if (idx <= s->vga.vram_size - size) {
488 stn_le_p(s->vga.vram_ptr + idx, size, data);
490 } else {
491 ati_mm_write(s, s->regs.mm_index + addr - MM_DATA, data, size);
493 break;
494 case BIOS_0_SCRATCH ... BUS_CNTL - 1:
496 int i = (addr - BIOS_0_SCRATCH) / 4;
497 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF && i > 3) {
498 break;
500 ati_reg_write_offs(&s->regs.bios_scratch[i],
501 addr - (BIOS_0_SCRATCH + i * 4), data, size);
502 break;
504 case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
506 uint32_t val = s->regs.crtc_gen_cntl;
507 ati_reg_write_offs(&s->regs.crtc_gen_cntl,
508 addr - CRTC_GEN_CNTL, data, size);
509 if ((val & CRTC2_CUR_EN) != (s->regs.crtc_gen_cntl & CRTC2_CUR_EN)) {
510 if (s->cursor_guest_mode) {
511 s->vga.force_shadow = !!(s->regs.crtc_gen_cntl & CRTC2_CUR_EN);
512 } else {
513 if (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) {
514 ati_cursor_define(s);
516 dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
517 s->regs.cur_hv_pos & 0xffff,
518 (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) != 0);
521 if ((val & (CRTC2_EXT_DISP_EN | CRTC2_EN)) !=
522 (s->regs.crtc_gen_cntl & (CRTC2_EXT_DISP_EN | CRTC2_EN))) {
523 ati_vga_switch_mode(s);
525 break;
527 case CRTC_EXT_CNTL ... CRTC_EXT_CNTL + 3:
529 uint32_t val = s->regs.crtc_ext_cntl;
530 ati_reg_write_offs(&s->regs.crtc_ext_cntl,
531 addr - CRTC_EXT_CNTL, data, size);
532 if (s->regs.crtc_ext_cntl & CRT_CRTC_DISPLAY_DIS) {
533 DPRINTF("Display disabled\n");
534 s->vga.ar_index &= ~BIT(5);
535 } else {
536 DPRINTF("Display enabled\n");
537 s->vga.ar_index |= BIT(5);
538 ati_vga_switch_mode(s);
540 if ((val & CRT_CRTC_DISPLAY_DIS) !=
541 (s->regs.crtc_ext_cntl & CRT_CRTC_DISPLAY_DIS)) {
542 ati_vga_switch_mode(s);
544 break;
546 case DAC_CNTL:
547 s->regs.dac_cntl = data & 0xffffe3ff;
548 s->vga.dac_8bit = !!(data & DAC_8BIT_EN);
549 break;
550 case GPIO_VGA_DDC:
551 if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
552 /* FIXME: Maybe add a property to select VGA or DVI port? */
554 break;
555 case GPIO_DVI_DDC:
556 if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
557 s->regs.gpio_dvi_ddc = ati_i2c(&s->bbi2c, data, 0);
559 break;
560 case GPIO_MONID ... GPIO_MONID + 3:
561 /* FIXME What does Radeon have here? */
562 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
563 ati_reg_write_offs(&s->regs.gpio_monid,
564 addr - GPIO_MONID, data, size);
566 * Rage128p accesses DDC used to get EDID via these bits.
567 * Because some drivers access this via multiple byte writes
568 * we have to be careful when we send bits to avoid spurious
569 * changes in bitbang_i2c state. So only do it when mask is set
570 * and either the enable bits are changed or output bits changed
571 * while enabled.
573 if ((s->regs.gpio_monid & BIT(25)) &&
574 ((addr <= GPIO_MONID + 2 && addr + size > GPIO_MONID + 2) ||
575 (addr == GPIO_MONID && (s->regs.gpio_monid & 0x60000)))) {
576 s->regs.gpio_monid = ati_i2c(&s->bbi2c, s->regs.gpio_monid, 1);
579 break;
580 case PALETTE_INDEX ... PALETTE_INDEX + 3:
581 if (size == 4) {
582 vga_ioport_write(&s->vga, VGA_PEL_IR, (data >> 16) & 0xff);
583 vga_ioport_write(&s->vga, VGA_PEL_IW, data & 0xff);
584 } else {
585 if (addr == PALETTE_INDEX) {
586 vga_ioport_write(&s->vga, VGA_PEL_IW, data & 0xff);
587 } else {
588 vga_ioport_write(&s->vga, VGA_PEL_IR, data & 0xff);
591 break;
592 case PALETTE_DATA ... PALETTE_DATA + 3:
593 data <<= addr - PALETTE_DATA;
594 data = bswap32(data) >> 8;
595 vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
596 data >>= 8;
597 vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
598 data >>= 8;
599 vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
600 break;
601 case CRTC_H_TOTAL_DISP:
602 s->regs.crtc_h_total_disp = data & 0x07ff07ff;
603 break;
604 case CRTC_H_SYNC_STRT_WID:
605 s->regs.crtc_h_sync_strt_wid = data & 0x17bf1fff;
606 break;
607 case CRTC_V_TOTAL_DISP:
608 s->regs.crtc_v_total_disp = data & 0x0fff0fff;
609 break;
610 case CRTC_V_SYNC_STRT_WID:
611 s->regs.crtc_v_sync_strt_wid = data & 0x9f0fff;
612 break;
613 case CRTC_OFFSET:
614 s->regs.crtc_offset = data & 0xc7ffffff;
615 break;
616 case CRTC_OFFSET_CNTL:
617 s->regs.crtc_offset_cntl = data; /* FIXME */
618 break;
619 case CRTC_PITCH:
620 s->regs.crtc_pitch = data & 0x07ff07ff;
621 break;
622 case 0xf00 ... 0xfff:
623 /* read-only copy of PCI config space so ignore writes */
624 break;
625 case CUR_OFFSET:
626 if (s->regs.cur_offset != (data & 0x87fffff0)) {
627 s->regs.cur_offset = data & 0x87fffff0;
628 ati_cursor_define(s);
630 break;
631 case CUR_HORZ_VERT_POSN:
632 s->regs.cur_hv_pos = data & 0x3fff0fff;
633 if (data & BIT(31)) {
634 s->regs.cur_offset |= data & BIT(31);
635 } else if (s->regs.cur_offset & BIT(31)) {
636 s->regs.cur_offset &= ~BIT(31);
637 ati_cursor_define(s);
639 if (!s->cursor_guest_mode &&
640 (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(data & BIT(31))) {
641 dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
642 s->regs.cur_hv_pos & 0xffff, 1);
644 break;
645 case CUR_HORZ_VERT_OFF:
646 s->regs.cur_hv_offs = data & 0x3f003f;
647 if (data & BIT(31)) {
648 s->regs.cur_offset |= data & BIT(31);
649 } else if (s->regs.cur_offset & BIT(31)) {
650 s->regs.cur_offset &= ~BIT(31);
651 ati_cursor_define(s);
653 break;
654 case CUR_CLR0:
655 if (s->regs.cur_color0 != (data & 0xffffff)) {
656 s->regs.cur_color0 = data & 0xffffff;
657 ati_cursor_define(s);
659 break;
660 case CUR_CLR1:
662 * Update cursor unconditionally here because some clients set up
663 * other registers before actually writing cursor data to memory at
664 * offset so we would miss cursor change unless always updating here
666 s->regs.cur_color1 = data & 0xffffff;
667 ati_cursor_define(s);
668 break;
669 case DST_OFFSET:
670 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
671 s->regs.dst_offset = data & 0xfffffff0;
672 } else {
673 s->regs.dst_offset = data & 0xfffffc00;
675 break;
676 case DST_PITCH:
677 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
678 s->regs.dst_pitch = data & 0x3fff;
679 s->regs.dst_tile = (data >> 16) & 1;
680 } else {
681 s->regs.dst_pitch = data & 0x3ff0;
683 break;
684 case DST_TILE:
685 if (s->dev_id == PCI_DEVICE_ID_ATI_RADEON_QY) {
686 s->regs.dst_tile = data & 3;
688 break;
689 case DST_WIDTH:
690 s->regs.dst_width = data & 0x3fff;
691 ati_2d_blt(s);
692 break;
693 case DST_HEIGHT:
694 s->regs.dst_height = data & 0x3fff;
695 break;
696 case SRC_X:
697 s->regs.src_x = data & 0x3fff;
698 break;
699 case SRC_Y:
700 s->regs.src_y = data & 0x3fff;
701 break;
702 case DST_X:
703 s->regs.dst_x = data & 0x3fff;
704 break;
705 case DST_Y:
706 s->regs.dst_y = data & 0x3fff;
707 break;
708 case SRC_PITCH_OFFSET:
709 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
710 s->regs.src_offset = (data & 0x1fffff) << 5;
711 s->regs.src_pitch = (data & 0x7fe00000) >> 21;
712 s->regs.src_tile = data >> 31;
713 } else {
714 s->regs.src_offset = (data & 0x3fffff) << 10;
715 s->regs.src_pitch = (data & 0x3fc00000) >> 16;
716 s->regs.src_tile = (data >> 30) & 1;
718 break;
719 case DST_PITCH_OFFSET:
720 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
721 s->regs.dst_offset = (data & 0x1fffff) << 5;
722 s->regs.dst_pitch = (data & 0x7fe00000) >> 21;
723 s->regs.dst_tile = data >> 31;
724 } else {
725 s->regs.dst_offset = (data & 0x3fffff) << 10;
726 s->regs.dst_pitch = (data & 0x3fc00000) >> 16;
727 s->regs.dst_tile = data >> 30;
729 break;
730 case SRC_Y_X:
731 s->regs.src_x = data & 0x3fff;
732 s->regs.src_y = (data >> 16) & 0x3fff;
733 break;
734 case DST_Y_X:
735 s->regs.dst_x = data & 0x3fff;
736 s->regs.dst_y = (data >> 16) & 0x3fff;
737 break;
738 case DST_HEIGHT_WIDTH:
739 s->regs.dst_width = data & 0x3fff;
740 s->regs.dst_height = (data >> 16) & 0x3fff;
741 ati_2d_blt(s);
742 break;
743 case DP_GUI_MASTER_CNTL:
744 s->regs.dp_gui_master_cntl = data & 0xf800000f;
745 s->regs.dp_datatype = (data & 0x0f00) >> 8 | (data & 0x30f0) << 4 |
746 (data & 0x4000) << 16;
747 s->regs.dp_mix = (data & GMC_ROP3_MASK) | (data & 0x7000000) >> 16;
748 break;
749 case DST_WIDTH_X:
750 s->regs.dst_x = data & 0x3fff;
751 s->regs.dst_width = (data >> 16) & 0x3fff;
752 ati_2d_blt(s);
753 break;
754 case SRC_X_Y:
755 s->regs.src_y = data & 0x3fff;
756 s->regs.src_x = (data >> 16) & 0x3fff;
757 break;
758 case DST_X_Y:
759 s->regs.dst_y = data & 0x3fff;
760 s->regs.dst_x = (data >> 16) & 0x3fff;
761 break;
762 case DST_WIDTH_HEIGHT:
763 s->regs.dst_height = data & 0x3fff;
764 s->regs.dst_width = (data >> 16) & 0x3fff;
765 ati_2d_blt(s);
766 break;
767 case DST_HEIGHT_Y:
768 s->regs.dst_y = data & 0x3fff;
769 s->regs.dst_height = (data >> 16) & 0x3fff;
770 break;
771 case SRC_OFFSET:
772 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
773 s->regs.src_offset = data & 0xfffffff0;
774 } else {
775 s->regs.src_offset = data & 0xfffffc00;
777 break;
778 case SRC_PITCH:
779 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
780 s->regs.src_pitch = data & 0x3fff;
781 s->regs.src_tile = (data >> 16) & 1;
782 } else {
783 s->regs.src_pitch = data & 0x3ff0;
785 break;
786 case DP_BRUSH_BKGD_CLR:
787 s->regs.dp_brush_bkgd_clr = data;
788 break;
789 case DP_BRUSH_FRGD_CLR:
790 s->regs.dp_brush_frgd_clr = data;
791 break;
792 case DP_CNTL:
793 s->regs.dp_cntl = data;
794 break;
795 case DP_DATATYPE:
796 s->regs.dp_datatype = data & 0xe0070f0f;
797 break;
798 case DP_MIX:
799 s->regs.dp_mix = data & 0x00ff0700;
800 break;
801 case DP_WRITE_MASK:
802 s->regs.dp_write_mask = data;
803 break;
804 case DEFAULT_OFFSET:
805 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
806 s->regs.default_offset = data & 0xfffffff0;
807 } else {
808 /* Radeon has DEFAULT_PITCH_OFFSET here like DST_PITCH_OFFSET */
809 s->regs.default_offset = (data & 0x3fffff) << 10;
810 s->regs.default_pitch = (data & 0x3fc00000) >> 16;
811 s->regs.default_tile = data >> 30;
813 break;
814 case DEFAULT_PITCH:
815 if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
816 s->regs.default_pitch = data & 0x3fff;
817 s->regs.default_tile = (data >> 16) & 1;
819 break;
820 case DEFAULT_SC_BOTTOM_RIGHT:
821 s->regs.default_sc_bottom_right = data & 0x3fff3fff;
822 break;
823 default:
824 break;
828 static const MemoryRegionOps ati_mm_ops = {
829 .read = ati_mm_read,
830 .write = ati_mm_write,
831 .endianness = DEVICE_LITTLE_ENDIAN,
834 static void ati_vga_realize(PCIDevice *dev, Error **errp)
836 ATIVGAState *s = ATI_VGA(dev);
837 VGACommonState *vga = &s->vga;
839 if (s->model) {
840 int i;
841 for (i = 0; i < ARRAY_SIZE(ati_model_aliases); i++) {
842 if (!strcmp(s->model, ati_model_aliases[i].name)) {
843 s->dev_id = ati_model_aliases[i].dev_id;
844 break;
847 if (i >= ARRAY_SIZE(ati_model_aliases)) {
848 warn_report("Unknown ATI VGA model name, "
849 "using default rage128p");
852 if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF &&
853 s->dev_id != PCI_DEVICE_ID_ATI_RADEON_QY) {
854 error_setg(errp, "Unknown ATI VGA device id, "
855 "only 0x5046 and 0x5159 are supported");
856 return;
858 pci_set_word(dev->config + PCI_DEVICE_ID, s->dev_id);
860 if (s->dev_id == PCI_DEVICE_ID_ATI_RADEON_QY &&
861 s->vga.vram_size_mb < 16) {
862 warn_report("Too small video memory for device id");
863 s->vga.vram_size_mb = 16;
866 /* init vga bits */
867 vga_common_init(vga, OBJECT(s));
868 vga_init(vga, OBJECT(s), pci_address_space(dev),
869 pci_address_space_io(dev), true);
870 vga->con = graphic_console_init(DEVICE(s), 0, s->vga.hw_ops, &s->vga);
871 if (s->cursor_guest_mode) {
872 vga->cursor_invalidate = ati_cursor_invalidate;
873 vga->cursor_draw_line = ati_cursor_draw_line;
876 /* ddc, edid */
877 I2CBus *i2cbus = i2c_init_bus(DEVICE(s), "ati-vga.ddc");
878 bitbang_i2c_init(&s->bbi2c, i2cbus);
879 I2CSlave *i2cddc = I2C_SLAVE(qdev_create(BUS(i2cbus), TYPE_I2CDDC));
880 i2c_set_slave_address(i2cddc, 0x50);
882 /* mmio register space */
883 memory_region_init_io(&s->mm, OBJECT(s), &ati_mm_ops, s,
884 "ati.mmregs", 0x4000);
885 /* io space is alias to beginning of mmregs */
886 memory_region_init_alias(&s->io, OBJECT(s), "ati.io", &s->mm, 0, 0x100);
888 pci_register_bar(dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
889 pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
890 pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mm);
893 static void ati_vga_reset(DeviceState *dev)
895 ATIVGAState *s = ATI_VGA(dev);
897 /* reset vga */
898 vga_common_reset(&s->vga);
899 s->mode = VGA_MODE;
902 static void ati_vga_exit(PCIDevice *dev)
904 ATIVGAState *s = ATI_VGA(dev);
906 graphic_console_close(s->vga.con);
909 static Property ati_vga_properties[] = {
910 DEFINE_PROP_UINT32("vgamem_mb", ATIVGAState, vga.vram_size_mb, 16),
911 DEFINE_PROP_STRING("model", ATIVGAState, model),
912 DEFINE_PROP_UINT16("x-device-id", ATIVGAState, dev_id,
913 PCI_DEVICE_ID_ATI_RAGE128_PF),
914 DEFINE_PROP_BOOL("guest_hwcursor", ATIVGAState, cursor_guest_mode, false),
915 DEFINE_PROP_END_OF_LIST()
918 static void ati_vga_class_init(ObjectClass *klass, void *data)
920 DeviceClass *dc = DEVICE_CLASS(klass);
921 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
923 dc->reset = ati_vga_reset;
924 dc->props = ati_vga_properties;
925 dc->hotpluggable = false;
926 set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
928 k->class_id = PCI_CLASS_DISPLAY_VGA;
929 k->vendor_id = PCI_VENDOR_ID_ATI;
930 k->device_id = PCI_DEVICE_ID_ATI_RAGE128_PF;
931 k->romfile = "vgabios-ati.bin";
932 k->realize = ati_vga_realize;
933 k->exit = ati_vga_exit;
936 static const TypeInfo ati_vga_info = {
937 .name = TYPE_ATI_VGA,
938 .parent = TYPE_PCI_DEVICE,
939 .instance_size = sizeof(ATIVGAState),
940 .class_init = ati_vga_class_init,
941 .interfaces = (InterfaceInfo[]) {
942 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
943 { },
947 static void ati_vga_register_types(void)
949 type_register_static(&ati_vga_info);
952 type_init(ati_vga_register_types)