mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-27 03:51:57 -06:00
ati-vga: Implement dummy VBlank IRQ
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>
This commit is contained in:
parent
8bb9a2b26d
commit
b7105d280c
4 changed files with 55 additions and 0 deletions
|
@ -243,6 +243,21 @@ static uint64_t ati_i2c(bitbang_i2c_interface *i2c, uint64_t data, int base)
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
static inline uint64_t ati_reg_read_offs(uint32_t reg, int offs,
|
||||||
unsigned int size)
|
unsigned int size)
|
||||||
{
|
{
|
||||||
|
@ -283,6 +298,12 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
|
||||||
addr - (BIOS_0_SCRATCH + i * 4), size);
|
addr - (BIOS_0_SCRATCH + i * 4), size);
|
||||||
break;
|
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:
|
case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
|
||||||
val = ati_reg_read_offs(s->regs.crtc_gen_cntl,
|
val = ati_reg_read_offs(s->regs.crtc_gen_cntl,
|
||||||
addr - CRTC_GEN_CNTL, size);
|
addr - CRTC_GEN_CNTL, size);
|
||||||
|
@ -512,6 +533,21 @@ static void ati_mm_write(void *opaque, hwaddr addr,
|
||||||
addr - (BIOS_0_SCRATCH + i * 4), data, size);
|
addr - (BIOS_0_SCRATCH + i * 4), data, size);
|
||||||
break;
|
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:
|
case CRTC_GEN_CNTL ... CRTC_GEN_CNTL + 3:
|
||||||
{
|
{
|
||||||
uint32_t val = s->regs.crtc_gen_cntl;
|
uint32_t val = s->regs.crtc_gen_cntl;
|
||||||
|
@ -902,12 +938,19 @@ static void ati_vga_realize(PCIDevice *dev, Error **errp)
|
||||||
pci_register_bar(dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &vga->vram);
|
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, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
|
||||||
pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mm);
|
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)
|
static void ati_vga_reset(DeviceState *dev)
|
||||||
{
|
{
|
||||||
ATIVGAState *s = ATI_VGA(dev);
|
ATIVGAState *s = ATI_VGA(dev);
|
||||||
|
|
||||||
|
timer_del(&s->vblank_timer);
|
||||||
|
ati_vga_update_irq(s);
|
||||||
|
|
||||||
/* reset vga */
|
/* reset vga */
|
||||||
vga_common_reset(&s->vga);
|
vga_common_reset(&s->vga);
|
||||||
s->mode = VGA_MODE;
|
s->mode = VGA_MODE;
|
||||||
|
@ -917,6 +960,7 @@ static void ati_vga_exit(PCIDevice *dev)
|
||||||
{
|
{
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ static struct ati_regdesc ati_reg_names[] = {
|
||||||
{"BUS_CNTL", 0x0030},
|
{"BUS_CNTL", 0x0030},
|
||||||
{"BUS_CNTL1", 0x0034},
|
{"BUS_CNTL1", 0x0034},
|
||||||
{"GEN_INT_CNTL", 0x0040},
|
{"GEN_INT_CNTL", 0x0040},
|
||||||
|
{"GEN_INT_STATUS", 0x0044},
|
||||||
{"CRTC_GEN_CNTL", 0x0050},
|
{"CRTC_GEN_CNTL", 0x0050},
|
||||||
{"CRTC_EXT_CNTL", 0x0054},
|
{"CRTC_EXT_CNTL", 0x0054},
|
||||||
{"DAC_CNTL", 0x0058},
|
{"DAC_CNTL", 0x0058},
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#ifndef ATI_INT_H
|
#ifndef ATI_INT_H
|
||||||
#define ATI_INT_H
|
#define ATI_INT_H
|
||||||
|
|
||||||
|
#include "qemu/timer.h"
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
#include "hw/i2c/bitbang_i2c.h"
|
#include "hw/i2c/bitbang_i2c.h"
|
||||||
#include "vga_int.h"
|
#include "vga_int.h"
|
||||||
|
@ -33,6 +34,8 @@
|
||||||
typedef struct ATIVGARegs {
|
typedef struct ATIVGARegs {
|
||||||
uint32_t mm_index;
|
uint32_t mm_index;
|
||||||
uint32_t bios_scratch[8];
|
uint32_t bios_scratch[8];
|
||||||
|
uint32_t gen_int_cntl;
|
||||||
|
uint32_t gen_int_status;
|
||||||
uint32_t crtc_gen_cntl;
|
uint32_t crtc_gen_cntl;
|
||||||
uint32_t crtc_ext_cntl;
|
uint32_t crtc_ext_cntl;
|
||||||
uint32_t dac_cntl;
|
uint32_t dac_cntl;
|
||||||
|
@ -89,6 +92,7 @@ typedef struct ATIVGAState {
|
||||||
uint16_t cursor_size;
|
uint16_t cursor_size;
|
||||||
uint32_t cursor_offset;
|
uint32_t cursor_offset;
|
||||||
QEMUCursor *cursor;
|
QEMUCursor *cursor;
|
||||||
|
QEMUTimer vblank_timer;
|
||||||
bitbang_i2c_interface bbi2c;
|
bitbang_i2c_interface bbi2c;
|
||||||
MemoryRegion io;
|
MemoryRegion io;
|
||||||
MemoryRegion mm;
|
MemoryRegion mm;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#define BUS_CNTL 0x0030
|
#define BUS_CNTL 0x0030
|
||||||
#define BUS_CNTL1 0x0034
|
#define BUS_CNTL1 0x0034
|
||||||
#define GEN_INT_CNTL 0x0040
|
#define GEN_INT_CNTL 0x0040
|
||||||
|
#define GEN_INT_STATUS 0x0044
|
||||||
#define CRTC_GEN_CNTL 0x0050
|
#define CRTC_GEN_CNTL 0x0050
|
||||||
#define CRTC_EXT_CNTL 0x0054
|
#define CRTC_EXT_CNTL 0x0054
|
||||||
#define DAC_CNTL 0x0058
|
#define DAC_CNTL 0x0058
|
||||||
|
@ -316,6 +317,11 @@
|
||||||
#define XPLL_FB_DIV_MASK 0x0000FF00
|
#define XPLL_FB_DIV_MASK 0x0000FF00
|
||||||
#define X_MPLL_REF_DIV_MASK 0x000000FF
|
#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) */
|
/* Config control values (CONFIG_CNTL) */
|
||||||
#define APER_0_ENDIAN 0x00000003
|
#define APER_0_ENDIAN 0x00000003
|
||||||
#define APER_1_ENDIAN 0x0000000c
|
#define APER_1_ENDIAN 0x0000000c
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue