The MacOS driver exits if the card does not have an interrupt. If we
set PCI_INTERRUPT_PIN to 1 then it enables VBlank interrupts and it
boots but the mouse pointer cannot be moved. This patch implements a
dummy VBlank interrupt triggered by a 60 Hz timer. With this the
pointer now moves but MacOS still hangs somewhere before completely
finishing boot.
Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
Message-Id: <
89364275f2fb5f85ee73c0e76528aa91691a499a.
1565907489.git.balaton@eik.bme.hu>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+static void ati_vga_update_irq(ATIVGAState *s)
+{
+ pci_set_irq(&s->dev, !!(s->regs.gen_int_status & s->regs.gen_int_cntl));
+}
+
+static void ati_vga_vblank_irq(void *opaque)
+{
+ ATIVGAState *s = opaque;
+
+ timer_mod(&s->vblank_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ NANOSECONDS_PER_SECOND / 60);
+ s->regs.gen_int_status |= CRTC_VBLANK_INT;
+ ati_vga_update_irq(s);
+}
+
static inline uint64_t ati_reg_read_offs(uint32_t reg, int offs,
unsigned int size)
{
static inline uint64_t ati_reg_read_offs(uint32_t reg, int offs,
unsigned int size)
{
addr - (BIOS_0_SCRATCH + i * 4), size);
break;
}
addr - (BIOS_0_SCRATCH + i * 4), size);
break;
}
+ case GEN_INT_CNTL:
+ val = s->regs.gen_int_cntl;
+ break;
+ case GEN_INT_STATUS:
+ val = s->regs.gen_int_status;
+ break;
case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
val = ati_reg_read_offs(s->regs.crtc_gen_cntl,
addr - CRTC_GEN_CNTL, size);
case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
val = ati_reg_read_offs(s->regs.crtc_gen_cntl,
addr - CRTC_GEN_CNTL, size);
addr - (BIOS_0_SCRATCH + i * 4), data, size);
break;
}
addr - (BIOS_0_SCRATCH + i * 4), data, size);
break;
}
+ case GEN_INT_CNTL:
+ s->regs.gen_int_cntl = data;
+ if (data & CRTC_VBLANK_INT) {
+ ati_vga_vblank_irq(s);
+ } else {
+ timer_del(&s->vblank_timer);
+ ati_vga_update_irq(s);
+ }
+ break;
+ case GEN_INT_STATUS:
+ data &= (s->dev_id == PCI_DEVICE_ID_ATI_RAGE128_PF ?
+ 0x000f040fUL : 0xfc080effUL);
+ s->regs.gen_int_status &= ~data;
+ ati_vga_update_irq(s);
+ break;
case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
{
uint32_t val = s->regs.crtc_gen_cntl;
case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
{
uint32_t val = s->regs.crtc_gen_cntl;
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mm);
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mm);
+
+ /* most interrupts are not yet emulated but MacOS needs at least VBlank */
+ dev->config[PCI_INTERRUPT_PIN] = 1;
+ timer_init_ns(&s->vblank_timer, QEMU_CLOCK_VIRTUAL, ati_vga_vblank_irq, s);
}
static void ati_vga_reset(DeviceState *dev)
{
ATIVGAState *s = ATI_VGA(dev);
}
static void ati_vga_reset(DeviceState *dev)
{
ATIVGAState *s = ATI_VGA(dev);
+ timer_del(&s->vblank_timer);
+ ati_vga_update_irq(s);
+
/* reset vga */
vga_common_reset(&s->vga);
s->mode = VGA_MODE;
/* reset vga */
vga_common_reset(&s->vga);
s->mode = VGA_MODE;
{
ATIVGAState *s = ATI_VGA(dev);
{
ATIVGAState *s = ATI_VGA(dev);
+ timer_del(&s->vblank_timer);
graphic_console_close(s->vga.con);
}
graphic_console_close(s->vga.con);
}
{"BUS_CNTL", 0x0030},
{"BUS_CNTL1", 0x0034},
{"GEN_INT_CNTL", 0x0040},
{"BUS_CNTL", 0x0030},
{"BUS_CNTL1", 0x0034},
{"GEN_INT_CNTL", 0x0040},
+ {"GEN_INT_STATUS", 0x0044},
{"CRTC_GEN_CNTL", 0x0050},
{"CRTC_EXT_CNTL", 0x0054},
{"DAC_CNTL", 0x0058},
{"CRTC_GEN_CNTL", 0x0050},
{"CRTC_EXT_CNTL", 0x0054},
{"DAC_CNTL", 0x0058},
#ifndef ATI_INT_H
#define ATI_INT_H
#ifndef ATI_INT_H
#define ATI_INT_H
#include "hw/pci/pci.h"
#include "hw/i2c/bitbang_i2c.h"
#include "vga_int.h"
#include "hw/pci/pci.h"
#include "hw/i2c/bitbang_i2c.h"
#include "vga_int.h"
typedef struct ATIVGARegs {
uint32_t mm_index;
uint32_t bios_scratch[8];
typedef struct ATIVGARegs {
uint32_t mm_index;
uint32_t bios_scratch[8];
+ uint32_t gen_int_cntl;
+ uint32_t gen_int_status;
uint32_t crtc_gen_cntl;
uint32_t crtc_ext_cntl;
uint32_t dac_cntl;
uint32_t crtc_gen_cntl;
uint32_t crtc_ext_cntl;
uint32_t dac_cntl;
uint16_t cursor_size;
uint32_t cursor_offset;
QEMUCursor *cursor;
uint16_t cursor_size;
uint32_t cursor_offset;
QEMUCursor *cursor;
+ QEMUTimer vblank_timer;
bitbang_i2c_interface bbi2c;
MemoryRegion io;
MemoryRegion mm;
bitbang_i2c_interface bbi2c;
MemoryRegion io;
MemoryRegion mm;
#define BUS_CNTL 0x0030
#define BUS_CNTL1 0x0034
#define GEN_INT_CNTL 0x0040
#define BUS_CNTL 0x0030
#define BUS_CNTL1 0x0034
#define GEN_INT_CNTL 0x0040
+#define GEN_INT_STATUS 0x0044
#define CRTC_GEN_CNTL 0x0050
#define CRTC_EXT_CNTL 0x0054
#define DAC_CNTL 0x0058
#define CRTC_GEN_CNTL 0x0050
#define CRTC_EXT_CNTL 0x0054
#define DAC_CNTL 0x0058
#define XPLL_FB_DIV_MASK 0x0000FF00
#define X_MPLL_REF_DIV_MASK 0x000000FF
#define XPLL_FB_DIV_MASK 0x0000FF00
#define X_MPLL_REF_DIV_MASK 0x000000FF
+/* GEN_INT_CNTL) */
+#define CRTC_VBLANK_INT 0x00000001
+#define CRTC_VLINE_INT 0x00000002
+#define CRTC_VSYNC_INT 0x00000004
+
/* Config control values (CONFIG_CNTL) */
#define APER_0_ENDIAN 0x00000003
#define APER_1_ENDIAN 0x0000000c
/* Config control values (CONFIG_CNTL) */
#define APER_0_ENDIAN 0x00000003
#define APER_1_ENDIAN 0x0000000c