xref: /openbmc/qemu/hw/display/ati.c (revision e452053097371880910c744a5d42ae2df058a4a7)
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-access.h"
23 #include "hw/qdev-properties.h"
24 #include "vga_regs.h"
25 #include "qemu/bswap.h"
26 #include "qemu/log.h"
27 #include "qemu/module.h"
28 #include "qemu/error-report.h"
29 #include "qapi/error.h"
30 #include "ui/console.h"
31 #include "hw/display/i2c-ddc.h"
32 #include "trace.h"
33 
34 #define ATI_DEBUG_HW_CURSOR 0
35 
36 #ifdef CONFIG_PIXMAN
37 #define DEFAULT_X_PIXMAN 3
38 #else
39 #define DEFAULT_X_PIXMAN 0
40 #endif
41 
42 static const struct {
43     const char *name;
44     uint16_t dev_id;
45 } ati_model_aliases[] = {
46     { "rage128p", PCI_DEVICE_ID_ATI_RAGE128_PF },
47     { "rv100", PCI_DEVICE_ID_ATI_RADEON_QY },
48 };
49 
50 enum { VGA_MODE, EXT_MODE };
51 
ati_vga_switch_mode(ATIVGAState * s)52 static void ati_vga_switch_mode(ATIVGAState *s)
53 {
54     DPRINTF("%d -> %d\n",
55             s->mode, !!(s->regs.crtc_gen_cntl & CRTC2_EXT_DISP_EN));
56     if (s->regs.crtc_gen_cntl & CRTC2_EXT_DISP_EN) {
57         /* Extended mode enabled */
58         s->mode = EXT_MODE;
59         if (s->regs.crtc_gen_cntl & CRTC2_EN) {
60             /* CRT controller enabled, use CRTC values */
61             /* FIXME Should these be the same as VGA CRTC regs? */
62             uint32_t offs = s->regs.crtc_offset & 0x07ffffff;
63             int stride = (s->regs.crtc_pitch & 0x7ff) * 8;
64             int bpp = 0;
65             int h, v;
66 
67             if (s->regs.crtc_h_total_disp == 0) {
68                 s->regs.crtc_h_total_disp = ((640 / 8) - 1) << 16;
69             }
70             if (s->regs.crtc_v_total_disp == 0) {
71                 s->regs.crtc_v_total_disp = (480 - 1) << 16;
72             }
73             h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8;
74             v = (s->regs.crtc_v_total_disp >> 16) + 1;
75             switch (s->regs.crtc_gen_cntl & CRTC_PIX_WIDTH_MASK) {
76             case CRTC_PIX_WIDTH_4BPP:
77                 bpp = 4;
78                 break;
79             case CRTC_PIX_WIDTH_8BPP:
80                 bpp = 8;
81                 break;
82             case CRTC_PIX_WIDTH_15BPP:
83                 bpp = 15;
84                 break;
85             case CRTC_PIX_WIDTH_16BPP:
86                 bpp = 16;
87                 break;
88             case CRTC_PIX_WIDTH_24BPP:
89                 bpp = 24;
90                 break;
91             case CRTC_PIX_WIDTH_32BPP:
92                 bpp = 32;
93                 break;
94             default:
95                 qemu_log_mask(LOG_UNIMP, "Unsupported bpp value\n");
96                 return;
97             }
98             DPRINTF("Switching to %dx%d %d %d @ %x\n", h, v, stride, bpp, offs);
99             vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
100             vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
101             s->vga.big_endian_fb = (s->regs.config_cntl & APER_0_ENDIAN ||
102                                     s->regs.config_cntl & APER_1_ENDIAN ?
103                                     true : false);
104             /* reset VBE regs then set up mode */
105             s->vga.vbe_regs[VBE_DISPI_INDEX_XRES] = h;
106             s->vga.vbe_regs[VBE_DISPI_INDEX_YRES] = v;
107             s->vga.vbe_regs[VBE_DISPI_INDEX_BPP] = bpp;
108             /* enable mode via ioport so it updates vga regs */
109             vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
110             vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_ENABLED |
111                 VBE_DISPI_LFB_ENABLED | VBE_DISPI_NOCLEARMEM |
112                 (s->regs.dac_cntl & DAC_8BIT_EN ? VBE_DISPI_8BIT_DAC : 0));
113             /* now set offset and stride after enable as that resets these */
114             if (stride) {
115                 int bypp = DIV_ROUND_UP(bpp, BITS_PER_BYTE);
116 
117                 vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_VIRT_WIDTH);
118                 vbe_ioport_write_data(&s->vga, 0, stride);
119                 stride *= bypp;
120                 if (offs % stride) {
121                     DPRINTF("CRTC offset is not multiple of pitch\n");
122                     vbe_ioport_write_index(&s->vga, 0,
123                                            VBE_DISPI_INDEX_X_OFFSET);
124                     vbe_ioport_write_data(&s->vga, 0, offs % stride / bypp);
125                 }
126                 vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_Y_OFFSET);
127                 vbe_ioport_write_data(&s->vga, 0, offs / stride);
128                 DPRINTF("VBE offset (%d,%d), vbe_start_addr=%x\n",
129                         s->vga.vbe_regs[VBE_DISPI_INDEX_X_OFFSET],
130                         s->vga.vbe_regs[VBE_DISPI_INDEX_Y_OFFSET],
131                         s->vga.vbe_start_addr);
132             }
133         }
134     } else {
135         /* VGA mode enabled */
136         s->mode = VGA_MODE;
137         vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
138         vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
139     }
140 }
141 
142 /* Used by host side hardware cursor */
ati_cursor_define(ATIVGAState * s)143 static void ati_cursor_define(ATIVGAState *s)
144 {
145     uint8_t data[1024];
146     uint32_t srcoff;
147     int i, j, idx = 0;
148 
149     if ((s->regs.cur_offset & BIT(31)) || s->cursor_guest_mode) {
150         return; /* Do not update cursor if locked or rendered by guest */
151     }
152     /* FIXME handle cur_hv_offs correctly */
153     srcoff = s->regs.cur_offset -
154         (s->regs.cur_hv_offs >> 16) - (s->regs.cur_hv_offs & 0xffff) * 16;
155     for (i = 0; i < 64; i++) {
156         for (j = 0; j < 8; j++, idx++) {
157             data[idx] = vga_read_byte(&s->vga, srcoff + i * 16 + j);
158             data[512 + idx] = vga_read_byte(&s->vga, srcoff + i * 16 + j + 8);
159         }
160     }
161     if (!s->cursor) {
162         s->cursor = cursor_alloc(64, 64);
163     }
164     cursor_set_mono(s->cursor, s->regs.cur_color1, s->regs.cur_color0,
165                     &data[512], 1, &data[0]);
166     dpy_cursor_define(s->vga.con, s->cursor);
167 }
168 
169 /* Alternatively support guest rendered hardware cursor */
ati_cursor_invalidate(VGACommonState * vga)170 static void ati_cursor_invalidate(VGACommonState *vga)
171 {
172     ATIVGAState *s = container_of(vga, ATIVGAState, vga);
173     int size = (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) ? 64 : 0;
174 
175     if (s->regs.cur_offset & BIT(31)) {
176         return; /* Do not update cursor if locked */
177     }
178     if (s->cursor_size != size ||
179         vga->hw_cursor_x != s->regs.cur_hv_pos >> 16 ||
180         vga->hw_cursor_y != (s->regs.cur_hv_pos & 0xffff) ||
181         s->cursor_offset != s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
182         (s->regs.cur_hv_offs & 0xffff) * 16) {
183         /* Remove old cursor then update and show new one if needed */
184         vga_invalidate_scanlines(vga, vga->hw_cursor_y, vga->hw_cursor_y + 63);
185         vga->hw_cursor_x = s->regs.cur_hv_pos >> 16;
186         vga->hw_cursor_y = s->regs.cur_hv_pos & 0xffff;
187         s->cursor_offset = s->regs.cur_offset - (s->regs.cur_hv_offs >> 16) -
188                            (s->regs.cur_hv_offs & 0xffff) * 16;
189         s->cursor_size = size;
190         if (size) {
191             vga_invalidate_scanlines(vga,
192                                      vga->hw_cursor_y, vga->hw_cursor_y + 63);
193         }
194     }
195 }
196 
ati_cursor_draw_line(VGACommonState * vga,uint8_t * d,int scr_y)197 static void ati_cursor_draw_line(VGACommonState *vga, uint8_t *d, int scr_y)
198 {
199     ATIVGAState *s = container_of(vga, ATIVGAState, vga);
200     uint32_t srcoff;
201     uint32_t *dp = (uint32_t *)d;
202     int i, j, h;
203 
204     if (!(s->regs.crtc_gen_cntl & CRTC2_CUR_EN) ||
205         scr_y < vga->hw_cursor_y || scr_y >= vga->hw_cursor_y + 64 ||
206         scr_y > s->regs.crtc_v_total_disp >> 16) {
207         return;
208     }
209     /* FIXME handle cur_hv_offs correctly */
210     srcoff = s->cursor_offset + (scr_y - vga->hw_cursor_y) * 16;
211     dp = &dp[vga->hw_cursor_x];
212     h = ((s->regs.crtc_h_total_disp >> 16) + 1) * 8;
213     for (i = 0; i < 8; i++) {
214         uint32_t color;
215         uint8_t abits = vga_read_byte(vga, srcoff + i);
216         uint8_t xbits = vga_read_byte(vga, srcoff + i + 8);
217         for (j = 0; j < 8; j++, abits <<= 1, xbits <<= 1) {
218             if (abits & BIT(7)) {
219                 if (xbits & BIT(7)) {
220                     color = dp[i * 8 + j] ^ 0xffffffff; /* complement */
221                 } else {
222                     continue; /* transparent, no change */
223                 }
224             } else {
225                 color = (xbits & BIT(7) ? s->regs.cur_color1 :
226                                           s->regs.cur_color0) | 0xff000000;
227             }
228             if (vga->hw_cursor_x + i * 8 + j >= h) {
229                 return; /* end of screen, don't span to next line */
230             }
231             dp[i * 8 + j] = color;
232         }
233     }
234 }
235 
ati_i2c(bitbang_i2c_interface * i2c,uint64_t data,int base)236 static uint64_t ati_i2c(bitbang_i2c_interface *i2c, uint64_t data, int base)
237 {
238     bool c = (data & BIT(base + 17) ? !!(data & BIT(base + 1)) : 1);
239     bool d = (data & BIT(base + 16) ? !!(data & BIT(base)) : 1);
240 
241     bitbang_i2c_set(i2c, BITBANG_I2C_SCL, c);
242     d = bitbang_i2c_set(i2c, BITBANG_I2C_SDA, d);
243 
244     data &= ~0xf00ULL;
245     if (c) {
246         data |= BIT(base + 9);
247     }
248     if (d) {
249         data |= BIT(base + 8);
250     }
251     return data;
252 }
253 
ati_vga_update_irq(ATIVGAState * s)254 static void ati_vga_update_irq(ATIVGAState *s)
255 {
256     pci_set_irq(&s->dev, !!(s->regs.gen_int_status & s->regs.gen_int_cntl));
257 }
258 
ati_vga_vblank_irq(void * opaque)259 static void ati_vga_vblank_irq(void *opaque)
260 {
261     ATIVGAState *s = opaque;
262 
263     timer_mod(&s->vblank_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
264               NANOSECONDS_PER_SECOND / 60);
265     s->regs.gen_int_status |= CRTC_VBLANK_INT;
266     ati_vga_update_irq(s);
267 }
268 
ati_reg_read_offs(uint32_t reg,int offs,unsigned int size)269 static inline uint64_t ati_reg_read_offs(uint32_t reg, int offs,
270                                          unsigned int size)
271 {
272     if (offs == 0 && size == 4) {
273         return reg;
274     } else {
275         return extract32(reg, offs * BITS_PER_BYTE, size * BITS_PER_BYTE);
276     }
277 }
278 
ati_mm_read(void * opaque,hwaddr addr,unsigned int size)279 static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
280 {
281     ATIVGAState *s = opaque;
282     uint64_t val = 0;
283 
284     switch (addr) {
285     case MM_INDEX:
286         val = s->regs.mm_index;
287         break;
288     case MM_DATA ... MM_DATA + 3:
289         /* indexed access to regs or memory */
290         if (s->regs.mm_index & BIT(31)) {
291             uint32_t idx = s->regs.mm_index & ~BIT(31);
292             if (idx <= s->vga.vram_size - size) {
293                 val = ldn_le_p(s->vga.vram_ptr + idx, size);
294             }
295         } else if (s->regs.mm_index > MM_DATA + 3) {
296             val = ati_mm_read(s, s->regs.mm_index + addr - MM_DATA, size);
297         } else {
298             qemu_log_mask(LOG_GUEST_ERROR,
299                 "ati_mm_read: mm_index too small: %u\n", s->regs.mm_index);
300         }
301         break;
302     case BIOS_0_SCRATCH ... BUS_CNTL - 1:
303     {
304         int i = (addr - BIOS_0_SCRATCH) / 4;
305         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF && i > 3) {
306             break;
307         }
308         val = ati_reg_read_offs(s->regs.bios_scratch[i],
309                                 addr - (BIOS_0_SCRATCH + i * 4), size);
310         break;
311     }
312     case GEN_INT_CNTL:
313         val = s->regs.gen_int_cntl;
314         break;
315     case GEN_INT_STATUS:
316         val = s->regs.gen_int_status;
317         break;
318     case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
319         val = ati_reg_read_offs(s->regs.crtc_gen_cntl,
320                                 addr - CRTC_GEN_CNTL, size);
321         break;
322     case CRTC_EXT_CNTL ... CRTC_EXT_CNTL + 3:
323         val = ati_reg_read_offs(s->regs.crtc_ext_cntl,
324                                 addr - CRTC_EXT_CNTL, size);
325         break;
326     case DAC_CNTL:
327         val = s->regs.dac_cntl;
328         break;
329     case GPIO_VGA_DDC ... GPIO_VGA_DDC + 3:
330         val = ati_reg_read_offs(s->regs.gpio_vga_ddc,
331                                 addr - GPIO_VGA_DDC, size);
332         break;
333     case GPIO_DVI_DDC ... GPIO_DVI_DDC + 3:
334         val = ati_reg_read_offs(s->regs.gpio_dvi_ddc,
335                                 addr - GPIO_DVI_DDC, size);
336         break;
337     case GPIO_MONID ... GPIO_MONID + 3:
338         val = ati_reg_read_offs(s->regs.gpio_monid,
339                                 addr - GPIO_MONID, size);
340         break;
341     case PALETTE_INDEX:
342         /* FIXME unaligned access */
343         val = vga_ioport_read(&s->vga, VGA_PEL_IR) << 16;
344         val |= vga_ioport_read(&s->vga, VGA_PEL_IW) & 0xff;
345         break;
346     case PALETTE_DATA:
347         val = vga_ioport_read(&s->vga, VGA_PEL_D);
348         break;
349     case PALETTE_30_DATA:
350         val = s->regs.palette[vga_ioport_read(&s->vga, VGA_PEL_IR)];
351         break;
352     case CNFG_CNTL:
353         val = s->regs.config_cntl;
354         break;
355     case CNFG_MEMSIZE:
356         val = s->vga.vram_size;
357         break;
358     case CONFIG_APER_0_BASE:
359     case CONFIG_APER_1_BASE:
360         val = pci_default_read_config(&s->dev,
361                                       PCI_BASE_ADDRESS_0, size) & 0xfffffff0;
362         break;
363     case CONFIG_APER_SIZE:
364         val = s->vga.vram_size / 2;
365         break;
366     case CONFIG_REG_1_BASE:
367         val = pci_default_read_config(&s->dev,
368                                       PCI_BASE_ADDRESS_2, size) & 0xfffffff0;
369         break;
370     case CONFIG_REG_APER_SIZE:
371         val = memory_region_size(&s->mm) / 2;
372         break;
373     case HOST_PATH_CNTL:
374         val = BIT(23); /* Radeon HDP_APER_CNTL */
375         break;
376     case MC_STATUS:
377         val = 5;
378         break;
379     case MEM_SDRAM_MODE_REG:
380         if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
381             val = BIT(28) | BIT(20);
382         }
383         break;
384     case RBBM_STATUS:
385     case GUI_STAT:
386         val = 64; /* free CMDFIFO entries */
387         break;
388     case CRTC_H_TOTAL_DISP:
389         val = s->regs.crtc_h_total_disp;
390         break;
391     case CRTC_H_SYNC_STRT_WID:
392         val = s->regs.crtc_h_sync_strt_wid;
393         break;
394     case CRTC_V_TOTAL_DISP:
395         val = s->regs.crtc_v_total_disp;
396         break;
397     case CRTC_V_SYNC_STRT_WID:
398         val = s->regs.crtc_v_sync_strt_wid;
399         break;
400     case CRTC_OFFSET:
401         val = s->regs.crtc_offset;
402         break;
403     case CRTC_OFFSET_CNTL:
404         val = s->regs.crtc_offset_cntl;
405         break;
406     case CRTC_PITCH:
407         val = s->regs.crtc_pitch;
408         break;
409     case 0xf00 ... 0xfff:
410         val = pci_default_read_config(&s->dev, addr - 0xf00, size);
411         break;
412     case CUR_OFFSET ... CUR_OFFSET + 3:
413         val = ati_reg_read_offs(s->regs.cur_offset, addr - CUR_OFFSET, size);
414         break;
415     case CUR_HORZ_VERT_POSN ... CUR_HORZ_VERT_POSN + 3:
416         val = ati_reg_read_offs(s->regs.cur_hv_pos,
417                                 addr - CUR_HORZ_VERT_POSN, size);
418         if (addr + size > CUR_HORZ_VERT_POSN + 3) {
419             val |= (s->regs.cur_offset & BIT(31)) >> (4 - size);
420         }
421         break;
422     case CUR_HORZ_VERT_OFF ... CUR_HORZ_VERT_OFF + 3:
423         val = ati_reg_read_offs(s->regs.cur_hv_offs,
424                                 addr - CUR_HORZ_VERT_OFF, size);
425         if (addr + size > CUR_HORZ_VERT_OFF + 3) {
426             val |= (s->regs.cur_offset & BIT(31)) >> (4 - size);
427         }
428         break;
429     case CUR_CLR0 ... CUR_CLR0 + 3:
430         val = ati_reg_read_offs(s->regs.cur_color0, addr - CUR_CLR0, size);
431         break;
432     case CUR_CLR1 ... CUR_CLR1 + 3:
433         val = ati_reg_read_offs(s->regs.cur_color1, addr - CUR_CLR1, size);
434         break;
435     case DST_OFFSET:
436         val = s->regs.dst_offset;
437         break;
438     case DST_PITCH:
439         val = s->regs.dst_pitch;
440         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
441             val &= s->regs.dst_tile << 16;
442         }
443         break;
444     case DST_WIDTH:
445         val = s->regs.dst_width;
446         break;
447     case DST_HEIGHT:
448         val = s->regs.dst_height;
449         break;
450     case SRC_X:
451         val = s->regs.src_x;
452         break;
453     case SRC_Y:
454         val = s->regs.src_y;
455         break;
456     case DST_X:
457         val = s->regs.dst_x;
458         break;
459     case DST_Y:
460         val = s->regs.dst_y;
461         break;
462     case DP_GUI_MASTER_CNTL:
463         val = s->regs.dp_gui_master_cntl;
464         break;
465     case SRC_OFFSET:
466         val = s->regs.src_offset;
467         break;
468     case SRC_PITCH:
469         val = s->regs.src_pitch;
470         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
471             val &= s->regs.src_tile << 16;
472         }
473         break;
474     case DP_BRUSH_BKGD_CLR:
475         val = s->regs.dp_brush_bkgd_clr;
476         break;
477     case DP_BRUSH_FRGD_CLR:
478         val = s->regs.dp_brush_frgd_clr;
479         break;
480     case DP_SRC_FRGD_CLR:
481         val = s->regs.dp_src_frgd_clr;
482         break;
483     case DP_SRC_BKGD_CLR:
484         val = s->regs.dp_src_bkgd_clr;
485         break;
486     case DP_CNTL:
487         val = s->regs.dp_cntl;
488         break;
489     case DP_DATATYPE:
490         val = s->regs.dp_datatype;
491         break;
492     case DP_MIX:
493         val = s->regs.dp_mix;
494         break;
495     case DP_WRITE_MASK:
496         val = s->regs.dp_write_mask;
497         break;
498     case DEFAULT_OFFSET:
499         val = s->regs.default_offset;
500         if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
501             val >>= 10;
502             val |= s->regs.default_pitch << 16;
503             val |= s->regs.default_tile << 30;
504         }
505         break;
506     case DEFAULT_PITCH:
507         val = s->regs.default_pitch;
508         val |= s->regs.default_tile << 16;
509         break;
510     case DEFAULT_SC_BOTTOM_RIGHT:
511         val = s->regs.default_sc_bottom_right;
512         break;
513     default:
514         break;
515     }
516     if (addr < CUR_OFFSET || addr > CUR_CLR1 || ATI_DEBUG_HW_CURSOR) {
517         trace_ati_mm_read(size, addr, ati_reg_name(addr & ~3ULL), val);
518     }
519     return val;
520 }
521 
ati_reg_write_offs(uint32_t * reg,int offs,uint64_t data,unsigned int size)522 static inline void ati_reg_write_offs(uint32_t *reg, int offs,
523                                       uint64_t data, unsigned int size)
524 {
525     if (offs == 0 && size == 4) {
526         *reg = data;
527     } else {
528         *reg = deposit32(*reg, offs * BITS_PER_BYTE, size * BITS_PER_BYTE,
529                          data);
530     }
531 }
532 
ati_mm_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)533 static void ati_mm_write(void *opaque, hwaddr addr,
534                            uint64_t data, unsigned int size)
535 {
536     ATIVGAState *s = opaque;
537 
538     if (addr < CUR_OFFSET || addr > CUR_CLR1 || ATI_DEBUG_HW_CURSOR) {
539         trace_ati_mm_write(size, addr, ati_reg_name(addr & ~3ULL), data);
540     }
541     switch (addr) {
542     case MM_INDEX:
543         s->regs.mm_index = data & ~3;
544         break;
545     case MM_DATA ... MM_DATA + 3:
546         /* indexed access to regs or memory */
547         if (s->regs.mm_index & BIT(31)) {
548             uint32_t idx = s->regs.mm_index & ~BIT(31);
549             if (idx <= s->vga.vram_size - size) {
550                 stn_le_p(s->vga.vram_ptr + idx, size, data);
551             }
552         } else if (s->regs.mm_index > MM_DATA + 3) {
553             ati_mm_write(s, s->regs.mm_index + addr - MM_DATA, data, size);
554         } else {
555             qemu_log_mask(LOG_GUEST_ERROR,
556                 "ati_mm_write: mm_index too small: %u\n", s->regs.mm_index);
557         }
558         break;
559     case BIOS_0_SCRATCH ... BUS_CNTL - 1:
560     {
561         int i = (addr - BIOS_0_SCRATCH) / 4;
562         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF && i > 3) {
563             break;
564         }
565         ati_reg_write_offs(&s->regs.bios_scratch[i],
566                            addr - (BIOS_0_SCRATCH + i * 4), data, size);
567         break;
568     }
569     case GEN_INT_CNTL:
570         s->regs.gen_int_cntl = data;
571         if (data & CRTC_VBLANK_INT) {
572             ati_vga_vblank_irq(s);
573         } else {
574             timer_del(&s->vblank_timer);
575             ati_vga_update_irq(s);
576         }
577         break;
578     case GEN_INT_STATUS:
579         data &= (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF ?
580                  0x000f040fUL : 0xfc080effUL);
581         s->regs.gen_int_status &= ~data;
582         ati_vga_update_irq(s);
583         break;
584     case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
585     {
586         uint32_t val = s->regs.crtc_gen_cntl;
587         ati_reg_write_offs(&s->regs.crtc_gen_cntl,
588                            addr - CRTC_GEN_CNTL, data, size);
589         if ((val & CRTC2_CUR_EN) != (s->regs.crtc_gen_cntl & CRTC2_CUR_EN)) {
590             if (s->cursor_guest_mode) {
591                 s->vga.force_shadow = !!(s->regs.crtc_gen_cntl & CRTC2_CUR_EN);
592             } else {
593                 if (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) {
594                     ati_cursor_define(s);
595                 }
596                 dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
597                               s->regs.cur_hv_pos & 0xffff,
598                               (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) != 0);
599             }
600         }
601         if ((val & (CRTC2_EXT_DISP_EN | CRTC2_EN)) !=
602             (s->regs.crtc_gen_cntl & (CRTC2_EXT_DISP_EN | CRTC2_EN))) {
603             ati_vga_switch_mode(s);
604         }
605         break;
606     }
607     case CRTC_EXT_CNTL ... CRTC_EXT_CNTL + 3:
608     {
609         uint32_t val = s->regs.crtc_ext_cntl;
610         ati_reg_write_offs(&s->regs.crtc_ext_cntl,
611                            addr - CRTC_EXT_CNTL, data, size);
612         if (s->regs.crtc_ext_cntl & CRT_CRTC_DISPLAY_DIS) {
613             DPRINTF("Display disabled\n");
614             s->vga.ar_index &= ~BIT(5);
615         } else {
616             DPRINTF("Display enabled\n");
617             s->vga.ar_index |= BIT(5);
618             ati_vga_switch_mode(s);
619         }
620         if ((val & CRT_CRTC_DISPLAY_DIS) !=
621             (s->regs.crtc_ext_cntl & CRT_CRTC_DISPLAY_DIS)) {
622             ati_vga_switch_mode(s);
623         }
624         break;
625     }
626     case DAC_CNTL:
627         s->regs.dac_cntl = data & 0xffffe3ff;
628         s->vga.dac_8bit = !!(data & DAC_8BIT_EN);
629         break;
630     /*
631      * GPIO regs for DDC access. Because some drivers access these via
632      * multiple byte writes we have to be careful when we send bits to
633      * avoid spurious changes in bitbang_i2c state. Only do it when either
634      * the enable bits are changed or output bits changed while enabled.
635      */
636     case GPIO_VGA_DDC ... GPIO_VGA_DDC + 3:
637         if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
638             /* FIXME: Maybe add a property to select VGA or DVI port? */
639         }
640         break;
641     case GPIO_DVI_DDC ... GPIO_DVI_DDC + 3:
642         if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
643             ati_reg_write_offs(&s->regs.gpio_dvi_ddc,
644                                addr - GPIO_DVI_DDC, data, size);
645             if ((addr <= GPIO_DVI_DDC + 2 && addr + size > GPIO_DVI_DDC + 2) ||
646                 (addr == GPIO_DVI_DDC && (s->regs.gpio_dvi_ddc & 0x30000))) {
647                 s->regs.gpio_dvi_ddc = ati_i2c(&s->bbi2c,
648                                                s->regs.gpio_dvi_ddc, 0);
649             }
650         }
651         break;
652     case GPIO_MONID ... GPIO_MONID + 3:
653         /* FIXME What does Radeon have here? */
654         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
655             /* Rage128p accesses DDC via MONID(1-2) with additional mask bit */
656             ati_reg_write_offs(&s->regs.gpio_monid,
657                                addr - GPIO_MONID, data, size);
658             if ((s->regs.gpio_monid & BIT(25)) &&
659                 ((addr <= GPIO_MONID + 2 && addr + size > GPIO_MONID + 2) ||
660                  (addr == GPIO_MONID && (s->regs.gpio_monid & 0x60000)))) {
661                 s->regs.gpio_monid = ati_i2c(&s->bbi2c, s->regs.gpio_monid, 1);
662             }
663         }
664         break;
665     case PALETTE_INDEX ... PALETTE_INDEX + 3:
666         if (size == 4) {
667             vga_ioport_write(&s->vga, VGA_PEL_IR, (data >> 16) & 0xff);
668             vga_ioport_write(&s->vga, VGA_PEL_IW, data & 0xff);
669         } else {
670             if (addr == PALETTE_INDEX) {
671                 vga_ioport_write(&s->vga, VGA_PEL_IW, data & 0xff);
672             } else {
673                 vga_ioport_write(&s->vga, VGA_PEL_IR, data & 0xff);
674             }
675         }
676         break;
677     case PALETTE_DATA ... PALETTE_DATA + 3:
678         data <<= addr - PALETTE_DATA;
679         data = bswap32(data) >> 8;
680         vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
681         data >>= 8;
682         vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
683         data >>= 8;
684         vga_ioport_write(&s->vga, VGA_PEL_D, data & 0xff);
685         break;
686     case PALETTE_30_DATA:
687         s->regs.palette[vga_ioport_read(&s->vga, VGA_PEL_IW)] = data;
688         vga_ioport_write(&s->vga, VGA_PEL_D, (data >> 22) & 0xff);
689         vga_ioport_write(&s->vga, VGA_PEL_D, (data >> 12) & 0xff);
690         vga_ioport_write(&s->vga, VGA_PEL_D, (data >> 2) & 0xff);
691         break;
692     case CNFG_CNTL:
693         s->regs.config_cntl = data;
694         break;
695     case CRTC_H_TOTAL_DISP:
696         s->regs.crtc_h_total_disp = data & 0x07ff07ff;
697         break;
698     case CRTC_H_SYNC_STRT_WID:
699         s->regs.crtc_h_sync_strt_wid = data & 0x17bf1fff;
700         break;
701     case CRTC_V_TOTAL_DISP:
702         s->regs.crtc_v_total_disp = data & 0x0fff0fff;
703         break;
704     case CRTC_V_SYNC_STRT_WID:
705         s->regs.crtc_v_sync_strt_wid = data & 0x9f0fff;
706         break;
707     case CRTC_OFFSET:
708         s->regs.crtc_offset = data & 0xc7ffffff;
709         break;
710     case CRTC_OFFSET_CNTL:
711         s->regs.crtc_offset_cntl = data; /* FIXME */
712         break;
713     case CRTC_PITCH:
714         s->regs.crtc_pitch = data & 0x07ff07ff;
715         break;
716     case 0xf00 ... 0xfff:
717         /* read-only copy of PCI config space so ignore writes */
718         break;
719     case CUR_OFFSET ... CUR_OFFSET + 3:
720     {
721         uint32_t t = s->regs.cur_offset;
722 
723         ati_reg_write_offs(&t, addr - CUR_OFFSET, data, size);
724         t &= 0x87fffff0;
725         if (s->regs.cur_offset != t) {
726             s->regs.cur_offset = t;
727             ati_cursor_define(s);
728         }
729         break;
730     }
731     case CUR_HORZ_VERT_POSN ... CUR_HORZ_VERT_POSN + 3:
732     {
733         uint32_t t = s->regs.cur_hv_pos | (s->regs.cur_offset & BIT(31));
734 
735         ati_reg_write_offs(&t, addr - CUR_HORZ_VERT_POSN, data, size);
736         s->regs.cur_hv_pos = t & 0x3fff0fff;
737         if (t & BIT(31)) {
738             s->regs.cur_offset |= t & BIT(31);
739         } else if (s->regs.cur_offset & BIT(31)) {
740             s->regs.cur_offset &= ~BIT(31);
741             ati_cursor_define(s);
742         }
743         if (!s->cursor_guest_mode &&
744             (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(t & BIT(31))) {
745             dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
746                           s->regs.cur_hv_pos & 0xffff, true);
747         }
748         break;
749     }
750     case CUR_HORZ_VERT_OFF:
751     {
752         uint32_t t = s->regs.cur_hv_offs | (s->regs.cur_offset & BIT(31));
753 
754         ati_reg_write_offs(&t, addr - CUR_HORZ_VERT_OFF, data, size);
755         s->regs.cur_hv_offs = t & 0x3f003f;
756         if (t & BIT(31)) {
757             s->regs.cur_offset |= t & BIT(31);
758         } else if (s->regs.cur_offset & BIT(31)) {
759             s->regs.cur_offset &= ~BIT(31);
760             ati_cursor_define(s);
761         }
762         break;
763     }
764     case CUR_CLR0 ... CUR_CLR0 + 3:
765     {
766         uint32_t t = s->regs.cur_color0;
767 
768         ati_reg_write_offs(&t, addr - CUR_CLR0, data, size);
769         t &= 0xffffff;
770         if (s->regs.cur_color0 != t) {
771             s->regs.cur_color0 = t;
772             ati_cursor_define(s);
773         }
774         break;
775     }
776     case CUR_CLR1 ... CUR_CLR1 + 3:
777         /*
778          * Update cursor unconditionally here because some clients set up
779          * other registers before actually writing cursor data to memory at
780          * offset so we would miss cursor change unless always updating here
781          */
782         ati_reg_write_offs(&s->regs.cur_color1, addr - CUR_CLR1, data, size);
783         s->regs.cur_color1 &= 0xffffff;
784         ati_cursor_define(s);
785         break;
786     case DST_OFFSET:
787         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
788             s->regs.dst_offset = data & 0xfffffff0;
789         } else {
790             s->regs.dst_offset = data & 0xfffffc00;
791         }
792         break;
793     case DST_PITCH:
794         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
795             s->regs.dst_pitch = data & 0x3fff;
796             s->regs.dst_tile = (data >> 16) & 1;
797         } else {
798             s->regs.dst_pitch = data & 0x3ff0;
799         }
800         break;
801     case DST_TILE:
802         if (s->dev_id == PCI_DEVICE_ID_ATI_RADEON_QY) {
803             s->regs.dst_tile = data & 3;
804         }
805         break;
806     case DST_WIDTH:
807         s->regs.dst_width = data & 0x3fff;
808         ati_2d_blt(s);
809         break;
810     case DST_HEIGHT:
811         s->regs.dst_height = data & 0x3fff;
812         break;
813     case SRC_X:
814         s->regs.src_x = data & 0x3fff;
815         break;
816     case SRC_Y:
817         s->regs.src_y = data & 0x3fff;
818         break;
819     case DST_X:
820         s->regs.dst_x = data & 0x3fff;
821         break;
822     case DST_Y:
823         s->regs.dst_y = data & 0x3fff;
824         break;
825     case SRC_PITCH_OFFSET:
826         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
827             s->regs.src_offset = (data & 0x1fffff) << 5;
828             s->regs.src_pitch = (data & 0x7fe00000) >> 21;
829             s->regs.src_tile = data >> 31;
830         } else {
831             s->regs.src_offset = (data & 0x3fffff) << 10;
832             s->regs.src_pitch = (data & 0x3fc00000) >> 16;
833             s->regs.src_tile = (data >> 30) & 1;
834         }
835         break;
836     case DST_PITCH_OFFSET:
837         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
838             s->regs.dst_offset = (data & 0x1fffff) << 5;
839             s->regs.dst_pitch = (data & 0x7fe00000) >> 21;
840             s->regs.dst_tile = data >> 31;
841         } else {
842             s->regs.dst_offset = (data & 0x3fffff) << 10;
843             s->regs.dst_pitch = (data & 0x3fc00000) >> 16;
844             s->regs.dst_tile = data >> 30;
845         }
846         break;
847     case SRC_Y_X:
848         s->regs.src_x = data & 0x3fff;
849         s->regs.src_y = (data >> 16) & 0x3fff;
850         break;
851     case DST_Y_X:
852         s->regs.dst_x = data & 0x3fff;
853         s->regs.dst_y = (data >> 16) & 0x3fff;
854         break;
855     case DST_HEIGHT_WIDTH:
856         s->regs.dst_width = data & 0x3fff;
857         s->regs.dst_height = (data >> 16) & 0x3fff;
858         ati_2d_blt(s);
859         break;
860     case DP_GUI_MASTER_CNTL:
861         s->regs.dp_gui_master_cntl = data & 0xf800000f;
862         s->regs.dp_datatype = (data & 0x0f00) >> 8 | (data & 0x30f0) << 4 |
863                               (data & 0x4000) << 16;
864         s->regs.dp_mix = (data & GMC_ROP3_MASK) | (data & 0x7000000) >> 16;
865         break;
866     case DST_WIDTH_X:
867         s->regs.dst_x = data & 0x3fff;
868         s->regs.dst_width = (data >> 16) & 0x3fff;
869         ati_2d_blt(s);
870         break;
871     case SRC_X_Y:
872         s->regs.src_y = data & 0x3fff;
873         s->regs.src_x = (data >> 16) & 0x3fff;
874         break;
875     case DST_X_Y:
876         s->regs.dst_y = data & 0x3fff;
877         s->regs.dst_x = (data >> 16) & 0x3fff;
878         break;
879     case DST_WIDTH_HEIGHT:
880         s->regs.dst_height = data & 0x3fff;
881         s->regs.dst_width = (data >> 16) & 0x3fff;
882         ati_2d_blt(s);
883         break;
884     case DST_HEIGHT_Y:
885         s->regs.dst_y = data & 0x3fff;
886         s->regs.dst_height = (data >> 16) & 0x3fff;
887         break;
888     case SRC_OFFSET:
889         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
890             s->regs.src_offset = data & 0xfffffff0;
891         } else {
892             s->regs.src_offset = data & 0xfffffc00;
893         }
894         break;
895     case SRC_PITCH:
896         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
897             s->regs.src_pitch = data & 0x3fff;
898             s->regs.src_tile = (data >> 16) & 1;
899         } else {
900             s->regs.src_pitch = data & 0x3ff0;
901         }
902         break;
903     case DP_BRUSH_BKGD_CLR:
904         s->regs.dp_brush_bkgd_clr = data;
905         break;
906     case DP_BRUSH_FRGD_CLR:
907         s->regs.dp_brush_frgd_clr = data;
908         break;
909     case DP_CNTL:
910         s->regs.dp_cntl = data;
911         break;
912     case DP_DATATYPE:
913         s->regs.dp_datatype = data & 0xe0070f0f;
914         break;
915     case DP_MIX:
916         s->regs.dp_mix = data & 0x00ff0700;
917         break;
918     case DP_WRITE_MASK:
919         s->regs.dp_write_mask = data;
920         break;
921     case DEFAULT_OFFSET:
922         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
923             s->regs.default_offset = data & 0xfffffff0;
924         } else {
925             /* Radeon has DEFAULT_PITCH_OFFSET here like DST_PITCH_OFFSET */
926             s->regs.default_offset = (data & 0x3fffff) << 10;
927             s->regs.default_pitch = (data & 0x3fc00000) >> 16;
928             s->regs.default_tile = data >> 30;
929         }
930         break;
931     case DEFAULT_PITCH:
932         if (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF) {
933             s->regs.default_pitch = data & 0x3fff;
934             s->regs.default_tile = (data >> 16) & 1;
935         }
936         break;
937     case DEFAULT_SC_BOTTOM_RIGHT:
938         s->regs.default_sc_bottom_right = data & 0x3fff3fff;
939         break;
940     default:
941         break;
942     }
943 }
944 
945 static const MemoryRegionOps ati_mm_ops = {
946     .read = ati_mm_read,
947     .write = ati_mm_write,
948     .endianness = DEVICE_LITTLE_ENDIAN,
949 };
950 
ati_vga_realize(PCIDevice * dev,Error ** errp)951 static void ati_vga_realize(PCIDevice *dev, Error **errp)
952 {
953     ATIVGAState *s = ATI_VGA(dev);
954     VGACommonState *vga = &s->vga;
955 
956 #ifndef CONFIG_PIXMAN
957     if (s->use_pixman != 0) {
958         warn_report("x-pixman != 0, not effective without PIXMAN");
959     }
960 #endif
961 
962     if (s->model) {
963         int i;
964         for (i = 0; i < ARRAY_SIZE(ati_model_aliases); i++) {
965             if (!strcmp(s->model, ati_model_aliases[i].name)) {
966                 s->dev_id = ati_model_aliases[i].dev_id;
967                 break;
968             }
969         }
970         if (i >= ARRAY_SIZE(ati_model_aliases)) {
971             warn_report("Unknown ATI VGA model name, "
972                         "using default rage128p");
973         }
974     }
975     if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF &&
976         s->dev_id != PCI_DEVICE_ID_ATI_RADEON_QY) {
977         error_setg(errp, "Unknown ATI VGA device id, "
978                    "only 0x5046 and 0x5159 are supported");
979         return;
980     }
981     pci_set_word(dev->config + PCI_DEVICE_ID, s->dev_id);
982 
983     if (s->dev_id == PCI_DEVICE_ID_ATI_RADEON_QY &&
984         s->vga.vram_size_mb < 16) {
985         warn_report("Too small video memory for device id");
986         s->vga.vram_size_mb = 16;
987     }
988 
989     /* init vga bits */
990     if (!vga_common_init(vga, OBJECT(s), errp)) {
991         return;
992     }
993     vga_init(vga, OBJECT(s), pci_address_space(dev),
994              pci_address_space_io(dev), true);
995     vga->con = graphic_console_init(DEVICE(s), 0, s->vga.hw_ops, vga);
996     if (s->cursor_guest_mode) {
997         vga->cursor_invalidate = ati_cursor_invalidate;
998         vga->cursor_draw_line = ati_cursor_draw_line;
999     }
1000 
1001     /* ddc, edid */
1002     I2CBus *i2cbus = i2c_init_bus(DEVICE(s), "ati-vga.ddc");
1003     bitbang_i2c_init(&s->bbi2c, i2cbus);
1004     I2CSlave *i2cddc = I2C_SLAVE(qdev_new(TYPE_I2CDDC));
1005     i2c_slave_set_address(i2cddc, 0x50);
1006     qdev_realize_and_unref(DEVICE(i2cddc), BUS(i2cbus), &error_abort);
1007 
1008     /* mmio register space */
1009     memory_region_init_io(&s->mm, OBJECT(s), &ati_mm_ops, s,
1010                           "ati.mmregs", 0x4000);
1011     /* io space is alias to beginning of mmregs */
1012     memory_region_init_alias(&s->io, OBJECT(s), "ati.io", &s->mm, 0, 0x100);
1013 
1014     pci_register_bar(dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
1015     pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
1016     pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mm);
1017 
1018     /* most interrupts are not yet emulated but MacOS needs at least VBlank */
1019     dev->config[PCI_INTERRUPT_PIN] = 1;
1020     timer_init_ns(&s->vblank_timer, QEMU_CLOCK_VIRTUAL, ati_vga_vblank_irq, s);
1021 }
1022 
ati_vga_reset(DeviceState * dev)1023 static void ati_vga_reset(DeviceState *dev)
1024 {
1025     ATIVGAState *s = ATI_VGA(dev);
1026 
1027     timer_del(&s->vblank_timer);
1028     ati_vga_update_irq(s);
1029 
1030     /* reset vga */
1031     vga_common_reset(&s->vga);
1032     s->mode = VGA_MODE;
1033 }
1034 
ati_vga_exit(PCIDevice * dev)1035 static void ati_vga_exit(PCIDevice *dev)
1036 {
1037     ATIVGAState *s = ATI_VGA(dev);
1038 
1039     timer_del(&s->vblank_timer);
1040     graphic_console_close(s->vga.con);
1041 }
1042 
1043 static const Property ati_vga_properties[] = {
1044     DEFINE_PROP_UINT32("vgamem_mb", ATIVGAState, vga.vram_size_mb, 16),
1045     DEFINE_PROP_STRING("model", ATIVGAState, model),
1046     DEFINE_PROP_UINT16("x-device-id", ATIVGAState, dev_id,
1047                        PCI_DEVICE_ID_ATI_RAGE128_PF),
1048     DEFINE_PROP_BOOL("guest_hwcursor", ATIVGAState, cursor_guest_mode, false),
1049     /* this is a debug option, prefer PROP_UINT over PROP_BIT for simplicity */
1050     DEFINE_PROP_UINT8("x-pixman", ATIVGAState, use_pixman, DEFAULT_X_PIXMAN),
1051 };
1052 
ati_vga_class_init(ObjectClass * klass,const void * data)1053 static void ati_vga_class_init(ObjectClass *klass, const void *data)
1054 {
1055     DeviceClass *dc = DEVICE_CLASS(klass);
1056     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1057 
1058     device_class_set_legacy_reset(dc, ati_vga_reset);
1059     device_class_set_props(dc, ati_vga_properties);
1060     dc->hotpluggable = false;
1061     set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
1062 
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;
1069 }
1070 
ati_vga_init(Object * o)1071 static void ati_vga_init(Object *o)
1072 {
1073     object_property_set_description(o, "x-pixman", "Use pixman for: "
1074                                     "1: fill, 2: blit");
1075 }
1076 
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 = (const InterfaceInfo[]) {
1084           { INTERFACE_CONVENTIONAL_PCI_DEVICE },
1085           { },
1086     },
1087 };
1088 
ati_vga_register_types(void)1089 static void ati_vga_register_types(void)
1090 {
1091     type_register_static(&ati_vga_info);
1092 }
1093 
1094 type_init(ati_vga_register_types)
1095