From: Laurent Vivier <laurent@vivier.eu>
To: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>, qemu-devel@nongnu.org
Subject: Re: [PATCH 08/12] macfb: add common monitor modes supported by the MacOS toolbox ROM
Date: Mon, 4 Oct 2021 16:39:25 +0200 [thread overview]
Message-ID: <ae8bca21-1e8c-d2a3-50e8-f8343d40e359@vivier.eu> (raw)
In-Reply-To: <20211002110007.30825-9-mark.cave-ayland@ilande.co.uk>
On 02/10/2021 13:00, Mark Cave-Ayland wrote:
> The monitor modes table is found by experimenting with the Monitors Control
> Panel in MacOS and analysing the reads/writes. From this it can be found that
> the mode is controlled by writes to the DAFB_MODE_CTRL1 and DAFB_MODE_CTRL2
> registers.
>
> Implement the first block of DAFB registers as a register array including the
> existing sense register, the newly discovered control registers above, and also
> the DAFB_MODE_VADDR1 and DAFB_MODE_VADDR2 registers which are used by NetBSD to
> determine the current video mode.
>
> These experiments also show that the offset of the start of video RAM and the
> stride can change depending upon the monitor mode, so update macfb_draw_graphic()
> and both the BI_MAC_VADDR and BI_MAC_VROW bootinfo for the q800 machine
> accordingly.
>
> Finally update macfb_common_realize() so that only the resolution and depth
> supported by the display type can be specified on the command line.
>
> Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
> ---
> hw/display/macfb.c | 125 ++++++++++++++++++++++++++++++++-----
> hw/display/trace-events | 1 +
> hw/m68k/q800.c | 11 ++--
> include/hw/display/macfb.h | 16 ++++-
> 4 files changed, 132 insertions(+), 21 deletions(-)
>
> diff --git a/hw/display/macfb.c b/hw/display/macfb.c
> index 023d1f0cd1..6a69334565 100644
> --- a/hw/display/macfb.c
> +++ b/hw/display/macfb.c
> @@ -22,12 +22,16 @@
> #include "migration/vmstate.h"
> #include "trace.h"
>
> -#define VIDEO_BASE 0x00001000
> +#define VIDEO_BASE 0x0
> #define DAFB_BASE 0x00800000
>
> #define MACFB_PAGE_SIZE 4096
> #define MACFB_VRAM_SIZE (4 * MiB)
>
> +#define DAFB_MODE_VADDR1 0x0
> +#define DAFB_MODE_VADDR2 0x4
> +#define DAFB_MODE_CTRL1 0x8
> +#define DAFB_MODE_CTRL2 0xc
> #define DAFB_MODE_SENSE 0x1c
> #define DAFB_RESET 0x200
> #define DAFB_LUT 0x213
> @@ -89,6 +93,22 @@ static MacFbSense macfb_sense_table[] = {
> { MACFB_DISPLAY_SVGA, 0x7, 0x5 },
> };
>
> +static MacFbMode macfb_mode_table[] = {
> + { MACFB_DISPLAY_VGA, 1, 0x100, 0x71e, 640, 480, 0x400, 0x1000 },
> + { MACFB_DISPLAY_VGA, 2, 0x100, 0x70e, 640, 480, 0x400, 0x1000 },
> + { MACFB_DISPLAY_VGA, 4, 0x100, 0x706, 640, 480, 0x400, 0x1000 },
> + { MACFB_DISPLAY_VGA, 8, 0x100, 0x702, 640, 480, 0x400, 0x1000 },
> + { MACFB_DISPLAY_VGA, 24, 0x100, 0x7ff, 640, 480, 0x1000, 0x1000 },
> + { MACFB_DISPLAY_VGA, 1, 0xd0 , 0x70e, 800, 600, 0x340, 0xe00 },
> + { MACFB_DISPLAY_VGA, 2, 0xd0 , 0x706, 800, 600, 0x340, 0xe00 },
> + { MACFB_DISPLAY_VGA, 4, 0xd0 , 0x702, 800, 600, 0x340, 0xe00 },
> + { MACFB_DISPLAY_VGA, 8, 0xd0, 0x700, 800, 600, 0x340, 0xe00 },
> + { MACFB_DISPLAY_VGA, 24, 0x340, 0x100, 800, 600, 0xd00, 0xe00 },
> + { MACFB_DISPLAY_APPLE_21_COLOR, 1, 0x90, 0x506, 1152, 870, 0x240, 0x80 },
> + { MACFB_DISPLAY_APPLE_21_COLOR, 2, 0x90, 0x502, 1152, 870, 0x240, 0x80 },
> + { MACFB_DISPLAY_APPLE_21_COLOR, 4, 0x90, 0x500, 1152, 870, 0x240, 0x80 },
> + { MACFB_DISPLAY_APPLE_21_COLOR, 8, 0x120, 0x5ff, 1152, 870, 0x480, 0x80 },
> +};
>
> typedef void macfb_draw_line_func(MacfbState *s, uint8_t *d, uint32_t addr,
> int width);
> @@ -246,7 +266,7 @@ static void macfb_draw_graphic(MacfbState *s)
> ram_addr_t page;
> uint32_t v = 0;
> int y, ymin;
> - int macfb_stride = (s->depth * s->width + 7) / 8;
> + int macfb_stride = s->mode->stride;
> macfb_draw_line_func *macfb_draw_line;
>
> switch (s->depth) {
> @@ -278,7 +298,7 @@ static void macfb_draw_graphic(MacfbState *s)
> DIRTY_MEMORY_VGA);
>
> ymin = -1;
> - page = 0;
> + page = s->mode->offset;
> for (y = 0; y < s->height; y++, page += macfb_stride) {
> if (macfb_check_dirty(s, snap, page, macfb_stride)) {
> uint8_t *data_display;
> @@ -322,25 +342,26 @@ static uint32_t macfb_sense_read(MacfbState *s)
> sense = 0;
> if (!(macfb_sense->ext_sense & 1)) {
> /* Pins 7-4 together */
> - if (~s->sense & 3) {
> - sense = (~s->sense & 7) | 3;
> + if (~s->regs[DAFB_MODE_SENSE >> 2] & 3) {
> + sense = (~s->regs[DAFB_MODE_SENSE >> 2] & 7) | 3;
> }
> }
> if (!(macfb_sense->ext_sense & 2)) {
> /* Pins 10-7 together */
> - if (~s->sense & 6) {
> - sense = (~s->sense & 7) | 6;
> + if (~s->regs[DAFB_MODE_SENSE >> 2] & 6) {
> + sense = (~s->regs[DAFB_MODE_SENSE >> 2] & 7) | 6;
> }
> }
> if (!(macfb_sense->ext_sense & 4)) {
> /* Pins 4-10 together */
> - if (~s->sense & 5) {
> - sense = (~s->sense & 7) | 5;
> + if (~s->regs[DAFB_MODE_SENSE >> 2] & 5) {
> + sense = (~s->regs[DAFB_MODE_SENSE >> 2] & 7) | 5;
> }
> }
> } else {
> /* Normal sense */
> - sense = (~macfb_sense->sense & 7) | (~s->sense & 7);
> + sense = (~macfb_sense->sense & 7) |
> + (~s->regs[DAFB_MODE_SENSE >> 2] & 7);
> }
>
> trace_macfb_sense_read(sense);
> @@ -349,12 +370,64 @@ static uint32_t macfb_sense_read(MacfbState *s)
>
> static void macfb_sense_write(MacfbState *s, uint32_t val)
> {
> - s->sense = val;
> + s->regs[DAFB_MODE_SENSE >> 2] = val;
>
> trace_macfb_sense_write(val);
> return;
> }
>
> +static void macfb_update_mode(MacfbState *s)
> +{
> + s->width = s->mode->width;
> + s->height = s->mode->height;
> + s->depth = s->mode->depth;
> +
> + trace_macfb_update_mode(s->width, s->height, s->depth);
> + macfb_invalidate_display(s);
> +}
> +
> +static void macfb_mode_write(MacfbState *s)
> +{
> + MacFbMode *macfb_mode;
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(macfb_mode_table); i++) {
> + macfb_mode = &macfb_mode_table[i];
> +
> + if (s->type != macfb_mode->type) {
> + continue;
> + }
> +
> + if ((s->regs[DAFB_MODE_CTRL1 >> 2] & 0xff) ==
> + (macfb_mode->mode_ctrl1 & 0xff) &&
> + (s->regs[DAFB_MODE_CTRL2 >> 2] & 0xff) ==
> + (macfb_mode->mode_ctrl2 & 0xff)) {
> + s->mode = macfb_mode;
> + macfb_update_mode(s);
> + break;
> + }
> + }
> +}
> +
> +static MacFbMode *macfb_find_mode(MacfbDisplayType display_type,
> + uint16_t width, uint16_t height,
> + uint8_t depth)
> +{
> + MacFbMode *macfb_mode;
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(macfb_mode_table); i++) {
> + macfb_mode = &macfb_mode_table[i];
> +
> + if (display_type == macfb_mode->type && width == macfb_mode->width &&
> + height == macfb_mode->height && depth == macfb_mode->depth) {
> + return macfb_mode;
> + }
> + }
> +
> + return NULL;
> +}
> +
> static void macfb_update_display(void *opaque)
> {
> MacfbState *s = opaque;
> @@ -396,6 +469,12 @@ static uint64_t macfb_ctrl_read(void *opaque,
> uint64_t val = 0;
>
> switch (addr) {
> + case DAFB_MODE_VADDR1:
> + case DAFB_MODE_VADDR2:
> + case DAFB_MODE_CTRL1:
> + case DAFB_MODE_CTRL2:
> + val = s->regs[addr >> 2];
> + break;
> case DAFB_MODE_SENSE:
> val = macfb_sense_read(s);
> break;
> @@ -412,6 +491,17 @@ static void macfb_ctrl_write(void *opaque,
> {
> MacfbState *s = opaque;
> switch (addr) {
> + case DAFB_MODE_VADDR1:
> + case DAFB_MODE_VADDR2:
> + s->regs[addr >> 2] = val;
> + break;
> + case DAFB_MODE_CTRL1 ... DAFB_MODE_CTRL1 + 3:
> + case DAFB_MODE_CTRL2 ... DAFB_MODE_CTRL2 + 3:
> + s->regs[addr >> 2] = val;
> + if (val) {
> + macfb_mode_write(s);
> + }
> + break;
> case DAFB_MODE_SENSE:
> macfb_sense_write(s, val);
> break;
> @@ -442,7 +532,7 @@ static const MemoryRegionOps macfb_ctrl_ops = {
>
> static int macfb_post_load(void *opaque, int version_id)
> {
> - macfb_invalidate_display(opaque);
> + macfb_mode_write(opaque);
> return 0;
> }
>
> @@ -455,7 +545,7 @@ static const VMStateDescription vmstate_macfb = {
> .fields = (VMStateField[]) {
> VMSTATE_UINT8_ARRAY(color_palette, MacfbState, 256 * 3),
> VMSTATE_UINT32(palette_current, MacfbState),
> - VMSTATE_UINT32(sense, MacfbState),
> + VMSTATE_UINT32_ARRAY(regs, MacfbState, MACFB_NUM_REGS),
> VMSTATE_END_OF_LIST()
> }
> };
> @@ -469,9 +559,10 @@ static void macfb_common_realize(DeviceState *dev, MacfbState *s, Error **errp)
> {
> DisplaySurface *surface;
>
> - if (s->depth != 1 && s->depth != 2 && s->depth != 4 && s->depth != 8 &&
> - s->depth != 16 && s->depth != 24) {
> - error_setg(errp, "unknown guest depth %d", s->depth);
> + s->mode = macfb_find_mode(s->type, s->width, s->height, s->depth);
> + if (!s->mode) {
> + error_setg(errp, "unknown display mode: width %d, height %d, depth %d",
> + s->width, s->height, s->depth);
> return;
> }
>
> @@ -492,6 +583,8 @@ static void macfb_common_realize(DeviceState *dev, MacfbState *s, Error **errp)
> s->vram = memory_region_get_ram_ptr(&s->mem_vram);
> s->vram_bit_mask = MACFB_VRAM_SIZE - 1;
> memory_region_set_coalescing(&s->mem_vram);
> +
> + macfb_update_mode(s);
> }
>
> static void macfb_sysbus_realize(DeviceState *dev, Error **errp)
> diff --git a/hw/display/trace-events b/hw/display/trace-events
> index 6e378036ab..75574e5976 100644
> --- a/hw/display/trace-events
> +++ b/hw/display/trace-events
> @@ -173,3 +173,4 @@ macfb_ctrl_read(uint64_t addr, uint64_t value, int size) "addr 0x%"PRIx64 " valu
> macfb_ctrl_write(uint64_t addr, uint64_t value, int size) "addr 0x%"PRIx64 " value 0x%"PRIx64 " size %d"
> macfb_sense_read(uint32_t value) "video sense: 0x%"PRIx32
> macfb_sense_write(uint32_t value) "video sense: 0x%"PRIx32
> +macfb_update_mode(uint32_t width, uint32_t height, uint8_t depth) "setting mode to width %"PRId32 " height %"PRId32 " size %d"
> diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
> index 5223b880bc..df3fd3711e 100644
> --- a/hw/m68k/q800.c
> +++ b/hw/m68k/q800.c
> @@ -74,7 +74,7 @@
> * is needed by the kernel to have early display and
> * thus provided by the bootloader
> */
> -#define VIDEO_BASE 0xf9001000
> +#define VIDEO_BASE 0xf9000000
>
> #define MAC_CLOCK 3686418
>
> @@ -221,6 +221,7 @@ static void q800_init(MachineState *machine)
> uint8_t *prom;
> const int io_slice_nb = (IO_SIZE / IO_SLICE) - 1;
> int i, checksum;
> + MacFbMode *macfb_mode;
> ram_addr_t ram_size = machine->ram_size;
> const char *kernel_filename = machine->kernel_filename;
> const char *initrd_filename = machine->initrd_filename;
> @@ -428,6 +429,8 @@ static void q800_init(MachineState *machine)
> }
> qdev_realize_and_unref(dev, BUS(nubus), &error_fatal);
>
> + macfb_mode = (NUBUS_MACFB(dev)->macfb).mode;
> +
> cs = CPU(cpu);
> if (linux_boot) {
> uint64_t high;
> @@ -450,12 +453,12 @@ static void q800_init(MachineState *machine)
> BOOTINFO1(cs->as, parameters_base,
> BI_MAC_MEMSIZE, ram_size >> 20); /* in MB */
> BOOTINFO2(cs->as, parameters_base, BI_MEMCHUNK, 0, ram_size);
> - BOOTINFO1(cs->as, parameters_base, BI_MAC_VADDR, VIDEO_BASE);
> + BOOTINFO1(cs->as, parameters_base, BI_MAC_VADDR,
> + VIDEO_BASE + macfb_mode->offset);
> BOOTINFO1(cs->as, parameters_base, BI_MAC_VDEPTH, graphic_depth);
> BOOTINFO1(cs->as, parameters_base, BI_MAC_VDIM,
> (graphic_height << 16) | graphic_width);
> - BOOTINFO1(cs->as, parameters_base, BI_MAC_VROW,
> - (graphic_width * graphic_depth + 7) / 8);
> + BOOTINFO1(cs->as, parameters_base, BI_MAC_VROW, macfb_mode->stride);
> BOOTINFO1(cs->as, parameters_base, BI_MAC_SCCBASE, SCC_BASE);
>
> rom = g_malloc(sizeof(*rom));
> diff --git a/include/hw/display/macfb.h b/include/hw/display/macfb.h
> index e95a97ebdc..0aff0d84d2 100644
> --- a/include/hw/display/macfb.h
> +++ b/include/hw/display/macfb.h
> @@ -35,6 +35,19 @@ typedef enum {
> MACFB_DISPLAY_SVGA = 14,
> } MacfbDisplayType;
>
> +typedef struct MacFbMode {
> + uint8_t type;
> + uint8_t depth;
> + uint32_t mode_ctrl1;
> + uint32_t mode_ctrl2;
> + uint32_t width;
> + uint32_t height;
> + uint32_t stride;
> + uint32_t offset;
> +} MacFbMode;
> +
> +#define MACFB_NUM_REGS 8
> +
> typedef struct MacfbState {
> MemoryRegion mem_vram;
> MemoryRegion mem_ctrl;
> @@ -48,7 +61,8 @@ typedef struct MacfbState {
> uint8_t depth;
> uint8_t type;
>
> - uint32_t sense;
> + uint32_t regs[MACFB_NUM_REGS];
> + MacFbMode *mode;
> } MacfbState;
>
> #define TYPE_MACFB "sysbus-macfb"
>
Reviewed-by: Laurent Vivier <laurent@vivier.eu>
next prev parent reply other threads:[~2021-10-04 14:41 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-02 10:59 [PATCH 00/12] macfb: fixes for booting MacOS Mark Cave-Ayland
2021-10-02 10:59 ` [PATCH 01/12] macfb: handle errors that occur during realize Mark Cave-Ayland
2021-10-02 11:36 ` BALATON Zoltan
2021-10-04 18:38 ` Mark Cave-Ayland
2021-10-02 13:47 ` Philippe Mathieu-Daudé
2021-10-04 18:39 ` Mark Cave-Ayland
2021-10-04 8:47 ` Laurent Vivier
2021-10-02 10:59 ` [PATCH 02/12] macfb: fix invalid object reference in macfb_common_realize() Mark Cave-Ayland
2021-10-02 11:38 ` BALATON Zoltan
2021-10-02 13:51 ` Philippe Mathieu-Daudé
2021-10-04 8:49 ` Laurent Vivier
2021-10-02 10:59 ` [PATCH 03/12] macfb: fix overflow of color_palette array Mark Cave-Ayland
2021-10-04 8:53 ` Laurent Vivier
2021-10-04 18:48 ` Mark Cave-Ayland
2021-10-02 10:59 ` [PATCH 04/12] macfb: use memory_region_init_ram() in macfb_common_realize() for the framebuffer Mark Cave-Ayland
2021-10-02 11:42 ` BALATON Zoltan
2021-10-02 13:59 ` Philippe Mathieu-Daudé
2021-10-04 8:53 ` Laurent Vivier
2021-10-02 11:00 ` [PATCH 05/12] macfb: add trace events for reading and writing the control registers Mark Cave-Ayland
2021-10-02 14:00 ` Philippe Mathieu-Daudé
2021-10-04 8:57 ` Laurent Vivier
2021-10-02 11:00 ` [PATCH 06/12] macfb: implement mode sense to allow display type to be detected Mark Cave-Ayland
2021-10-04 9:20 ` Laurent Vivier
2021-10-04 10:32 ` BALATON Zoltan
2021-10-04 10:50 ` Laurent Vivier
2021-10-02 11:00 ` [PATCH 07/12] macfb: add qdev property to specify display type Mark Cave-Ayland
2021-10-02 14:04 ` Philippe Mathieu-Daudé
2021-10-04 18:46 ` Mark Cave-Ayland
2021-10-04 9:24 ` Laurent Vivier
2021-10-04 14:38 ` Laurent Vivier
2021-10-02 11:00 ` [PATCH 08/12] macfb: add common monitor modes supported by the MacOS toolbox ROM Mark Cave-Ayland
2021-10-04 14:39 ` Laurent Vivier [this message]
2021-10-02 11:00 ` [PATCH 09/12] macfb: fix up 1-bit pixel encoding Mark Cave-Ayland
2021-10-04 14:40 ` Laurent Vivier
2021-10-02 11:00 ` [PATCH 10/12] macfb: fix 24-bit RGB " Mark Cave-Ayland
2021-10-04 14:41 ` Laurent Vivier
2021-10-02 11:00 ` [PATCH 11/12] macfb: add vertical blank interrupt Mark Cave-Ayland
2021-10-04 16:32 ` Laurent Vivier
2021-10-04 18:52 ` Mark Cave-Ayland
2021-10-02 11:00 ` [PATCH 12/12] q800: wire macfb IRQ to separate video interrupt on VIA2 Mark Cave-Ayland
2021-10-02 14:06 ` Philippe Mathieu-Daudé
2021-10-04 9:28 ` Laurent Vivier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ae8bca21-1e8c-d2a3-50e8-f8343d40e359@vivier.eu \
--to=laurent@vivier.eu \
--cc=mark.cave-ayland@ilande.co.uk \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).