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