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.
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"
22 #include "vga-access.h"
23 #include "hw/qdev-properties.h"
26 #include "qemu/module.h"
27 #include "qemu/error-report.h"
28 #include "qapi/error.h"
29 #include "ui/console.h"
30 #include "hw/display/i2c-ddc.h"
33 #define ATI_DEBUG_HW_CURSOR 0
36 #define DEFAULT_X_PIXMAN 3
38 #define DEFAULT_X_PIXMAN 0
44 } ati_model_aliases
[] = {
45 { "rage128p", PCI_DEVICE_ID_ATI_RAGE128_PF
},
46 { "rv100", PCI_DEVICE_ID_ATI_RADEON_QY
},
49 enum { VGA_MODE
, EXT_MODE
};
51 static void ati_vga_switch_mode(ATIVGAState
*s
)
54 s
->mode
, !!(s
->regs
.crtc_gen_cntl
& CRTC2_EXT_DISP_EN
));
55 if (s
->regs
.crtc_gen_cntl
& CRTC2_EXT_DISP_EN
) {
56 /* Extended mode enabled */
58 if (s
->regs
.crtc_gen_cntl
& CRTC2_EN
) {
59 /* CRT controller enabled, use CRTC values */
60 /* FIXME Should these be the same as VGA CRTC regs? */
61 uint32_t offs
= s
->regs
.crtc_offset
& 0x07ffffff;
62 int stride
= (s
->regs
.crtc_pitch
& 0x7ff) * 8;
66 if (s
->regs
.crtc_h_total_disp
== 0) {
67 s
->regs
.crtc_h_total_disp
= ((640 / 8) - 1) << 16;
69 if (s
->regs
.crtc_v_total_disp
== 0) {
70 s
->regs
.crtc_v_total_disp
= (480 - 1) << 16;
72 h
= ((s
->regs
.crtc_h_total_disp
>> 16) + 1) * 8;
73 v
= (s
->regs
.crtc_v_total_disp
>> 16) + 1;
74 switch (s
->regs
.crtc_gen_cntl
& CRTC_PIX_WIDTH_MASK
) {
75 case CRTC_PIX_WIDTH_4BPP
:
78 case CRTC_PIX_WIDTH_8BPP
:
81 case CRTC_PIX_WIDTH_15BPP
:
84 case CRTC_PIX_WIDTH_16BPP
:
87 case CRTC_PIX_WIDTH_24BPP
:
90 case CRTC_PIX_WIDTH_32BPP
:
94 qemu_log_mask(LOG_UNIMP
, "Unsupported bpp value\n");
97 DPRINTF("Switching to %dx%d %d %d @ %x\n", h
, v
, stride
, bpp
, offs
);
98 vbe_ioport_write_index(&s
->vga
, 0, VBE_DISPI_INDEX_ENABLE
);
99 vbe_ioport_write_data(&s
->vga
, 0, VBE_DISPI_DISABLED
);
100 s
->vga
.big_endian_fb
= (s
->regs
.config_cntl
& APER_0_ENDIAN
||
101 s
->regs
.config_cntl
& APER_1_ENDIAN
?
103 /* reset VBE regs then set up mode */
104 s
->vga
.vbe_regs
[VBE_DISPI_INDEX_XRES
] = h
;
105 s
->vga
.vbe_regs
[VBE_DISPI_INDEX_YRES
] = v
;
106 s
->vga
.vbe_regs
[VBE_DISPI_INDEX_BPP
] = bpp
;
107 /* enable mode via ioport so it updates vga regs */
108 vbe_ioport_write_index(&s
->vga
, 0, VBE_DISPI_INDEX_ENABLE
);
109 vbe_ioport_write_data(&s
->vga
, 0, VBE_DISPI_ENABLED
|
110 VBE_DISPI_LFB_ENABLED
| VBE_DISPI_NOCLEARMEM
|
111 (s
->regs
.dac_cntl
& DAC_8BIT_EN
? VBE_DISPI_8BIT_DAC
: 0));
112 /* now set offset and stride after enable as that resets these */
114 int bypp
= DIV_ROUND_UP(bpp
, BITS_PER_BYTE
);
116 vbe_ioport_write_index(&s
->vga
, 0, VBE_DISPI_INDEX_VIRT_WIDTH
);
117 vbe_ioport_write_data(&s
->vga
, 0, stride
);
120 DPRINTF("CRTC offset is not multiple of pitch\n");
121 vbe_ioport_write_index(&s
->vga
, 0,
122 VBE_DISPI_INDEX_X_OFFSET
);
123 vbe_ioport_write_data(&s
->vga
, 0, offs
% stride
/ bypp
);
125 vbe_ioport_write_index(&s
->vga
, 0, VBE_DISPI_INDEX_Y_OFFSET
);
126 vbe_ioport_write_data(&s
->vga
, 0, offs
/ stride
);
127 DPRINTF("VBE offset (%d,%d), vbe_start_addr=%x\n",
128 s
->vga
.vbe_regs
[VBE_DISPI_INDEX_X_OFFSET
],
129 s
->vga
.vbe_regs
[VBE_DISPI_INDEX_Y_OFFSET
],
130 s
->vga
.vbe_start_addr
);
134 /* VGA mode enabled */
136 vbe_ioport_write_index(&s
->vga
, 0, VBE_DISPI_INDEX_ENABLE
);
137 vbe_ioport_write_data(&s
->vga
, 0, VBE_DISPI_DISABLED
);
141 /* Used by host side hardware cursor */
142 static void ati_cursor_define(ATIVGAState
*s
)
148 if ((s
->regs
.cur_offset
& BIT(31)) || s
->cursor_guest_mode
) {
149 return; /* Do not update cursor if locked or rendered by guest */
151 /* FIXME handle cur_hv_offs correctly */
152 srcoff
= s
->regs
.cur_offset
-
153 (s
->regs
.cur_hv_offs
>> 16) - (s
->regs
.cur_hv_offs
& 0xffff) * 16;
154 for (i
= 0; i
< 64; i
++) {
155 for (j
= 0; j
< 8; j
++, idx
++) {
156 data
[idx
] = vga_read_byte(&s
->vga
, srcoff
+ i
* 16 + j
);
157 data
[512 + idx
] = vga_read_byte(&s
->vga
, srcoff
+ i
* 16 + j
+ 8);
161 s
->cursor
= cursor_alloc(64, 64);
163 cursor_set_mono(s
->cursor
, s
->regs
.cur_color1
, s
->regs
.cur_color0
,
164 &data
[512], 1, &data
[0]);
165 dpy_cursor_define(s
->vga
.con
, s
->cursor
);
168 /* Alternatively support guest rendered hardware cursor */
169 static void ati_cursor_invalidate(VGACommonState
*vga
)
171 ATIVGAState
*s
= container_of(vga
, ATIVGAState
, vga
);
172 int size
= (s
->regs
.crtc_gen_cntl
& CRTC2_CUR_EN
) ? 64 : 0;
174 if (s
->regs
.cur_offset
& BIT(31)) {
175 return; /* Do not update cursor if locked */
177 if (s
->cursor_size
!= size
||
178 vga
->hw_cursor_x
!= s
->regs
.cur_hv_pos
>> 16 ||
179 vga
->hw_cursor_y
!= (s
->regs
.cur_hv_pos
& 0xffff) ||
180 s
->cursor_offset
!= s
->regs
.cur_offset
- (s
->regs
.cur_hv_offs
>> 16) -
181 (s
->regs
.cur_hv_offs
& 0xffff) * 16) {
182 /* Remove old cursor then update and show new one if needed */
183 vga_invalidate_scanlines(vga
, vga
->hw_cursor_y
, vga
->hw_cursor_y
+ 63);
184 vga
->hw_cursor_x
= s
->regs
.cur_hv_pos
>> 16;
185 vga
->hw_cursor_y
= s
->regs
.cur_hv_pos
& 0xffff;
186 s
->cursor_offset
= s
->regs
.cur_offset
- (s
->regs
.cur_hv_offs
>> 16) -
187 (s
->regs
.cur_hv_offs
& 0xffff) * 16;
188 s
->cursor_size
= size
;
190 vga_invalidate_scanlines(vga
,
191 vga
->hw_cursor_y
, vga
->hw_cursor_y
+ 63);
196 static void ati_cursor_draw_line(VGACommonState
*vga
, uint8_t *d
, int scr_y
)
198 ATIVGAState
*s
= container_of(vga
, ATIVGAState
, vga
);
200 uint32_t *dp
= (uint32_t *)d
;
203 if (!(s
->regs
.crtc_gen_cntl
& CRTC2_CUR_EN
) ||
204 scr_y
< vga
->hw_cursor_y
|| scr_y
>= vga
->hw_cursor_y
+ 64 ||
205 scr_y
> s
->regs
.crtc_v_total_disp
>> 16) {
208 /* FIXME handle cur_hv_offs correctly */
209 srcoff
= s
->cursor_offset
+ (scr_y
- vga
->hw_cursor_y
) * 16;
210 dp
= &dp
[vga
->hw_cursor_x
];
211 h
= ((s
->regs
.crtc_h_total_disp
>> 16) + 1) * 8;
212 for (i
= 0; i
< 8; i
++) {
214 uint8_t abits
= vga_read_byte(vga
, srcoff
+ i
);
215 uint8_t xbits
= vga_read_byte(vga
, srcoff
+ i
+ 8);
216 for (j
= 0; j
< 8; j
++, abits
<<= 1, xbits
<<= 1) {
217 if (abits
& BIT(7)) {
218 if (xbits
& BIT(7)) {
219 color
= dp
[i
* 8 + j
] ^ 0xffffffff; /* complement */
221 continue; /* transparent, no change */
224 color
= (xbits
& BIT(7) ? s
->regs
.cur_color1
:
225 s
->regs
.cur_color0
) | 0xff000000;
227 if (vga
->hw_cursor_x
+ i
* 8 + j
>= h
) {
228 return; /* end of screen, don't span to next line */
230 dp
[i
* 8 + j
] = color
;
235 static uint64_t ati_i2c(bitbang_i2c_interface
*i2c
, uint64_t data
, int base
)
237 bool c
= (data
& BIT(base
+ 17) ? !!(data
& BIT(base
+ 1)) : 1);
238 bool d
= (data
& BIT(base
+ 16) ? !!(data
& BIT(base
)) : 1);
240 bitbang_i2c_set(i2c
, BITBANG_I2C_SCL
, c
);
241 d
= bitbang_i2c_set(i2c
, BITBANG_I2C_SDA
, d
);
245 data
|= BIT(base
+ 9);
248 data
|= BIT(base
+ 8);
253 static void ati_vga_update_irq(ATIVGAState
*s
)
255 pci_set_irq(&s
->dev
, !!(s
->regs
.gen_int_status
& s
->regs
.gen_int_cntl
));
258 static void ati_vga_vblank_irq(void *opaque
)
260 ATIVGAState
*s
= opaque
;
262 timer_mod(&s
->vblank_timer
, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) +
263 NANOSECONDS_PER_SECOND
/ 60);
264 s
->regs
.gen_int_status
|= CRTC_VBLANK_INT
;
265 ati_vga_update_irq(s
);
268 static inline uint64_t ati_reg_read_offs(uint32_t reg
, int offs
,
271 if (offs
== 0 && size
== 4) {
274 return extract32(reg
, offs
* BITS_PER_BYTE
, size
* BITS_PER_BYTE
);
278 static uint64_t ati_mm_read(void *opaque
, hwaddr addr
, unsigned int size
)
280 ATIVGAState
*s
= opaque
;
285 val
= s
->regs
.mm_index
;
287 case MM_DATA
... MM_DATA
+ 3:
288 /* indexed access to regs or memory */
289 if (s
->regs
.mm_index
& BIT(31)) {
290 uint32_t idx
= s
->regs
.mm_index
& ~BIT(31);
291 if (idx
<= s
->vga
.vram_size
- size
) {
292 val
= ldn_le_p(s
->vga
.vram_ptr
+ idx
, size
);
294 } else if (s
->regs
.mm_index
> MM_DATA
+ 3) {
295 val
= ati_mm_read(s
, s
->regs
.mm_index
+ addr
- MM_DATA
, size
);
297 qemu_log_mask(LOG_GUEST_ERROR
,
298 "ati_mm_read: mm_index too small: %u\n", s
->regs
.mm_index
);
301 case BIOS_0_SCRATCH
... BUS_CNTL
- 1:
303 int i
= (addr
- BIOS_0_SCRATCH
) / 4;
304 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
&& i
> 3) {
307 val
= ati_reg_read_offs(s
->regs
.bios_scratch
[i
],
308 addr
- (BIOS_0_SCRATCH
+ i
* 4), size
);
312 val
= s
->regs
.gen_int_cntl
;
315 val
= s
->regs
.gen_int_status
;
317 case CRTC_GEN_CNTL
... CRTC_GEN_CNTL
+ 3:
318 val
= ati_reg_read_offs(s
->regs
.crtc_gen_cntl
,
319 addr
- CRTC_GEN_CNTL
, size
);
321 case CRTC_EXT_CNTL
... CRTC_EXT_CNTL
+ 3:
322 val
= ati_reg_read_offs(s
->regs
.crtc_ext_cntl
,
323 addr
- CRTC_EXT_CNTL
, size
);
326 val
= s
->regs
.dac_cntl
;
328 case GPIO_VGA_DDC
... GPIO_VGA_DDC
+ 3:
329 val
= ati_reg_read_offs(s
->regs
.gpio_vga_ddc
,
330 addr
- GPIO_VGA_DDC
, size
);
332 case GPIO_DVI_DDC
... GPIO_DVI_DDC
+ 3:
333 val
= ati_reg_read_offs(s
->regs
.gpio_dvi_ddc
,
334 addr
- GPIO_DVI_DDC
, size
);
336 case GPIO_MONID
... GPIO_MONID
+ 3:
337 val
= ati_reg_read_offs(s
->regs
.gpio_monid
,
338 addr
- GPIO_MONID
, size
);
341 /* FIXME unaligned access */
342 val
= vga_ioport_read(&s
->vga
, VGA_PEL_IR
) << 16;
343 val
|= vga_ioport_read(&s
->vga
, VGA_PEL_IW
) & 0xff;
346 val
= vga_ioport_read(&s
->vga
, VGA_PEL_D
);
348 case PALETTE_30_DATA
:
349 val
= s
->regs
.palette
[vga_ioport_read(&s
->vga
, VGA_PEL_IR
)];
352 val
= s
->regs
.config_cntl
;
355 val
= s
->vga
.vram_size
;
357 case CONFIG_APER_0_BASE
:
358 case CONFIG_APER_1_BASE
:
359 val
= pci_default_read_config(&s
->dev
,
360 PCI_BASE_ADDRESS_0
, size
) & 0xfffffff0;
362 case CONFIG_APER_SIZE
:
363 val
= s
->vga
.vram_size
/ 2;
365 case CONFIG_REG_1_BASE
:
366 val
= pci_default_read_config(&s
->dev
,
367 PCI_BASE_ADDRESS_2
, size
) & 0xfffffff0;
369 case CONFIG_REG_APER_SIZE
:
370 val
= memory_region_size(&s
->mm
) / 2;
373 val
= BIT(23); /* Radeon HDP_APER_CNTL */
378 case MEM_SDRAM_MODE_REG
:
379 if (s
->dev_id
!= PCI_DEVICE_ID_ATI_RAGE128_PF
) {
380 val
= BIT(28) | BIT(20);
385 val
= 64; /* free CMDFIFO entries */
387 case CRTC_H_TOTAL_DISP
:
388 val
= s
->regs
.crtc_h_total_disp
;
390 case CRTC_H_SYNC_STRT_WID
:
391 val
= s
->regs
.crtc_h_sync_strt_wid
;
393 case CRTC_V_TOTAL_DISP
:
394 val
= s
->regs
.crtc_v_total_disp
;
396 case CRTC_V_SYNC_STRT_WID
:
397 val
= s
->regs
.crtc_v_sync_strt_wid
;
400 val
= s
->regs
.crtc_offset
;
402 case CRTC_OFFSET_CNTL
:
403 val
= s
->regs
.crtc_offset_cntl
;
406 val
= s
->regs
.crtc_pitch
;
408 case 0xf00 ... 0xfff:
409 val
= pci_default_read_config(&s
->dev
, addr
- 0xf00, size
);
411 case CUR_OFFSET
... CUR_OFFSET
+ 3:
412 val
= ati_reg_read_offs(s
->regs
.cur_offset
, addr
- CUR_OFFSET
, size
);
414 case CUR_HORZ_VERT_POSN
... CUR_HORZ_VERT_POSN
+ 3:
415 val
= ati_reg_read_offs(s
->regs
.cur_hv_pos
,
416 addr
- CUR_HORZ_VERT_POSN
, size
);
417 if (addr
+ size
> CUR_HORZ_VERT_POSN
+ 3) {
418 val
|= (s
->regs
.cur_offset
& BIT(31)) >> (4 - size
);
421 case CUR_HORZ_VERT_OFF
... CUR_HORZ_VERT_OFF
+ 3:
422 val
= ati_reg_read_offs(s
->regs
.cur_hv_offs
,
423 addr
- CUR_HORZ_VERT_OFF
, size
);
424 if (addr
+ size
> CUR_HORZ_VERT_OFF
+ 3) {
425 val
|= (s
->regs
.cur_offset
& BIT(31)) >> (4 - size
);
428 case CUR_CLR0
... CUR_CLR0
+ 3:
429 val
= ati_reg_read_offs(s
->regs
.cur_color0
, addr
- CUR_CLR0
, size
);
431 case CUR_CLR1
... CUR_CLR1
+ 3:
432 val
= ati_reg_read_offs(s
->regs
.cur_color1
, addr
- CUR_CLR1
, size
);
435 val
= s
->regs
.dst_offset
;
438 val
= s
->regs
.dst_pitch
;
439 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
440 val
&= s
->regs
.dst_tile
<< 16;
444 val
= s
->regs
.dst_width
;
447 val
= s
->regs
.dst_height
;
461 case DP_GUI_MASTER_CNTL
:
462 val
= s
->regs
.dp_gui_master_cntl
;
465 val
= s
->regs
.src_offset
;
468 val
= s
->regs
.src_pitch
;
469 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
470 val
&= s
->regs
.src_tile
<< 16;
473 case DP_BRUSH_BKGD_CLR
:
474 val
= s
->regs
.dp_brush_bkgd_clr
;
476 case DP_BRUSH_FRGD_CLR
:
477 val
= s
->regs
.dp_brush_frgd_clr
;
479 case DP_SRC_FRGD_CLR
:
480 val
= s
->regs
.dp_src_frgd_clr
;
482 case DP_SRC_BKGD_CLR
:
483 val
= s
->regs
.dp_src_bkgd_clr
;
486 val
= s
->regs
.dp_cntl
;
489 val
= s
->regs
.dp_datatype
;
492 val
= s
->regs
.dp_mix
;
495 val
= s
->regs
.dp_write_mask
;
498 val
= s
->regs
.default_offset
;
499 if (s
->dev_id
!= PCI_DEVICE_ID_ATI_RAGE128_PF
) {
501 val
|= s
->regs
.default_pitch
<< 16;
502 val
|= s
->regs
.default_tile
<< 30;
506 val
= s
->regs
.default_pitch
;
507 val
|= s
->regs
.default_tile
<< 16;
509 case DEFAULT_SC_BOTTOM_RIGHT
:
510 val
= s
->regs
.default_sc_bottom_right
;
515 if (addr
< CUR_OFFSET
|| addr
> CUR_CLR1
|| ATI_DEBUG_HW_CURSOR
) {
516 trace_ati_mm_read(size
, addr
, ati_reg_name(addr
& ~3ULL), val
);
521 static inline void ati_reg_write_offs(uint32_t *reg
, int offs
,
522 uint64_t data
, unsigned int size
)
524 if (offs
== 0 && size
== 4) {
527 *reg
= deposit32(*reg
, offs
* BITS_PER_BYTE
, size
* BITS_PER_BYTE
,
532 static void ati_mm_write(void *opaque
, hwaddr addr
,
533 uint64_t data
, unsigned int size
)
535 ATIVGAState
*s
= opaque
;
537 if (addr
< CUR_OFFSET
|| addr
> CUR_CLR1
|| ATI_DEBUG_HW_CURSOR
) {
538 trace_ati_mm_write(size
, addr
, ati_reg_name(addr
& ~3ULL), data
);
542 s
->regs
.mm_index
= data
& ~3;
544 case MM_DATA
... MM_DATA
+ 3:
545 /* indexed access to regs or memory */
546 if (s
->regs
.mm_index
& BIT(31)) {
547 uint32_t idx
= s
->regs
.mm_index
& ~BIT(31);
548 if (idx
<= s
->vga
.vram_size
- size
) {
549 stn_le_p(s
->vga
.vram_ptr
+ idx
, size
, data
);
551 } else if (s
->regs
.mm_index
> MM_DATA
+ 3) {
552 ati_mm_write(s
, s
->regs
.mm_index
+ addr
- MM_DATA
, data
, size
);
554 qemu_log_mask(LOG_GUEST_ERROR
,
555 "ati_mm_write: mm_index too small: %u\n", s
->regs
.mm_index
);
558 case BIOS_0_SCRATCH
... BUS_CNTL
- 1:
560 int i
= (addr
- BIOS_0_SCRATCH
) / 4;
561 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
&& i
> 3) {
564 ati_reg_write_offs(&s
->regs
.bios_scratch
[i
],
565 addr
- (BIOS_0_SCRATCH
+ i
* 4), data
, size
);
569 s
->regs
.gen_int_cntl
= data
;
570 if (data
& CRTC_VBLANK_INT
) {
571 ati_vga_vblank_irq(s
);
573 timer_del(&s
->vblank_timer
);
574 ati_vga_update_irq(s
);
578 data
&= (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
?
579 0x000f040fUL
: 0xfc080effUL
);
580 s
->regs
.gen_int_status
&= ~data
;
581 ati_vga_update_irq(s
);
583 case CRTC_GEN_CNTL
... CRTC_GEN_CNTL
+ 3:
585 uint32_t val
= s
->regs
.crtc_gen_cntl
;
586 ati_reg_write_offs(&s
->regs
.crtc_gen_cntl
,
587 addr
- CRTC_GEN_CNTL
, data
, size
);
588 if ((val
& CRTC2_CUR_EN
) != (s
->regs
.crtc_gen_cntl
& CRTC2_CUR_EN
)) {
589 if (s
->cursor_guest_mode
) {
590 s
->vga
.force_shadow
= !!(s
->regs
.crtc_gen_cntl
& CRTC2_CUR_EN
);
592 if (s
->regs
.crtc_gen_cntl
& CRTC2_CUR_EN
) {
593 ati_cursor_define(s
);
595 dpy_mouse_set(s
->vga
.con
, s
->regs
.cur_hv_pos
>> 16,
596 s
->regs
.cur_hv_pos
& 0xffff,
597 (s
->regs
.crtc_gen_cntl
& CRTC2_CUR_EN
) != 0);
600 if ((val
& (CRTC2_EXT_DISP_EN
| CRTC2_EN
)) !=
601 (s
->regs
.crtc_gen_cntl
& (CRTC2_EXT_DISP_EN
| CRTC2_EN
))) {
602 ati_vga_switch_mode(s
);
606 case CRTC_EXT_CNTL
... CRTC_EXT_CNTL
+ 3:
608 uint32_t val
= s
->regs
.crtc_ext_cntl
;
609 ati_reg_write_offs(&s
->regs
.crtc_ext_cntl
,
610 addr
- CRTC_EXT_CNTL
, data
, size
);
611 if (s
->regs
.crtc_ext_cntl
& CRT_CRTC_DISPLAY_DIS
) {
612 DPRINTF("Display disabled\n");
613 s
->vga
.ar_index
&= ~BIT(5);
615 DPRINTF("Display enabled\n");
616 s
->vga
.ar_index
|= BIT(5);
617 ati_vga_switch_mode(s
);
619 if ((val
& CRT_CRTC_DISPLAY_DIS
) !=
620 (s
->regs
.crtc_ext_cntl
& CRT_CRTC_DISPLAY_DIS
)) {
621 ati_vga_switch_mode(s
);
626 s
->regs
.dac_cntl
= data
& 0xffffe3ff;
627 s
->vga
.dac_8bit
= !!(data
& DAC_8BIT_EN
);
630 * GPIO regs for DDC access. Because some drivers access these via
631 * multiple byte writes we have to be careful when we send bits to
632 * avoid spurious changes in bitbang_i2c state. Only do it when either
633 * the enable bits are changed or output bits changed while enabled.
635 case GPIO_VGA_DDC
... GPIO_VGA_DDC
+ 3:
636 if (s
->dev_id
!= PCI_DEVICE_ID_ATI_RAGE128_PF
) {
637 /* FIXME: Maybe add a property to select VGA or DVI port? */
640 case GPIO_DVI_DDC
... GPIO_DVI_DDC
+ 3:
641 if (s
->dev_id
!= PCI_DEVICE_ID_ATI_RAGE128_PF
) {
642 ati_reg_write_offs(&s
->regs
.gpio_dvi_ddc
,
643 addr
- GPIO_DVI_DDC
, data
, size
);
644 if ((addr
<= GPIO_DVI_DDC
+ 2 && addr
+ size
> GPIO_DVI_DDC
+ 2) ||
645 (addr
== GPIO_DVI_DDC
&& (s
->regs
.gpio_dvi_ddc
& 0x30000))) {
646 s
->regs
.gpio_dvi_ddc
= ati_i2c(&s
->bbi2c
,
647 s
->regs
.gpio_dvi_ddc
, 0);
651 case GPIO_MONID
... GPIO_MONID
+ 3:
652 /* FIXME What does Radeon have here? */
653 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
654 /* Rage128p accesses DDC via MONID(1-2) with additional mask bit */
655 ati_reg_write_offs(&s
->regs
.gpio_monid
,
656 addr
- GPIO_MONID
, data
, size
);
657 if ((s
->regs
.gpio_monid
& BIT(25)) &&
658 ((addr
<= GPIO_MONID
+ 2 && addr
+ size
> GPIO_MONID
+ 2) ||
659 (addr
== GPIO_MONID
&& (s
->regs
.gpio_monid
& 0x60000)))) {
660 s
->regs
.gpio_monid
= ati_i2c(&s
->bbi2c
, s
->regs
.gpio_monid
, 1);
664 case PALETTE_INDEX
... PALETTE_INDEX
+ 3:
666 vga_ioport_write(&s
->vga
, VGA_PEL_IR
, (data
>> 16) & 0xff);
667 vga_ioport_write(&s
->vga
, VGA_PEL_IW
, data
& 0xff);
669 if (addr
== PALETTE_INDEX
) {
670 vga_ioport_write(&s
->vga
, VGA_PEL_IW
, data
& 0xff);
672 vga_ioport_write(&s
->vga
, VGA_PEL_IR
, data
& 0xff);
676 case PALETTE_DATA
... PALETTE_DATA
+ 3:
677 data
<<= addr
- PALETTE_DATA
;
678 data
= bswap32(data
) >> 8;
679 vga_ioport_write(&s
->vga
, VGA_PEL_D
, data
& 0xff);
681 vga_ioport_write(&s
->vga
, VGA_PEL_D
, data
& 0xff);
683 vga_ioport_write(&s
->vga
, VGA_PEL_D
, data
& 0xff);
685 case PALETTE_30_DATA
:
686 s
->regs
.palette
[vga_ioport_read(&s
->vga
, VGA_PEL_IW
)] = data
;
687 vga_ioport_write(&s
->vga
, VGA_PEL_D
, (data
>> 22) & 0xff);
688 vga_ioport_write(&s
->vga
, VGA_PEL_D
, (data
>> 12) & 0xff);
689 vga_ioport_write(&s
->vga
, VGA_PEL_D
, (data
>> 2) & 0xff);
692 s
->regs
.config_cntl
= data
;
694 case CRTC_H_TOTAL_DISP
:
695 s
->regs
.crtc_h_total_disp
= data
& 0x07ff07ff;
697 case CRTC_H_SYNC_STRT_WID
:
698 s
->regs
.crtc_h_sync_strt_wid
= data
& 0x17bf1fff;
700 case CRTC_V_TOTAL_DISP
:
701 s
->regs
.crtc_v_total_disp
= data
& 0x0fff0fff;
703 case CRTC_V_SYNC_STRT_WID
:
704 s
->regs
.crtc_v_sync_strt_wid
= data
& 0x9f0fff;
707 s
->regs
.crtc_offset
= data
& 0xc7ffffff;
709 case CRTC_OFFSET_CNTL
:
710 s
->regs
.crtc_offset_cntl
= data
; /* FIXME */
713 s
->regs
.crtc_pitch
= data
& 0x07ff07ff;
715 case 0xf00 ... 0xfff:
716 /* read-only copy of PCI config space so ignore writes */
718 case CUR_OFFSET
... CUR_OFFSET
+ 3:
720 uint32_t t
= s
->regs
.cur_offset
;
722 ati_reg_write_offs(&t
, addr
- CUR_OFFSET
, data
, size
);
724 if (s
->regs
.cur_offset
!= t
) {
725 s
->regs
.cur_offset
= t
;
726 ati_cursor_define(s
);
730 case CUR_HORZ_VERT_POSN
... CUR_HORZ_VERT_POSN
+ 3:
732 uint32_t t
= s
->regs
.cur_hv_pos
| (s
->regs
.cur_offset
& BIT(31));
734 ati_reg_write_offs(&t
, addr
- CUR_HORZ_VERT_POSN
, data
, size
);
735 s
->regs
.cur_hv_pos
= t
& 0x3fff0fff;
737 s
->regs
.cur_offset
|= t
& BIT(31);
738 } else if (s
->regs
.cur_offset
& BIT(31)) {
739 s
->regs
.cur_offset
&= ~BIT(31);
740 ati_cursor_define(s
);
742 if (!s
->cursor_guest_mode
&&
743 (s
->regs
.crtc_gen_cntl
& CRTC2_CUR_EN
) && !(t
& BIT(31))) {
744 dpy_mouse_set(s
->vga
.con
, s
->regs
.cur_hv_pos
>> 16,
745 s
->regs
.cur_hv_pos
& 0xffff, 1);
749 case CUR_HORZ_VERT_OFF
:
751 uint32_t t
= s
->regs
.cur_hv_offs
| (s
->regs
.cur_offset
& BIT(31));
753 ati_reg_write_offs(&t
, addr
- CUR_HORZ_VERT_OFF
, data
, size
);
754 s
->regs
.cur_hv_offs
= t
& 0x3f003f;
756 s
->regs
.cur_offset
|= t
& BIT(31);
757 } else if (s
->regs
.cur_offset
& BIT(31)) {
758 s
->regs
.cur_offset
&= ~BIT(31);
759 ati_cursor_define(s
);
763 case CUR_CLR0
... CUR_CLR0
+ 3:
765 uint32_t t
= s
->regs
.cur_color0
;
767 ati_reg_write_offs(&t
, addr
- CUR_CLR0
, data
, size
);
769 if (s
->regs
.cur_color0
!= t
) {
770 s
->regs
.cur_color0
= t
;
771 ati_cursor_define(s
);
775 case CUR_CLR1
... CUR_CLR1
+ 3:
777 * Update cursor unconditionally here because some clients set up
778 * other registers before actually writing cursor data to memory at
779 * offset so we would miss cursor change unless always updating here
781 ati_reg_write_offs(&s
->regs
.cur_color1
, addr
- CUR_CLR1
, data
, size
);
782 s
->regs
.cur_color1
&= 0xffffff;
783 ati_cursor_define(s
);
786 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
787 s
->regs
.dst_offset
= data
& 0xfffffff0;
789 s
->regs
.dst_offset
= data
& 0xfffffc00;
793 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
794 s
->regs
.dst_pitch
= data
& 0x3fff;
795 s
->regs
.dst_tile
= (data
>> 16) & 1;
797 s
->regs
.dst_pitch
= data
& 0x3ff0;
801 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RADEON_QY
) {
802 s
->regs
.dst_tile
= data
& 3;
806 s
->regs
.dst_width
= data
& 0x3fff;
810 s
->regs
.dst_height
= data
& 0x3fff;
813 s
->regs
.src_x
= data
& 0x3fff;
816 s
->regs
.src_y
= data
& 0x3fff;
819 s
->regs
.dst_x
= data
& 0x3fff;
822 s
->regs
.dst_y
= data
& 0x3fff;
824 case SRC_PITCH_OFFSET
:
825 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
826 s
->regs
.src_offset
= (data
& 0x1fffff) << 5;
827 s
->regs
.src_pitch
= (data
& 0x7fe00000) >> 21;
828 s
->regs
.src_tile
= data
>> 31;
830 s
->regs
.src_offset
= (data
& 0x3fffff) << 10;
831 s
->regs
.src_pitch
= (data
& 0x3fc00000) >> 16;
832 s
->regs
.src_tile
= (data
>> 30) & 1;
835 case DST_PITCH_OFFSET
:
836 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
837 s
->regs
.dst_offset
= (data
& 0x1fffff) << 5;
838 s
->regs
.dst_pitch
= (data
& 0x7fe00000) >> 21;
839 s
->regs
.dst_tile
= data
>> 31;
841 s
->regs
.dst_offset
= (data
& 0x3fffff) << 10;
842 s
->regs
.dst_pitch
= (data
& 0x3fc00000) >> 16;
843 s
->regs
.dst_tile
= data
>> 30;
847 s
->regs
.src_x
= data
& 0x3fff;
848 s
->regs
.src_y
= (data
>> 16) & 0x3fff;
851 s
->regs
.dst_x
= data
& 0x3fff;
852 s
->regs
.dst_y
= (data
>> 16) & 0x3fff;
854 case DST_HEIGHT_WIDTH
:
855 s
->regs
.dst_width
= data
& 0x3fff;
856 s
->regs
.dst_height
= (data
>> 16) & 0x3fff;
859 case DP_GUI_MASTER_CNTL
:
860 s
->regs
.dp_gui_master_cntl
= data
& 0xf800000f;
861 s
->regs
.dp_datatype
= (data
& 0x0f00) >> 8 | (data
& 0x30f0) << 4 |
862 (data
& 0x4000) << 16;
863 s
->regs
.dp_mix
= (data
& GMC_ROP3_MASK
) | (data
& 0x7000000) >> 16;
866 s
->regs
.dst_x
= data
& 0x3fff;
867 s
->regs
.dst_width
= (data
>> 16) & 0x3fff;
871 s
->regs
.src_y
= data
& 0x3fff;
872 s
->regs
.src_x
= (data
>> 16) & 0x3fff;
875 s
->regs
.dst_y
= data
& 0x3fff;
876 s
->regs
.dst_x
= (data
>> 16) & 0x3fff;
878 case DST_WIDTH_HEIGHT
:
879 s
->regs
.dst_height
= data
& 0x3fff;
880 s
->regs
.dst_width
= (data
>> 16) & 0x3fff;
884 s
->regs
.dst_y
= data
& 0x3fff;
885 s
->regs
.dst_height
= (data
>> 16) & 0x3fff;
888 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
889 s
->regs
.src_offset
= data
& 0xfffffff0;
891 s
->regs
.src_offset
= data
& 0xfffffc00;
895 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
896 s
->regs
.src_pitch
= data
& 0x3fff;
897 s
->regs
.src_tile
= (data
>> 16) & 1;
899 s
->regs
.src_pitch
= data
& 0x3ff0;
902 case DP_BRUSH_BKGD_CLR
:
903 s
->regs
.dp_brush_bkgd_clr
= data
;
905 case DP_BRUSH_FRGD_CLR
:
906 s
->regs
.dp_brush_frgd_clr
= data
;
909 s
->regs
.dp_cntl
= data
;
912 s
->regs
.dp_datatype
= data
& 0xe0070f0f;
915 s
->regs
.dp_mix
= data
& 0x00ff0700;
918 s
->regs
.dp_write_mask
= data
;
921 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
922 s
->regs
.default_offset
= data
& 0xfffffff0;
924 /* Radeon has DEFAULT_PITCH_OFFSET here like DST_PITCH_OFFSET */
925 s
->regs
.default_offset
= (data
& 0x3fffff) << 10;
926 s
->regs
.default_pitch
= (data
& 0x3fc00000) >> 16;
927 s
->regs
.default_tile
= data
>> 30;
931 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RAGE128_PF
) {
932 s
->regs
.default_pitch
= data
& 0x3fff;
933 s
->regs
.default_tile
= (data
>> 16) & 1;
936 case DEFAULT_SC_BOTTOM_RIGHT
:
937 s
->regs
.default_sc_bottom_right
= data
& 0x3fff3fff;
944 static const MemoryRegionOps ati_mm_ops
= {
946 .write
= ati_mm_write
,
947 .endianness
= DEVICE_LITTLE_ENDIAN
,
950 static void ati_vga_realize(PCIDevice
*dev
, Error
**errp
)
952 ATIVGAState
*s
= ATI_VGA(dev
);
953 VGACommonState
*vga
= &s
->vga
;
955 #ifndef CONFIG_PIXMAN
956 if (s
->use_pixman
!= 0) {
957 warn_report("x-pixman != 0, not effective without PIXMAN");
963 for (i
= 0; i
< ARRAY_SIZE(ati_model_aliases
); i
++) {
964 if (!strcmp(s
->model
, ati_model_aliases
[i
].name
)) {
965 s
->dev_id
= ati_model_aliases
[i
].dev_id
;
969 if (i
>= ARRAY_SIZE(ati_model_aliases
)) {
970 warn_report("Unknown ATI VGA model name, "
971 "using default rage128p");
974 if (s
->dev_id
!= PCI_DEVICE_ID_ATI_RAGE128_PF
&&
975 s
->dev_id
!= PCI_DEVICE_ID_ATI_RADEON_QY
) {
976 error_setg(errp
, "Unknown ATI VGA device id, "
977 "only 0x5046 and 0x5159 are supported");
980 pci_set_word(dev
->config
+ PCI_DEVICE_ID
, s
->dev_id
);
982 if (s
->dev_id
== PCI_DEVICE_ID_ATI_RADEON_QY
&&
983 s
->vga
.vram_size_mb
< 16) {
984 warn_report("Too small video memory for device id");
985 s
->vga
.vram_size_mb
= 16;
989 if (!vga_common_init(vga
, OBJECT(s
), errp
)) {
992 vga_init(vga
, OBJECT(s
), pci_address_space(dev
),
993 pci_address_space_io(dev
), true);
994 vga
->con
= graphic_console_init(DEVICE(s
), 0, s
->vga
.hw_ops
, &s
->vga
);
995 if (s
->cursor_guest_mode
) {
996 vga
->cursor_invalidate
= ati_cursor_invalidate
;
997 vga
->cursor_draw_line
= ati_cursor_draw_line
;
1001 I2CBus
*i2cbus
= i2c_init_bus(DEVICE(s
), "ati-vga.ddc");
1002 bitbang_i2c_init(&s
->bbi2c
, i2cbus
);
1003 I2CSlave
*i2cddc
= I2C_SLAVE(qdev_new(TYPE_I2CDDC
));
1004 i2c_slave_set_address(i2cddc
, 0x50);
1005 qdev_realize_and_unref(DEVICE(i2cddc
), BUS(i2cbus
), &error_abort
);
1007 /* mmio register space */
1008 memory_region_init_io(&s
->mm
, OBJECT(s
), &ati_mm_ops
, s
,
1009 "ati.mmregs", 0x4000);
1010 /* io space is alias to beginning of mmregs */
1011 memory_region_init_alias(&s
->io
, OBJECT(s
), "ati.io", &s
->mm
, 0, 0x100);
1013 pci_register_bar(dev
, 0, PCI_BASE_ADDRESS_MEM_PREFETCH
, &vga
->vram
);
1014 pci_register_bar(dev
, 1, PCI_BASE_ADDRESS_SPACE_IO
, &s
->io
);
1015 pci_register_bar(dev
, 2, PCI_BASE_ADDRESS_SPACE_MEMORY
, &s
->mm
);
1017 /* most interrupts are not yet emulated but MacOS needs at least VBlank */
1018 dev
->config
[PCI_INTERRUPT_PIN
] = 1;
1019 timer_init_ns(&s
->vblank_timer
, QEMU_CLOCK_VIRTUAL
, ati_vga_vblank_irq
, s
);
1022 static void ati_vga_reset(DeviceState
*dev
)
1024 ATIVGAState
*s
= ATI_VGA(dev
);
1026 timer_del(&s
->vblank_timer
);
1027 ati_vga_update_irq(s
);
1030 vga_common_reset(&s
->vga
);
1034 static void ati_vga_exit(PCIDevice
*dev
)
1036 ATIVGAState
*s
= ATI_VGA(dev
);
1038 timer_del(&s
->vblank_timer
);
1039 graphic_console_close(s
->vga
.con
);
1042 static Property ati_vga_properties
[] = {
1043 DEFINE_PROP_UINT32("vgamem_mb", ATIVGAState
, vga
.vram_size_mb
, 16),
1044 DEFINE_PROP_STRING("model", ATIVGAState
, model
),
1045 DEFINE_PROP_UINT16("x-device-id", ATIVGAState
, dev_id
,
1046 PCI_DEVICE_ID_ATI_RAGE128_PF
),
1047 DEFINE_PROP_BOOL("guest_hwcursor", ATIVGAState
, cursor_guest_mode
, false),
1048 /* this is a debug option, prefer PROP_UINT over PROP_BIT for simplicity */
1049 DEFINE_PROP_UINT8("x-pixman", ATIVGAState
, use_pixman
, DEFAULT_X_PIXMAN
),
1050 DEFINE_PROP_END_OF_LIST()
1053 static void ati_vga_class_init(ObjectClass
*klass
, void *data
)
1055 DeviceClass
*dc
= DEVICE_CLASS(klass
);
1056 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
1058 dc
->reset
= ati_vga_reset
;
1059 device_class_set_props(dc
, ati_vga_properties
);
1060 dc
->hotpluggable
= false;
1061 set_bit(DEVICE_CATEGORY_DISPLAY
, dc
->categories
);
1063 k
->class_id
= PCI_CLASS_DISPLAY_VGA
;
1064 k
->vendor_id
= PCI_VENDOR_ID_ATI
;
1065 k
->device_id
= PCI_DEVICE_ID_ATI_RAGE128_PF
;
1066 k
->romfile
= "vgabios-ati.bin";
1067 k
->realize
= ati_vga_realize
;
1068 k
->exit
= ati_vga_exit
;
1071 static void ati_vga_init(Object
*o
)
1073 object_property_set_description(o
, "x-pixman", "Use pixman for: "
1074 "1: fill, 2: blit");
1077 static const TypeInfo ati_vga_info
= {
1078 .name
= TYPE_ATI_VGA
,
1079 .parent
= TYPE_PCI_DEVICE
,
1080 .instance_size
= sizeof(ATIVGAState
),
1081 .class_init
= ati_vga_class_init
,
1082 .instance_init
= ati_vga_init
,
1083 .interfaces
= (InterfaceInfo
[]) {
1084 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
1089 static void ati_vga_register_types(void)
1091 type_register_static(&ati_vga_info
);
1094 type_init(ati_vga_register_types
)