Commit b7105d28 authored by BALATON Zoltan's avatar BALATON Zoltan Committed by Gerd Hoffmann
Browse files

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: default avatarBALATON Zoltan <balaton@eik.bme.hu>
Message-Id: <89364275f2fb5f85ee73c0e76528aa91691a499a.1565907489.git.balaton@eik.bme.hu>
Signed-off-by: default avatarGerd Hoffmann <kraxel@redhat.com>
parent 8bb9a2b2
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -243,6 +243,21 @@ static uint64_t ati_i2c(bitbang_i2c_interface *i2c, uint64_t data, int base)
    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,
                                         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);
        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);
@@ -512,6 +533,21 @@ static void ati_mm_write(void *opaque, hwaddr addr,
                           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;
@@ -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, 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);

    timer_del(&s->vblank_timer);
    ati_vga_update_irq(s);

    /* reset vga */
    vga_common_reset(&s->vga);
    s->mode = VGA_MODE;
@@ -917,6 +960,7 @@ static void ati_vga_exit(PCIDevice *dev)
{
    ATIVGAState *s = ATI_VGA(dev);

    timer_del(&s->vblank_timer);
    graphic_console_close(s->vga.con);
}

+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ static struct ati_regdesc ati_reg_names[] = {
    {"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},
+4 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#ifndef ATI_INT_H
#define ATI_INT_H

#include "qemu/timer.h"
#include "hw/pci/pci.h"
#include "hw/i2c/bitbang_i2c.h"
#include "vga_int.h"
@@ -33,6 +34,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;
@@ -89,6 +92,7 @@ typedef struct ATIVGAState {
    uint16_t cursor_size;
    uint32_t cursor_offset;
    QEMUCursor *cursor;
    QEMUTimer vblank_timer;
    bitbang_i2c_interface bbi2c;
    MemoryRegion io;
    MemoryRegion mm;
+6 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#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
@@ -316,6 +317,11 @@
#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