2 * QEMU Motorola 680x0 Macintosh Video Card Emulation
3 * Copyright (c) 2012-2018 Laurent Vivier
5 * some parts from QEMU G364 framebuffer Emulator.
6 * Copyright (c) 2007-2011 Herve Poussineau
8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
9 * See the COPYING file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "qemu/units.h"
15 #include "hw/sysbus.h"
16 #include "ui/console.h"
17 #include "ui/pixel_ops.h"
18 #include "hw/nubus/nubus.h"
19 #include "hw/display/macfb.h"
20 #include "qapi/error.h"
21 #include "hw/qdev-properties.h"
22 #include "migration/vmstate.h"
25 #define VIDEO_BASE 0x0
26 #define DAFB_BASE 0x00800000
28 #define MACFB_PAGE_SIZE 4096
29 #define MACFB_VRAM_SIZE (4 * MiB)
31 #define DAFB_MODE_VADDR1 0x0
32 #define DAFB_MODE_VADDR2 0x4
33 #define DAFB_MODE_CTRL1 0x8
34 #define DAFB_MODE_CTRL2 0xc
35 #define DAFB_MODE_SENSE 0x1c
36 #define DAFB_INTR_MASK 0x104
37 #define DAFB_INTR_STAT 0x108
38 #define DAFB_INTR_CLEAR 0x10c
39 #define DAFB_LUT_INDEX 0x200
40 #define DAFB_LUT 0x210
42 #define DAFB_INTR_VBL 0x4
44 /* Vertical Blank period (60.15Hz) */
45 #define DAFB_INTR_VBL_PERIOD_NS 16625800
48 * Quadra sense codes taken from Apple Technical Note HW26:
49 * "Macintosh Quadra Built-In Video". The sense codes and
50 * extended sense codes have different meanings:
53 * bit 2: SENSE2 (pin 10)
54 * bit 1: SENSE1 (pin 7)
55 * bit 0: SENSE0 (pin 4)
57 * 0 = pin tied to ground
65 * 0 = pins tied together
66 * 1 = pins unconnected
68 * Reads from the sense register appear to be active low, i.e. a 1 indicates
69 * that the pin is tied to ground, a 0 indicates the pin is disconnected.
71 * Writes to the sense register appear to activate pulldowns i.e. a 1 enables
72 * a pulldown on a particular pin.
74 * The MacOS toolbox appears to use a series of reads and writes to first
75 * determine if extended sense is to be used, and then check which pins are
76 * tied together in order to determine the display type.
79 typedef struct MacFbSense
{
85 static MacFbSense macfb_sense_table
[] = {
86 { MACFB_DISPLAY_APPLE_21_COLOR
, 0x0, 0 },
87 { MACFB_DISPLAY_APPLE_PORTRAIT
, 0x1, 0 },
88 { MACFB_DISPLAY_APPLE_12_RGB
, 0x2, 0 },
89 { MACFB_DISPLAY_APPLE_2PAGE_MONO
, 0x3, 0 },
90 { MACFB_DISPLAY_NTSC_UNDERSCAN
, 0x4, 0 },
91 { MACFB_DISPLAY_NTSC_OVERSCAN
, 0x4, 0 },
92 { MACFB_DISPLAY_APPLE_12_MONO
, 0x6, 0 },
93 { MACFB_DISPLAY_APPLE_13_RGB
, 0x6, 0 },
94 { MACFB_DISPLAY_16_COLOR
, 0x7, 0x3 },
95 { MACFB_DISPLAY_PAL1_UNDERSCAN
, 0x7, 0x0 },
96 { MACFB_DISPLAY_PAL1_OVERSCAN
, 0x7, 0x0 },
97 { MACFB_DISPLAY_PAL2_UNDERSCAN
, 0x7, 0x6 },
98 { MACFB_DISPLAY_PAL2_OVERSCAN
, 0x7, 0x6 },
99 { MACFB_DISPLAY_VGA
, 0x7, 0x5 },
100 { MACFB_DISPLAY_SVGA
, 0x7, 0x5 },
103 static MacFbMode macfb_mode_table
[] = {
104 { MACFB_DISPLAY_VGA
, 1, 0x100, 0x71e, 640, 480, 0x400, 0x1000 },
105 { MACFB_DISPLAY_VGA
, 2, 0x100, 0x70e, 640, 480, 0x400, 0x1000 },
106 { MACFB_DISPLAY_VGA
, 4, 0x100, 0x706, 640, 480, 0x400, 0x1000 },
107 { MACFB_DISPLAY_VGA
, 8, 0x100, 0x702, 640, 480, 0x400, 0x1000 },
108 { MACFB_DISPLAY_VGA
, 24, 0x100, 0x7ff, 640, 480, 0x1000, 0x1000 },
109 { MACFB_DISPLAY_VGA
, 1, 0xd0 , 0x70e, 800, 600, 0x340, 0xe00 },
110 { MACFB_DISPLAY_VGA
, 2, 0xd0 , 0x706, 800, 600, 0x340, 0xe00 },
111 { MACFB_DISPLAY_VGA
, 4, 0xd0 , 0x702, 800, 600, 0x340, 0xe00 },
112 { MACFB_DISPLAY_VGA
, 8, 0xd0, 0x700, 800, 600, 0x340, 0xe00 },
113 { MACFB_DISPLAY_VGA
, 24, 0x340, 0x100, 800, 600, 0xd00, 0xe00 },
114 { MACFB_DISPLAY_APPLE_21_COLOR
, 1, 0x90, 0x506, 1152, 870, 0x240, 0x80 },
115 { MACFB_DISPLAY_APPLE_21_COLOR
, 2, 0x90, 0x502, 1152, 870, 0x240, 0x80 },
116 { MACFB_DISPLAY_APPLE_21_COLOR
, 4, 0x90, 0x500, 1152, 870, 0x240, 0x80 },
117 { MACFB_DISPLAY_APPLE_21_COLOR
, 8, 0x120, 0x5ff, 1152, 870, 0x480, 0x80 },
120 typedef void macfb_draw_line_func(MacfbState
*s
, uint8_t *d
, uint32_t addr
,
123 static inline uint8_t macfb_read_byte(MacfbState
*s
, uint32_t addr
)
125 return s
->vram
[addr
& s
->vram_bit_mask
];
129 static void macfb_draw_line1(MacfbState
*s
, uint8_t *d
, uint32_t addr
,
135 for (x
= 0; x
< width
; x
++) {
137 int idx
= (macfb_read_byte(s
, addr
) >> (7 - bit
)) & 1;
138 r
= s
->color_palette
[idx
* 3];
139 g
= s
->color_palette
[idx
* 3 + 1];
140 b
= s
->color_palette
[idx
* 3 + 2];
143 *(uint32_t *)d
= rgb_to_pixel32(r
, g
, b
);
149 static void macfb_draw_line2(MacfbState
*s
, uint8_t *d
, uint32_t addr
,
155 for (x
= 0; x
< width
; x
++) {
157 int idx
= (macfb_read_byte(s
, addr
) >> ((3 - bit
) << 1)) & 3;
158 r
= s
->color_palette
[idx
* 3];
159 g
= s
->color_palette
[idx
* 3 + 1];
160 b
= s
->color_palette
[idx
* 3 + 2];
163 *(uint32_t *)d
= rgb_to_pixel32(r
, g
, b
);
169 static void macfb_draw_line4(MacfbState
*s
, uint8_t *d
, uint32_t addr
,
175 for (x
= 0; x
< width
; x
++) {
177 int idx
= (macfb_read_byte(s
, addr
) >> ((1 - bit
) << 2)) & 15;
178 r
= s
->color_palette
[idx
* 3];
179 g
= s
->color_palette
[idx
* 3 + 1];
180 b
= s
->color_palette
[idx
* 3 + 2];
183 *(uint32_t *)d
= rgb_to_pixel32(r
, g
, b
);
189 static void macfb_draw_line8(MacfbState
*s
, uint8_t *d
, uint32_t addr
,
195 for (x
= 0; x
< width
; x
++) {
196 r
= s
->color_palette
[macfb_read_byte(s
, addr
) * 3];
197 g
= s
->color_palette
[macfb_read_byte(s
, addr
) * 3 + 1];
198 b
= s
->color_palette
[macfb_read_byte(s
, addr
) * 3 + 2];
201 *(uint32_t *)d
= rgb_to_pixel32(r
, g
, b
);
207 static void macfb_draw_line16(MacfbState
*s
, uint8_t *d
, uint32_t addr
,
213 for (x
= 0; x
< width
; x
++) {
215 pixel
= (macfb_read_byte(s
, addr
) << 8) | macfb_read_byte(s
, addr
+ 1);
216 r
= ((pixel
>> 10) & 0x1f) << 3;
217 g
= ((pixel
>> 5) & 0x1f) << 3;
218 b
= (pixel
& 0x1f) << 3;
221 *(uint32_t *)d
= rgb_to_pixel32(r
, g
, b
);
227 static void macfb_draw_line24(MacfbState
*s
, uint8_t *d
, uint32_t addr
,
233 for (x
= 0; x
< width
; x
++) {
234 r
= macfb_read_byte(s
, addr
+ 1);
235 g
= macfb_read_byte(s
, addr
+ 2);
236 b
= macfb_read_byte(s
, addr
+ 3);
239 *(uint32_t *)d
= rgb_to_pixel32(r
, g
, b
);
255 static macfb_draw_line_func
* const
256 macfb_draw_line_table
[MACFB_DRAW_LINE_NB
] = {
265 static int macfb_check_dirty(MacfbState
*s
, DirtyBitmapSnapshot
*snap
,
266 ram_addr_t addr
, int len
)
268 return memory_region_snapshot_get_dirty(&s
->mem_vram
, snap
, addr
, len
);
271 static void macfb_draw_graphic(MacfbState
*s
)
273 DisplaySurface
*surface
= qemu_console_surface(s
->con
);
274 DirtyBitmapSnapshot
*snap
= NULL
;
278 int macfb_stride
= s
->mode
->stride
;
279 macfb_draw_line_func
*macfb_draw_line
;
283 v
= MACFB_DRAW_LINE1
;
286 v
= MACFB_DRAW_LINE2
;
289 v
= MACFB_DRAW_LINE4
;
292 v
= MACFB_DRAW_LINE8
;
295 v
= MACFB_DRAW_LINE16
;
298 v
= MACFB_DRAW_LINE24
;
302 macfb_draw_line
= macfb_draw_line_table
[v
];
303 assert(macfb_draw_line
!= NULL
);
305 snap
= memory_region_snapshot_and_clear_dirty(&s
->mem_vram
, 0x0,
306 memory_region_size(&s
->mem_vram
),
310 page
= s
->mode
->offset
;
311 for (y
= 0; y
< s
->height
; y
++, page
+= macfb_stride
) {
312 if (macfb_check_dirty(s
, snap
, page
, macfb_stride
)) {
313 uint8_t *data_display
;
315 data_display
= surface_data(surface
) + y
* surface_stride(surface
);
316 macfb_draw_line(s
, data_display
, page
, s
->width
);
323 dpy_gfx_update(s
->con
, 0, ymin
, s
->width
, y
- ymin
);
330 dpy_gfx_update(s
->con
, 0, ymin
, s
->width
, y
- ymin
);
336 static void macfb_invalidate_display(void *opaque
)
338 MacfbState
*s
= opaque
;
340 memory_region_set_dirty(&s
->mem_vram
, 0, MACFB_VRAM_SIZE
);
343 static uint32_t macfb_sense_read(MacfbState
*s
)
345 MacFbSense
*macfb_sense
;
348 assert(s
->type
< ARRAY_SIZE(macfb_sense_table
));
349 macfb_sense
= &macfb_sense_table
[s
->type
];
350 if (macfb_sense
->sense
== 0x7) {
353 if (!(macfb_sense
->ext_sense
& 1)) {
354 /* Pins 7-4 together */
355 if (~s
->regs
[DAFB_MODE_SENSE
>> 2] & 3) {
356 sense
= (~s
->regs
[DAFB_MODE_SENSE
>> 2] & 7) | 3;
359 if (!(macfb_sense
->ext_sense
& 2)) {
360 /* Pins 10-7 together */
361 if (~s
->regs
[DAFB_MODE_SENSE
>> 2] & 6) {
362 sense
= (~s
->regs
[DAFB_MODE_SENSE
>> 2] & 7) | 6;
365 if (!(macfb_sense
->ext_sense
& 4)) {
366 /* Pins 4-10 together */
367 if (~s
->regs
[DAFB_MODE_SENSE
>> 2] & 5) {
368 sense
= (~s
->regs
[DAFB_MODE_SENSE
>> 2] & 7) | 5;
373 sense
= (~macfb_sense
->sense
& 7) |
374 (~s
->regs
[DAFB_MODE_SENSE
>> 2] & 7);
377 trace_macfb_sense_read(sense
);
381 static void macfb_sense_write(MacfbState
*s
, uint32_t val
)
383 s
->regs
[DAFB_MODE_SENSE
>> 2] = val
;
385 trace_macfb_sense_write(val
);
389 static void macfb_update_mode(MacfbState
*s
)
391 s
->width
= s
->mode
->width
;
392 s
->height
= s
->mode
->height
;
393 s
->depth
= s
->mode
->depth
;
395 trace_macfb_update_mode(s
->width
, s
->height
, s
->depth
);
396 macfb_invalidate_display(s
);
399 static void macfb_mode_write(MacfbState
*s
)
401 MacFbMode
*macfb_mode
;
404 for (i
= 0; i
< ARRAY_SIZE(macfb_mode_table
); i
++) {
405 macfb_mode
= &macfb_mode_table
[i
];
407 if (s
->type
!= macfb_mode
->type
) {
411 if ((s
->regs
[DAFB_MODE_CTRL1
>> 2] & 0xff) ==
412 (macfb_mode
->mode_ctrl1
& 0xff) &&
413 (s
->regs
[DAFB_MODE_CTRL2
>> 2] & 0xff) ==
414 (macfb_mode
->mode_ctrl2
& 0xff)) {
415 s
->mode
= macfb_mode
;
416 macfb_update_mode(s
);
422 static MacFbMode
*macfb_find_mode(MacfbDisplayType display_type
,
423 uint16_t width
, uint16_t height
,
426 MacFbMode
*macfb_mode
;
429 for (i
= 0; i
< ARRAY_SIZE(macfb_mode_table
); i
++) {
430 macfb_mode
= &macfb_mode_table
[i
];
432 if (display_type
== macfb_mode
->type
&& width
== macfb_mode
->width
&&
433 height
== macfb_mode
->height
&& depth
== macfb_mode
->depth
) {
441 static gchar
*macfb_mode_list(void)
443 GString
*list
= g_string_new("");
444 MacFbMode
*macfb_mode
;
447 for (i
= 0; i
< ARRAY_SIZE(macfb_mode_table
); i
++) {
448 macfb_mode
= &macfb_mode_table
[i
];
450 g_string_append_printf(list
, " %dx%dx%d\n", macfb_mode
->width
,
451 macfb_mode
->height
, macfb_mode
->depth
);
454 return g_string_free(list
, FALSE
);
458 static void macfb_update_display(void *opaque
)
460 MacfbState
*s
= opaque
;
461 DisplaySurface
*surface
= qemu_console_surface(s
->con
);
463 qemu_flush_coalesced_mmio_buffer();
465 if (s
->width
== 0 || s
->height
== 0) {
469 if (s
->width
!= surface_width(surface
) ||
470 s
->height
!= surface_height(surface
)) {
471 qemu_console_resize(s
->con
, s
->width
, s
->height
);
474 macfb_draw_graphic(s
);
477 static void macfb_update_irq(MacfbState
*s
)
479 uint32_t irq_state
= s
->regs
[DAFB_INTR_STAT
>> 2] &
480 s
->regs
[DAFB_INTR_MASK
>> 2];
483 qemu_irq_raise(s
->irq
);
485 qemu_irq_lower(s
->irq
);
489 static int64_t macfb_next_vbl(void)
491 return (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) + DAFB_INTR_VBL_PERIOD_NS
) /
492 DAFB_INTR_VBL_PERIOD_NS
* DAFB_INTR_VBL_PERIOD_NS
;
495 static void macfb_vbl_timer(void *opaque
)
497 MacfbState
*s
= opaque
;
500 s
->regs
[DAFB_INTR_STAT
>> 2] |= DAFB_INTR_VBL
;
504 next_vbl
= macfb_next_vbl();
505 timer_mod(s
->vbl_timer
, next_vbl
);
508 static void macfb_reset(MacfbState
*s
)
512 s
->palette_current
= 0;
513 for (i
= 0; i
< 256; i
++) {
514 s
->color_palette
[i
* 3] = 255 - i
;
515 s
->color_palette
[i
* 3 + 1] = 255 - i
;
516 s
->color_palette
[i
* 3 + 2] = 255 - i
;
518 memset(s
->vram
, 0, MACFB_VRAM_SIZE
);
519 macfb_invalidate_display(s
);
522 static uint64_t macfb_ctrl_read(void *opaque
,
526 MacfbState
*s
= opaque
;
530 case DAFB_MODE_VADDR1
:
531 case DAFB_MODE_VADDR2
:
532 case DAFB_MODE_CTRL1
:
533 case DAFB_MODE_CTRL2
:
535 val
= s
->regs
[addr
>> 2];
537 case DAFB_MODE_SENSE
:
538 val
= macfb_sense_read(s
);
540 case DAFB_LUT
... DAFB_LUT
+ 3:
541 val
= s
->color_palette
[s
->palette_current
];
542 s
->palette_current
= (s
->palette_current
+ 1) %
543 ARRAY_SIZE(s
->color_palette
);
546 if (addr
< MACFB_CTRL_TOPADDR
) {
547 val
= s
->regs
[addr
>> 2];
551 trace_macfb_ctrl_read(addr
, val
, size
);
555 static void macfb_ctrl_write(void *opaque
,
560 MacfbState
*s
= opaque
;
564 case DAFB_MODE_VADDR1
:
565 case DAFB_MODE_VADDR2
:
566 s
->regs
[addr
>> 2] = val
;
568 case DAFB_MODE_CTRL1
... DAFB_MODE_CTRL1
+ 3:
569 case DAFB_MODE_CTRL2
... DAFB_MODE_CTRL2
+ 3:
570 s
->regs
[addr
>> 2] = val
;
575 case DAFB_MODE_SENSE
:
576 macfb_sense_write(s
, val
);
579 s
->regs
[addr
>> 2] = val
;
580 if (val
& DAFB_INTR_VBL
) {
581 next_vbl
= macfb_next_vbl();
582 timer_mod(s
->vbl_timer
, next_vbl
);
584 timer_del(s
->vbl_timer
);
587 case DAFB_INTR_CLEAR
:
588 s
->regs
[DAFB_INTR_STAT
>> 2] &= ~DAFB_INTR_VBL
;
592 s
->palette_current
= (val
& 0xff) * 3;
594 case DAFB_LUT
... DAFB_LUT
+ 3:
595 s
->color_palette
[s
->palette_current
] = val
& 0xff;
596 s
->palette_current
= (s
->palette_current
+ 1) %
597 ARRAY_SIZE(s
->color_palette
);
598 if (s
->palette_current
% 3) {
599 macfb_invalidate_display(s
);
603 if (addr
< MACFB_CTRL_TOPADDR
) {
604 s
->regs
[addr
>> 2] = val
;
608 trace_macfb_ctrl_write(addr
, val
, size
);
611 static const MemoryRegionOps macfb_ctrl_ops
= {
612 .read
= macfb_ctrl_read
,
613 .write
= macfb_ctrl_write
,
614 .endianness
= DEVICE_BIG_ENDIAN
,
615 .impl
.min_access_size
= 1,
616 .impl
.max_access_size
= 4,
619 static int macfb_post_load(void *opaque
, int version_id
)
621 macfb_mode_write(opaque
);
625 static const VMStateDescription vmstate_macfb
= {
628 .minimum_version_id
= 1,
629 .post_load
= macfb_post_load
,
630 .fields
= (VMStateField
[]) {
631 VMSTATE_UINT8(type
, MacfbState
),
632 VMSTATE_UINT8_ARRAY(color_palette
, MacfbState
, 256 * 3),
633 VMSTATE_UINT32(palette_current
, MacfbState
),
634 VMSTATE_UINT32_ARRAY(regs
, MacfbState
, MACFB_NUM_REGS
),
635 VMSTATE_TIMER_PTR(vbl_timer
, MacfbState
),
636 VMSTATE_END_OF_LIST()
640 static const GraphicHwOps macfb_ops
= {
641 .invalidate
= macfb_invalidate_display
,
642 .gfx_update
= macfb_update_display
,
645 static bool macfb_common_realize(DeviceState
*dev
, MacfbState
*s
, Error
**errp
)
647 DisplaySurface
*surface
;
649 s
->mode
= macfb_find_mode(s
->type
, s
->width
, s
->height
, s
->depth
);
652 error_setg(errp
, "unknown display mode: width %d, height %d, depth %d",
653 s
->width
, s
->height
, s
->depth
);
654 list
= macfb_mode_list();
655 error_append_hint(errp
, "Available modes:\n%s", list
);
662 * Set mode control registers to match the mode found above so that
663 * macfb_mode_write() does the right thing if no MacOS toolbox ROM
664 * is present to initialise them
666 s
->regs
[DAFB_MODE_CTRL1
>> 2] = s
->mode
->mode_ctrl1
;
667 s
->regs
[DAFB_MODE_CTRL2
>> 2] = s
->mode
->mode_ctrl2
;
669 s
->con
= graphic_console_init(dev
, 0, &macfb_ops
, s
);
670 surface
= qemu_console_surface(s
->con
);
672 if (surface_bits_per_pixel(surface
) != 32) {
673 error_setg(errp
, "unknown host depth %d",
674 surface_bits_per_pixel(surface
));
678 memory_region_init_io(&s
->mem_ctrl
, OBJECT(dev
), &macfb_ctrl_ops
, s
,
679 "macfb-ctrl", 0x1000);
681 memory_region_init_ram(&s
->mem_vram
, OBJECT(dev
), "macfb-vram",
682 MACFB_VRAM_SIZE
, &error_abort
);
683 memory_region_set_log(&s
->mem_vram
, true, DIRTY_MEMORY_VGA
);
684 s
->vram
= memory_region_get_ram_ptr(&s
->mem_vram
);
685 s
->vram_bit_mask
= MACFB_VRAM_SIZE
- 1;
687 s
->vbl_timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, macfb_vbl_timer
, s
);
688 macfb_update_mode(s
);
692 static void macfb_sysbus_realize(DeviceState
*dev
, Error
**errp
)
694 MacfbSysBusState
*s
= MACFB(dev
);
695 MacfbState
*ms
= &s
->macfb
;
697 if (!macfb_common_realize(dev
, ms
, errp
)) {
701 sysbus_init_mmio(SYS_BUS_DEVICE(s
), &ms
->mem_ctrl
);
702 sysbus_init_mmio(SYS_BUS_DEVICE(s
), &ms
->mem_vram
);
704 qdev_init_gpio_out(dev
, &ms
->irq
, 1);
707 static void macfb_nubus_set_irq(void *opaque
, int n
, int level
)
709 MacfbNubusState
*s
= NUBUS_MACFB(opaque
);
710 NubusDevice
*nd
= NUBUS_DEVICE(s
);
712 nubus_set_irq(nd
, level
);
715 static void macfb_nubus_realize(DeviceState
*dev
, Error
**errp
)
717 NubusDevice
*nd
= NUBUS_DEVICE(dev
);
718 MacfbNubusState
*s
= NUBUS_MACFB(dev
);
719 MacfbNubusDeviceClass
*ndc
= NUBUS_MACFB_GET_CLASS(dev
);
720 MacfbState
*ms
= &s
->macfb
;
722 ndc
->parent_realize(dev
, errp
);
727 if (!macfb_common_realize(dev
, ms
, errp
)) {
731 memory_region_add_subregion(&nd
->slot_mem
, DAFB_BASE
, &ms
->mem_ctrl
);
732 memory_region_add_subregion(&nd
->slot_mem
, VIDEO_BASE
, &ms
->mem_vram
);
734 ms
->irq
= qemu_allocate_irq(macfb_nubus_set_irq
, s
, 0);
737 static void macfb_nubus_unrealize(DeviceState
*dev
)
739 MacfbNubusState
*s
= NUBUS_MACFB(dev
);
740 MacfbNubusDeviceClass
*ndc
= NUBUS_MACFB_GET_CLASS(dev
);
741 MacfbState
*ms
= &s
->macfb
;
743 ndc
->parent_unrealize(dev
);
745 qemu_free_irq(ms
->irq
);
748 static void macfb_sysbus_reset(DeviceState
*d
)
750 MacfbSysBusState
*s
= MACFB(d
);
751 macfb_reset(&s
->macfb
);
754 static void macfb_nubus_reset(DeviceState
*d
)
756 MacfbNubusState
*s
= NUBUS_MACFB(d
);
757 macfb_reset(&s
->macfb
);
760 static Property macfb_sysbus_properties
[] = {
761 DEFINE_PROP_UINT32("width", MacfbSysBusState
, macfb
.width
, 640),
762 DEFINE_PROP_UINT32("height", MacfbSysBusState
, macfb
.height
, 480),
763 DEFINE_PROP_UINT8("depth", MacfbSysBusState
, macfb
.depth
, 8),
764 DEFINE_PROP_UINT8("display", MacfbSysBusState
, macfb
.type
,
766 DEFINE_PROP_END_OF_LIST(),
769 static const VMStateDescription vmstate_macfb_sysbus
= {
770 .name
= "macfb-sysbus",
772 .minimum_version_id
= 1,
773 .fields
= (VMStateField
[]) {
774 VMSTATE_STRUCT(macfb
, MacfbSysBusState
, 1, vmstate_macfb
, MacfbState
),
775 VMSTATE_END_OF_LIST()
779 static Property macfb_nubus_properties
[] = {
780 DEFINE_PROP_UINT32("width", MacfbNubusState
, macfb
.width
, 640),
781 DEFINE_PROP_UINT32("height", MacfbNubusState
, macfb
.height
, 480),
782 DEFINE_PROP_UINT8("depth", MacfbNubusState
, macfb
.depth
, 8),
783 DEFINE_PROP_UINT8("display", MacfbNubusState
, macfb
.type
,
785 DEFINE_PROP_END_OF_LIST(),
788 static const VMStateDescription vmstate_macfb_nubus
= {
789 .name
= "macfb-nubus",
791 .minimum_version_id
= 1,
792 .fields
= (VMStateField
[]) {
793 VMSTATE_STRUCT(macfb
, MacfbNubusState
, 1, vmstate_macfb
, MacfbState
),
794 VMSTATE_END_OF_LIST()
798 static void macfb_sysbus_class_init(ObjectClass
*klass
, void *data
)
800 DeviceClass
*dc
= DEVICE_CLASS(klass
);
802 dc
->realize
= macfb_sysbus_realize
;
803 dc
->desc
= "SysBus Macintosh framebuffer";
804 dc
->reset
= macfb_sysbus_reset
;
805 dc
->vmsd
= &vmstate_macfb_sysbus
;
806 device_class_set_props(dc
, macfb_sysbus_properties
);
809 static void macfb_nubus_class_init(ObjectClass
*klass
, void *data
)
811 DeviceClass
*dc
= DEVICE_CLASS(klass
);
812 MacfbNubusDeviceClass
*ndc
= NUBUS_MACFB_CLASS(klass
);
814 device_class_set_parent_realize(dc
, macfb_nubus_realize
,
815 &ndc
->parent_realize
);
816 device_class_set_parent_unrealize(dc
, macfb_nubus_unrealize
,
817 &ndc
->parent_unrealize
);
818 dc
->desc
= "Nubus Macintosh framebuffer";
819 dc
->reset
= macfb_nubus_reset
;
820 dc
->vmsd
= &vmstate_macfb_nubus
;
821 set_bit(DEVICE_CATEGORY_DISPLAY
, dc
->categories
);
822 device_class_set_props(dc
, macfb_nubus_properties
);
825 static const TypeInfo macfb_sysbus_info
= {
827 .parent
= TYPE_SYS_BUS_DEVICE
,
828 .instance_size
= sizeof(MacfbSysBusState
),
829 .class_init
= macfb_sysbus_class_init
,
832 static const TypeInfo macfb_nubus_info
= {
833 .name
= TYPE_NUBUS_MACFB
,
834 .parent
= TYPE_NUBUS_DEVICE
,
835 .instance_size
= sizeof(MacfbNubusState
),
836 .class_init
= macfb_nubus_class_init
,
837 .class_size
= sizeof(MacfbNubusDeviceClass
),
840 static void macfb_register_types(void)
842 type_register_static(&macfb_sysbus_info
);
843 type_register_static(&macfb_nubus_info
);
846 type_init(macfb_register_types
)