xref: /openbmc/qemu/hw/display/ati.c (revision 37677d7d)
1 /*
2  * QEMU ATI SVGA emulation
3  *
4  * Copyright (c) 2019 BALATON Zoltan
5  *
6  * This work is licensed under the GNU GPL license version 2 or later.
7  */
8 
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)
17  */
18 
19 #include "qemu/osdep.h"
20 #include "ati_int.h"
21 #include "ati_regs.h"
22 #include "vga_regs.h"
23 #include "qemu/log.h"
24 #include "qemu/module.h"
25 #include "qemu/error-report.h"
26 #include "qapi/error.h"
27 #include "hw/hw.h"
28 #include "ui/console.h"
29 #include "trace.h"
30 
31 #define ATI_DEBUG_HW_CURSOR 0
32 
33 static const struct {
34     const char *name;
35     uint16_t dev_id;
36 } ati_model_aliases[] = {
37     { "rage128p", PCI_DEVICE_ID_ATI_RAGE128_PF },
38     { "rv100", PCI_DEVICE_ID_ATI_RADEON_QY },
39 };
40 
41 enum { VGA_MODE, EXT_MODE };
42 
43 static void ati_vga_switch_mode(ATIVGAState *s)
44 {
45     DPRINTF("%d -> %d\n",
46             s->mode, !!(s->regs.crtc_gen_cntl & CRTC2_EXT_DISP_EN));
47     if (s->regs.crtc_gen_cntl & CRTC2_EXT_DISP_EN) {
48         /* Extended mode enabled */
49         s->mode = EXT_MODE;
50         if (s->regs.crtc_gen_cntl & CRTC2_EN) {
51             /* CRT controller enabled, use CRTC values */
52             uint32_t offs = s->regs.crtc_offset & 0x07ffffff;
53             int stride = (s->regs.crtc_pitch & 0x7ff) * 8;
54             int bpp = 0;
55             int h, v;
56 
57             if (s->regs.crtc_h_total_disp == 0) {
58                 s->regs.crtc_h_total_disp = ((640 / 8) - 1) << 16;
59             }
60             if (s->regs.crtc_v_total_disp == 0) {
61                 s->regs.crtc_v_total_disp = (480 - 1) << 16;
62             }
63             h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8;
64             v = (s->regs.crtc_v_total_disp >> 16) + 1;
65             switch (s->regs.crtc_gen_cntl & CRTC_PIX_WIDTH_MASK) {
66             case CRTC_PIX_WIDTH_4BPP:
67                 bpp = 4;
68                 break;
69             case CRTC_PIX_WIDTH_8BPP:
70                 bpp = 8;
71                 break;
72             case CRTC_PIX_WIDTH_15BPP:
73                 bpp = 15;
74                 break;
75             case CRTC_PIX_WIDTH_16BPP:
76                 bpp = 16;
77                 break;
78             case CRTC_PIX_WIDTH_24BPP:
79                 bpp = 24;
80                 break;
81             case CRTC_PIX_WIDTH_32BPP:
82                 bpp = 32;
83                 break;
84             default:
85                 qemu_log_mask(LOG_UNIMP, "Unsupported bpp value\n");
86             }
87             assert(bpp != 0);
88             DPRINTF("Switching to %dx%d %d %d @ %x\n", h, v, stride, bpp, offs);
89             vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
90             vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
91             /* reset VBE regs then set up mode */
92             s->vga.vbe_regs[VBE_DISPI_INDEX_XRES] = h;
93             s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] = v;
94             s->vga.vbe_regs[VBE_DISPI_INDEX_BPP] = bpp;
95             /* enable mode via ioport so it updates vga regs */
96             vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
97             vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_ENABLED |
98                 VBE_DISPI_LFB_ENABLED | VBE_DISPI_NOCLEARMEM |
99                 (s->regs.dac_cntl & DAC_8BIT_EN ? VBE_DISPI_8BIT_DAC : 0));
100             /* now set offset and stride after enable as that resets these */
101             if (stride) {
102                 vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_VIRT_WIDTH);
103                 vbe_ioport_write_data(&s->vga, 0, stride);
104                 if (offs % stride == 0) {
105                     vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_Y_OFFSET);
106                     vbe_ioport_write_data(&s->vga, 0, offs / stride);
107                 } else {
108                     /* FIXME what to do with this? */
109                     error_report("VGA offset is not multiple of pitch, "
110                                  "expect bad picture");
111                 }
112             }
113         }
114     } else {
115         /* VGA mode enabled */
116         s->mode = VGA_MODE;
117         vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
118         vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
119     }
120 }
121 
122 /* Used by host side hardware cursor */
123 static void ati_cursor_define(ATIVGAState *s)
124 {
125     uint8_t data[1024];
126     uint8_t *src;
127     int i, j, idx = 0;
128 
129     if ((s->regs.cur_offset & BIT(31)) || s->cursor_guest_mode) {
130         return; /* Do not update cursor if locked or rendered by guest */
131     }
132     /* FIXME handle cur_hv_offs correctly */
133     src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) +
134           s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
135           (s->regs.cur_hv_offs & 0xffff) * 16;
136     for (i = 0; i < 64; i++) {
137         for (j = 0; j < 8; j++, idx++) {
138             data[idx] = src[i * 16 + j];
139             data[512 + idx] = src[i * 16 + j + 8];
140         }
141     }
142     if (!s->cursor) {
143         s->cursor = cursor_alloc(64, 64);
144     }
145     cursor_set_mono(s->cursor, s->regs.cur_color1, s->regs.cur_color0,
146                     &data[512], 1, &data[0]);
147     dpy_cursor_define(s->vga.con, s->cursor);
148 }
149 
150 /* Alternatively support guest rendered hardware cursor */
151 static void ati_cursor_invalidate(VGACommonState *vga)
152 {
153     ATIVGAState *s = container_of(vga, ATIVGAState, vga);
154     int size = (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) ? 64 : 0;
155 
156     if (s->regs.cur_offset & BIT(31)) {
157         return; /* Do not update cursor if locked */
158     }
159     if (s->cursor_size != size ||
160         vga->hw_cursor_x != s->regs.cur_hv_pos >> 16 ||
161         vga->hw_cursor_y != (s->regs.cur_hv_pos & 0xffff) ||
162         s->cursor_offset != s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
163         (s->regs.cur_hv_offs & 0xffff) * 16) {
164         /* Remove old cursor then update and show new one if needed */
165         vga_invalidate_scanlines(vga, vga->hw_cursor_y, vga->hw_cursor_y + 63);
166         vga->hw_cursor_x = s->regs.cur_hv_pos >> 16;
167         vga->hw_cursor_y = s->regs.cur_hv_pos & 0xffff;
168         s->cursor_offset = s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
169                            (s->regs.cur_hv_offs & 0xffff) * 16;
170         s->cursor_size = size;
171         if (size) {
172             vga_invalidate_scanlines(vga,
173                                      vga->hw_cursor_y, vga->hw_cursor_y + 63);
174         }
175     }
176 }
177 
178 static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y)
179 {
180     ATIVGAState *s = container_of(vga, ATIVGAState, vga);
181     uint8_t *src;
182     uint32_t *dp = (uint32_t *)d;
183     int i, j, h;
184 
185     if (!(s->regs.crtc_gen_cntl & CRTC2_CUR_EN) ||
186         scr_y < vga->hw_cursor_y || scr_y >= vga->hw_cursor_y + 64 ||
187         scr_y > s->regs.crtc_v_total_disp >> 16) {
188         return;
189     }
190     /* FIXME handle cur_hv_offs correctly */
191     src = s->vga.vram_ptr + (s->regs.crtc_offset & 0x07ffffff) +
192           s->cursor_offset + (scr_y - vga->hw_cursor_y) * 16;
193     dp = &dp[vga->hw_cursor_x];
194     h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8;
195     for (i = 0; i < 8; i++) {
196         uint32_t color;
197         uint8_t abits = src[i];
198         uint8_t xbits = src[i + 8];
199         for (j = 0; j < 8; j++, abits <<= 1, xbits <<= 1) {
200             if (abits & BIT(7)) {
201                 if (xbits & BIT(7)) {
202                     color = dp[i * 8 + j] ^ 0xffffffff; /* complement */
203                 } else {
204                     continue; /* transparent, no change */
205                 }
206             } else {
207                 color = (xbits & BIT(7) ? s->regs.cur_color1 :
208                                           s->regs.cur_color0) << 8 | 0xff;
209             }
210             if (vga->hw_cursor_x + i * 8 + j >= h) {
211                 return; /* end of screen, don't span to next line */
212             }
213             dp[i * 8 + j] = color;
214         }
215     }
216 }
217 
218 static inline uint64_t ati_reg_read_offs(uint32_t reg, int offs,
219                                          unsigned int size)
220 {
221     if (offs == 0 && size == 4) {
222         return reg;
223     } else {
224         return extract32(reg, offs * BITS_PER_BYTE, size * BITS_PER_BYTE);
225     }
226 }
227 
228 static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
229 {
230     ATIVGAState *s = opaque;
231     uint64_t val = 0;
232 
233     switch (addr) {
234     case MM_INDEX:
235         val = s->regs.mm_index;
236         break;
237     case MM_DATA ... MM_DATA + 3:
238         /* indexed access to regs or memory */
239         if (s->regs.mm_index & BIT(31)) {
240             uint32_t idx = s->regs.mm_index & ~BIT(31);
241             if (idx <= s->vga.vram_size - size) {
242                 val = ldn_le_p(s->vga.vram_ptr + idx, size);
243             }
244         } else {
245             val = ati_mm_read(s, s->regs.mm_index + addr - MM_DATA, size);
246         }
247         break;
248     case BIOS_0_SCRATCH ... BUS_CNTL - 1:
249     {
250         int i = (addr - BIOS_0_SCRATCH) / 4;
251         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF && i > 3) {
252             break;
253         }
254         val = ati_reg_read_offs(s->regs.bios_scratch[i],
255                                 addr - (BIOS_0_SCRATCH + i * 4), size);
256         break;
257     }
258     case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
259         val = ati_reg_read_offs(s->regs.crtc_gen_cntl,
260                                 addr - CRTC_GEN_CNTL, size);
261         break;
262     case CRTC_EXT_CNTL ... CRTC_EXT_CNTL + 3:
263         val = ati_reg_read_offs(s->regs.crtc_ext_cntl,
264                                 addr - CRTC_EXT_CNTL, size);
265         break;
266     case DAC_CNTL:
267         val = s->regs.dac_cntl;
268         break;
269 /*    case GPIO_MONID: FIXME hook up DDC I2C here */
270     case PALETTE_INDEX:
271         /* FIXME unaligned access */
272         val = vga_ioport_read(&s->vga, VGA_PEL_IR) << 16;
273         val |= vga_ioport_read(&s->vga, VGA_PEL_IW) & 0xff;
274         break;
275     case PALETTE_DATA:
276         val = vga_ioport_read(&s->vga, VGA_PEL_D);
277         break;
278     case CNFG_MEMSIZE:
279         val = s->vga.vram_size;
280         break;
281     case MC_STATUS:
282         val = 5;
283         break;
284     case RBBM_STATUS:
285     case GUI_STAT:
286         val = 64; /* free CMDFIFO entries */
287         break;
288     case CRTC_H_TOTAL_DISP:
289         val = s->regs.crtc_h_total_disp;
290         break;
291     case CRTC_H_SYNC_STRT_WID:
292         val = s->regs.crtc_h_sync_strt_wid;
293         break;
294     case CRTC_V_TOTAL_DISP:
295         val = s->regs.crtc_v_total_disp;
296         break;
297     case CRTC_V_SYNC_STRT_WID:
298         val = s->regs.crtc_v_sync_strt_wid;
299         break;
300     case CRTC_OFFSET:
301         val = s->regs.crtc_offset;
302         break;
303     case CRTC_OFFSET_CNTL:
304         val = s->regs.crtc_offset_cntl;
305         break;
306     case CRTC_PITCH:
307         val = s->regs.crtc_pitch;
308         break;
309     case 0xf00 ... 0xfff:
310         val = pci_default_read_config(&s->dev, addr - 0xf00, size);
311         break;
312     case CUR_OFFSET:
313         val = s->regs.cur_offset;
314         break;
315     case CUR_HORZ_VERT_POSN:
316         val = s->regs.cur_hv_pos;
317         val |= s->regs.cur_offset & BIT(31);
318         break;
319     case CUR_HORZ_VERT_OFF:
320         val = s->regs.cur_hv_offs;
321         val |= s->regs.cur_offset & BIT(31);
322         break;
323     case CUR_CLR0:
324         val = s->regs.cur_color0;
325         break;
326     case CUR_CLR1:
327         val = s->regs.cur_color1;
328         break;
329     case DST_OFFSET:
330         val = s->regs.dst_offset;
331         break;
332     case DST_PITCH:
333         val = s->regs.dst_pitch;
334         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
335             val &= s->regs.dst_tile << 16;
336         }
337         break;
338     case DST_WIDTH:
339         val = s->regs.dst_width;
340         break;
341     case DST_HEIGHT:
342         val = s->regs.dst_height;
343         break;
344     case SRC_X:
345         val = s->regs.src_x;
346         break;
347     case SRC_Y:
348         val = s->regs.src_y;
349         break;
350     case DST_X:
351         val = s->regs.dst_x;
352         break;
353     case DST_Y:
354         val = s->regs.dst_y;
355         break;
356     case DP_GUI_MASTER_CNTL:
357         val = s->regs.dp_gui_master_cntl;
358         break;
359     case SRC_OFFSET:
360         val = s->regs.src_offset;
361         break;
362     case SRC_PITCH:
363         val = s->regs.src_pitch;
364         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
365             val &= s->regs.src_tile << 16;
366         }
367         break;
368     case DP_BRUSH_BKGD_CLR:
369         val = s->regs.dp_brush_bkgd_clr;
370         break;
371     case DP_BRUSH_FRGD_CLR:
372         val = s->regs.dp_brush_frgd_clr;
373         break;
374     case DP_SRC_FRGD_CLR:
375         val = s->regs.dp_src_frgd_clr;
376         break;
377     case DP_SRC_BKGD_CLR:
378         val = s->regs.dp_src_bkgd_clr;
379         break;
380     case DP_CNTL:
381         val = s->regs.dp_cntl;
382         break;
383     case DP_DATATYPE:
384         val = s->regs.dp_datatype;
385         break;
386     case DP_MIX:
387         val = s->regs.dp_mix;
388         break;
389     case DP_WRITE_MASK:
390         val = s->regs.dp_write_mask;
391         break;
392     case DEFAULT_OFFSET:
393         val = s->regs.default_offset;
394         break;
395     case DEFAULT_PITCH:
396         val = s->regs.default_pitch;
397         break;
398     case DEFAULT_SC_BOTTOM_RIGHT:
399         val = s->regs.default_sc_bottom_right;
400         break;
401     default:
402         break;
403     }
404     if (addr < CUR_OFFSET || addr > CUR_CLR1 || ATI_DEBUG_HW_CURSOR) {
405         trace_ati_mm_read(size, addr, ati_reg_name(addr & ~3ULL), val);
406     }
407     return val;
408 }
409 
410 static inline void ati_reg_write_offs(uint32_t *reg, int offs,
411                                       uint64_t data, unsigned int size)
412 {
413     if (offs == 0 && size == 4) {
414         *reg = data;
415     } else {
416         *reg = deposit32(*reg, offs * BITS_PER_BYTE, size * BITS_PER_BYTE,
417                          data);
418     }
419 }
420 
421 static void ati_mm_write(void *opaque, hwaddr addr,
422                            uint64_t data, unsigned int size)
423 {
424     ATIVGAState *s = opaque;
425 
426     if (addr < CUR_OFFSET || addr > CUR_CLR1 || ATI_DEBUG_HW_CURSOR) {
427         trace_ati_mm_write(size, addr, ati_reg_name(addr & ~3ULL), data);
428     }
429     switch (addr) {
430     case MM_INDEX:
431         s->regs.mm_index = data;
432         break;
433     case MM_DATA ... MM_DATA + 3:
434         /* indexed access to regs or memory */
435         if (s->regs.mm_index & BIT(31)) {
436             uint32_t idx = s->regs.mm_index & ~BIT(31);
437             if (idx <= s->vga.vram_size - size) {
438                 stn_le_p(s->vga.vram_ptr + idx, size, data);
439             }
440         } else {
441             ati_mm_write(s, s->regs.mm_index + addr - MM_DATA, data, size);
442         }
443         break;
444     case BIOS_0_SCRATCH ... BUS_CNTL - 1:
445     {
446         int i = (addr - BIOS_0_SCRATCH) / 4;
447         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF && i > 3) {
448             break;
449         }
450         ati_reg_write_offs(&s->regs.bios_scratch[i],
451                            addr - (BIOS_0_SCRATCH + i * 4), data, size);
452         break;
453     }
454     case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
455     {
456         uint32_t val = s->regs.crtc_gen_cntl;
457         ati_reg_write_offs(&s->regs.crtc_gen_cntl,
458                            addr - CRTC_GEN_CNTL, data, size);
459         if ((val & CRTC2_CUR_EN) != (s->regs.crtc_gen_cntl & CRTC2_CUR_EN)) {
460             if (s->cursor_guest_mode) {
461                 s->vga.force_shadow = !!(s->regs.crtc_gen_cntl & CRTC2_CUR_EN);
462             } else {
463                 if (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) {
464                     ati_cursor_define(s);
465                 }
466                 dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
467                               s->regs.cur_hv_pos & 0xffff,
468                               (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) != 0);
469             }
470         }
471         if ((val & (CRTC2_EXT_DISP_EN | CRTC2_EN)) !=
472             (s->regs.crtc_gen_cntl & (CRTC2_EXT_DISP_EN | CRTC2_EN))) {
473             ati_vga_switch_mode(s);
474         }
475         break;
476     }
477     case CRTC_EXT_CNTL ... CRTC_EXT_CNTL + 3:
478     {
479         uint32_t val = s->regs.crtc_ext_cntl;
480         ati_reg_write_offs(&s->regs.crtc_ext_cntl,
481                            addr - CRTC_EXT_CNTL, data, size);
482         if (s->regs.crtc_ext_cntl & CRT_CRTC_DISPLAY_DIS) {
483             DPRINTF("Display disabled\n");
484             s->vga.ar_index &= ~BIT(5);
485         } else {
486             DPRINTF("Display enabled\n");
487             s->vga.ar_index |= BIT(5);
488             ati_vga_switch_mode(s);
489         }
490         if ((val & CRT_CRTC_DISPLAY_DIS) !=
491             (s->regs.crtc_ext_cntl & CRT_CRTC_DISPLAY_DIS)) {
492             ati_vga_switch_mode(s);
493         }
494         break;
495     }
496     case DAC_CNTL:
497         s->regs.dac_cntl = data & 0xffffe3ff;
498         s->vga.dac_8bit = !!(data & DAC_8BIT_EN);
499         break;
500 /*    case GPIO_MONID: FIXME hook up DDC I2C here */
501     case PALETTE_INDEX ... PALETTE_INDEX + 3:
502         if (size == 4) {
503             vga_ioport_write(&s->vga, VGA_PEL_IR, (data >> 16) & 0xff);
504             vga_ioport_write(&s->vga, VGA_PEL_IW, data & 0xff);
505         } else {
506             if (addr == PALETTE_INDEX) {
507                 vga_ioport_write(&s->vga, VGA_PEL_IW, data & 0xff);
508             } else {
509                 vga_ioport_write(&s->vga, VGA_PEL_IR, data & 0xff);
510             }
511         }
512         break;
513     case PALETTE_DATA ... PALETTE_DATA + 3:
514         data <<= addr - PALETTE_DATA;
515         data = bswap32(data) >> 8;
516         vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
517         data >>= 8;
518         vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
519         data >>= 8;
520         vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
521         break;
522     case CRTC_H_TOTAL_DISP:
523         s->regs.crtc_h_total_disp = data & 0x07ff07ff;
524         break;
525     case CRTC_H_SYNC_STRT_WID:
526         s->regs.crtc_h_sync_strt_wid = data & 0x17bf1fff;
527         break;
528     case CRTC_V_TOTAL_DISP:
529         s->regs.crtc_v_total_disp = data & 0x0fff0fff;
530         break;
531     case CRTC_V_SYNC_STRT_WID:
532         s->regs.crtc_v_sync_strt_wid = data & 0x9f0fff;
533         break;
534     case CRTC_OFFSET:
535         s->regs.crtc_offset = data & 0xc7ffffff;
536         break;
537     case CRTC_OFFSET_CNTL:
538         s->regs.crtc_offset_cntl = data; /* FIXME */
539         break;
540     case CRTC_PITCH:
541         s->regs.crtc_pitch = data & 0x07ff07ff;
542         break;
543     case 0xf00 ... 0xfff:
544         /* read-only copy of PCI config space so ignore writes */
545         break;
546     case CUR_OFFSET:
547         if (s->regs.cur_offset != (data & 0x87fffff0)) {
548             s->regs.cur_offset = data & 0x87fffff0;
549             ati_cursor_define(s);
550         }
551         break;
552     case CUR_HORZ_VERT_POSN:
553         s->regs.cur_hv_pos = data & 0x3fff0fff;
554         if (data & BIT(31)) {
555             s->regs.cur_offset |= data & BIT(31);
556         } else if (s->regs.cur_offset & BIT(31)) {
557             s->regs.cur_offset &= ~BIT(31);
558             ati_cursor_define(s);
559         }
560         if (!s->cursor_guest_mode &&
561             (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(data & BIT(31))) {
562             dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
563                           s->regs.cur_hv_pos & 0xffff, 1);
564         }
565         break;
566     case CUR_HORZ_VERT_OFF:
567         s->regs.cur_hv_offs = data & 0x3f003f;
568         if (data & BIT(31)) {
569             s->regs.cur_offset |= data & BIT(31);
570         } else if (s->regs.cur_offset & BIT(31)) {
571             s->regs.cur_offset &= ~BIT(31);
572             ati_cursor_define(s);
573         }
574         break;
575     case CUR_CLR0:
576         if (s->regs.cur_color0 != (data & 0xffffff)) {
577             s->regs.cur_color0 = data & 0xffffff;
578             ati_cursor_define(s);
579         }
580         break;
581     case CUR_CLR1:
582         /*
583          * Update cursor unconditionally here because some clients set up
584          * other registers before actually writing cursor data to memory at
585          * offset so we would miss cursor change unless always updating here
586          */
587         s->regs.cur_color1 = data & 0xffffff;
588         ati_cursor_define(s);
589         break;
590     case DST_OFFSET:
591         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
592             s->regs.dst_offset = data & 0xfffffff0;
593         } else {
594             s->regs.dst_offset = data & 0xfffffc00;
595         }
596         break;
597     case DST_PITCH:
598         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
599             s->regs.dst_pitch = data & 0x3fff;
600             s->regs.dst_tile = (data >> 16) & 1;
601         } else {
602             s->regs.dst_pitch = data & 0x3ff0;
603         }
604         break;
605     case DST_TILE:
606         if (s->dev_id == PCI_DEVICE_ID_ATI_RADEON_QY) {
607             s->regs.dst_tile = data & 3;
608         }
609         break;
610     case DST_WIDTH:
611         s->regs.dst_width = data & 0x3fff;
612         ati_2d_blt(s);
613         break;
614     case DST_HEIGHT:
615         s->regs.dst_height = data & 0x3fff;
616         break;
617     case SRC_X:
618         s->regs.src_x = data & 0x3fff;
619         break;
620     case SRC_Y:
621         s->regs.src_y = data & 0x3fff;
622         break;
623     case DST_X:
624         s->regs.dst_x = data & 0x3fff;
625         break;
626     case DST_Y:
627         s->regs.dst_y = data & 0x3fff;
628         break;
629     case SRC_PITCH_OFFSET:
630         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
631             s->regs.src_offset = (data & 0x1fffff) << 5;
632             s->regs.src_pitch = (data >> 21) & 0x3ff;
633             s->regs.src_tile = data >> 31;
634         } else {
635             s->regs.src_offset = (data & 0x3fffff) << 11;
636             s->regs.src_pitch = (data & 0x3fc00000) >> 16;
637             s->regs.src_tile = (data >> 30) & 1;
638         }
639         break;
640     case DST_PITCH_OFFSET:
641         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
642             s->regs.dst_offset = (data & 0x1fffff) << 5;
643             s->regs.dst_pitch = (data >> 21) & 0x3ff;
644             s->regs.dst_tile = data >> 31;
645         } else {
646             s->regs.dst_offset = (data & 0x3fffff) << 11;
647             s->regs.dst_pitch = (data & 0x3fc00000) >> 16;
648             s->regs.dst_tile = data >> 30;
649         }
650         break;
651     case SRC_Y_X:
652         s->regs.src_x = data & 0x3fff;
653         s->regs.src_y = (data >> 16) & 0x3fff;
654         break;
655     case DST_Y_X:
656         s->regs.dst_x = data & 0x3fff;
657         s->regs.dst_y = (data >> 16) & 0x3fff;
658         break;
659     case DST_HEIGHT_WIDTH:
660         s->regs.dst_width = data & 0x3fff;
661         s->regs.dst_height = (data >> 16) & 0x3fff;
662         ati_2d_blt(s);
663         break;
664     case DP_GUI_MASTER_CNTL:
665         s->regs.dp_gui_master_cntl = data & 0xf800000f;
666         s->regs.dp_datatype = (data & 0x0f00) >> 8 | (data & 0x30f0) << 4 |
667                               (data & 0x4000) << 16;
668         s->regs.dp_mix = (data & GMC_ROP3_MASK) | (data & 0x7000000) >> 16;
669         break;
670     case DST_WIDTH_X:
671         s->regs.dst_x = data & 0x3fff;
672         s->regs.dst_width = (data >> 16) & 0x3fff;
673         ati_2d_blt(s);
674         break;
675     case SRC_X_Y:
676         s->regs.src_y = data & 0x3fff;
677         s->regs.src_x = (data >> 16) & 0x3fff;
678         break;
679     case DST_X_Y:
680         s->regs.dst_y = data & 0x3fff;
681         s->regs.dst_x = (data >> 16) & 0x3fff;
682         break;
683     case DST_WIDTH_HEIGHT:
684         s->regs.dst_height = data & 0x3fff;
685         s->regs.dst_width = (data >> 16) & 0x3fff;
686         ati_2d_blt(s);
687         break;
688     case DST_HEIGHT_Y:
689         s->regs.dst_y = data & 0x3fff;
690         s->regs.dst_height = (data >> 16) & 0x3fff;
691         break;
692     case SRC_OFFSET:
693         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
694             s->regs.src_offset = data & 0xfffffff0;
695         } else {
696             s->regs.src_offset = data & 0xfffffc00;
697         }
698         break;
699     case SRC_PITCH:
700         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
701             s->regs.src_pitch = data & 0x3fff;
702             s->regs.src_tile = (data >> 16) & 1;
703         } else {
704             s->regs.src_pitch = data & 0x3ff0;
705         }
706         break;
707     case DP_BRUSH_BKGD_CLR:
708         s->regs.dp_brush_bkgd_clr = data;
709         break;
710     case DP_BRUSH_FRGD_CLR:
711         s->regs.dp_brush_frgd_clr = data;
712         break;
713     case DP_CNTL:
714         s->regs.dp_cntl = data;
715         break;
716     case DP_DATATYPE:
717         s->regs.dp_datatype = data & 0xe0070f0f;
718         break;
719     case DP_MIX:
720         s->regs.dp_mix = data & 0x00ff0700;
721         break;
722     case DP_WRITE_MASK:
723         s->regs.dp_write_mask = data;
724         break;
725     case DEFAULT_OFFSET:
726         data &= (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF ?
727                  0x03fffc00 : 0xfffffc00);
728         s->regs.default_offset = data;
729         break;
730     case DEFAULT_PITCH:
731         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
732             s->regs.default_pitch = data & 0x103ff;
733         }
734         break;
735     case DEFAULT_SC_BOTTOM_RIGHT:
736         s->regs.default_sc_bottom_right = data & 0x3fff3fff;
737         break;
738     default:
739         break;
740     }
741 }
742 
743 static const MemoryRegionOps ati_mm_ops = {
744     .read = ati_mm_read,
745     .write = ati_mm_write,
746     .endianness = DEVICE_LITTLE_ENDIAN,
747 };
748 
749 static void ati_vga_realize(PCIDevice *dev, Error **errp)
750 {
751     ATIVGAState *s = ATI_VGA(dev);
752     VGACommonState *vga = &s->vga;
753 
754     if (s->model) {
755         int i;
756         for (i = 0; i < ARRAY_SIZE(ati_model_aliases); i++) {
757             if (!strcmp(s->model, ati_model_aliases[i].name)) {
758                 s->dev_id = ati_model_aliases[i].dev_id;
759                 break;
760             }
761         }
762         if (i >= ARRAY_SIZE(ati_model_aliases)) {
763             warn_report("Unknown ATI VGA model name, "
764                         "using default rage128p");
765         }
766     }
767     if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF &&
768         s->dev_id != PCI_DEVICE_ID_ATI_RADEON_QY) {
769         error_setg(errp, "Unknown ATI VGA device id, "
770                    "only 0x5046 and 0x5159 are supported");
771         return;
772     }
773     pci_set_word(dev->config + PCI_DEVICE_ID, s->dev_id);
774 
775     if (s->dev_id == PCI_DEVICE_ID_ATI_RADEON_QY &&
776         s->vga.vram_size_mb < 16) {
777         warn_report("Too small video memory for device id");
778         s->vga.vram_size_mb = 16;
779     }
780 
781     /* init vga bits */
782     vga_common_init(vga, OBJECT(s));
783     vga_init(vga, OBJECT(s), pci_address_space(dev),
784              pci_address_space_io(dev), true);
785     vga->con = graphic_console_init(DEVICE(s), 0, s->vga.hw_ops, &s->vga);
786     if (s->cursor_guest_mode) {
787         vga->cursor_invalidate = ati_cursor_invalidate;
788         vga->cursor_draw_line = ati_cursor_draw_line;
789     }
790 
791     /* mmio register space */
792     memory_region_init_io(&s->mm, OBJECT(s), &ati_mm_ops, s,
793                           "ati.mmregs", 0x4000);
794     /* io space is alias to beginning of mmregs */
795     memory_region_init_alias(&s->io, OBJECT(s), "ati.io", &s->mm, 0, 0x100);
796 
797     pci_register_bar(dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
798     pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
799     pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mm);
800 }
801 
802 static void ati_vga_reset(DeviceState *dev)
803 {
804     ATIVGAState *s = ATI_VGA(dev);
805 
806     /* reset vga */
807     vga_common_reset(&s->vga);
808     s->mode = VGA_MODE;
809 }
810 
811 static void ati_vga_exit(PCIDevice *dev)
812 {
813     ATIVGAState *s = ATI_VGA(dev);
814 
815     graphic_console_close(s->vga.con);
816 }
817 
818 static Property ati_vga_properties[] = {
819     DEFINE_PROP_UINT32("vgamem_mb", ATIVGAState, vga.vram_size_mb, 16),
820     DEFINE_PROP_STRING("model", ATIVGAState, model),
821     DEFINE_PROP_UINT16("x-device-id", ATIVGAState, dev_id,
822                        PCI_DEVICE_ID_ATI_RAGE128_PF),
823     DEFINE_PROP_BOOL("guest_hwcursor", ATIVGAState, cursor_guest_mode, false),
824     DEFINE_PROP_END_OF_LIST()
825 };
826 
827 static void ati_vga_class_init(ObjectClass *klass, void *data)
828 {
829     DeviceClass *dc = DEVICE_CLASS(klass);
830     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
831 
832     dc->reset = ati_vga_reset;
833     dc->props = ati_vga_properties;
834     dc->hotpluggable = false;
835     set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
836 
837     k->class_id = PCI_CLASS_DISPLAY_VGA;
838     k->vendor_id = PCI_VENDOR_ID_ATI;
839     k->device_id = PCI_DEVICE_ID_ATI_RAGE128_PF;
840     k->romfile = "vgabios-stdvga.bin";
841     k->realize = ati_vga_realize;
842     k->exit = ati_vga_exit;
843 }
844 
845 static const TypeInfo ati_vga_info = {
846     .name = TYPE_ATI_VGA,
847     .parent = TYPE_PCI_DEVICE,
848     .instance_size = sizeof(ATIVGAState),
849     .class_init = ati_vga_class_init,
850     .interfaces = (InterfaceInfo[]) {
851           { INTERFACE_CONVENTIONAL_PCI_DEVICE },
852           { },
853     },
854 };
855 
856 static void ati_vga_register_types(void)
857 {
858     type_register_static(&ati_vga_info);
859 }
860 
861 type_init(ati_vga_register_types)
862