From nobody Tue Feb 10 13:36:13 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1633382835693622.0190679818346; Mon, 4 Oct 2021 14:27:15 -0700 (PDT) Received: from localhost ([::1]:57248 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mXVUQ-0005l4-H0 for importer@patchew.org; Mon, 04 Oct 2021 17:27:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56878) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mXVNd-0002Kf-PP for qemu-devel@nongnu.org; Mon, 04 Oct 2021 17:20:13 -0400 Received: from mail.ilande.co.uk ([2001:41c9:1:41f::167]:35874 helo=mail.default.ilande.bv.iomart.io) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mXVNb-0002HS-Ih for qemu-devel@nongnu.org; Mon, 04 Oct 2021 17:20:13 -0400 Received: from [2a00:23c4:8b9d:4100:5d98:71b5:90ca:dad1] (helo=kentang.home) by mail.default.ilande.bv.iomart.io with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mXVNN-0008kv-C3; Mon, 04 Oct 2021 22:20:01 +0100 From: Mark Cave-Ayland To: qemu-devel@nongnu.org, laurent@vivier.eu Date: Mon, 4 Oct 2021 22:19:24 +0100 Message-Id: <20211004211928.15803-9-mark.cave-ayland@ilande.co.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20211004211928.15803-1-mark.cave-ayland@ilande.co.uk> References: <20211004211928.15803-1-mark.cave-ayland@ilande.co.uk> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-SA-Exim-Connect-IP: 2a00:23c4:8b9d:4100:5d98:71b5:90ca:dad1 X-SA-Exim-Mail-From: mark.cave-ayland@ilande.co.uk Subject: [PATCH v2 08/12] macfb: add common monitor modes supported by the MacOS toolbox ROM X-SA-Exim-Version: 4.2.1 (built Wed, 08 May 2019 21:11:16 +0000) X-SA-Exim-Scanned: Yes (on mail.default.ilande.bv.iomart.io) Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2001:41c9:1:41f::167; envelope-from=mark.cave-ayland@ilande.co.uk; helo=mail.default.ilande.bv.iomart.io X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZM-MESSAGEID: 1633382837144100001 Content-Type: text/plain; charset="utf-8" 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 th= at 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 t= he existing sense register, the newly discovered control registers above, and = also the DAFB_MODE_VADDR1 and DAFB_MODE_VADDR2 registers which are used by NetBS= D to determine the current video mode. These experiments also show that the offset of the start of video RAM and t= he stride can change depending upon the monitor mode, so update macfb_draw_gra= phic() 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 Reviewed-by: Laurent Vivier --- hw/display/macfb.c | 124 ++++++++++++++++++++++++++++++++----- hw/display/trace-events | 1 + hw/m68k/q800.c | 11 ++-- include/hw/display/macfb.h | 16 ++++- 4 files changed, 131 insertions(+), 21 deletions(-) diff --git a/hw/display/macfb.c b/hw/display/macfb.c index f98bcdec2d..357fe18be5 100644 --- a/hw/display/macfb.c +++ b/hw/display/macfb.c @@ -22,12 +22,16 @@ #include "migration/vmstate.h" #include "trace.h" =20 -#define VIDEO_BASE 0x00001000 +#define VIDEO_BASE 0x0 #define DAFB_BASE 0x00800000 =20 #define MACFB_PAGE_SIZE 4096 #define MACFB_VRAM_SIZE (4 * MiB) =20 +#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[] =3D { { MACFB_DISPLAY_SVGA, 0x7, 0x5 }, }; =20 +static MacFbMode macfb_mode_table[] =3D { + { 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, 0x8= 0 }, +}; =20 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 =3D 0; int y, ymin; - int macfb_stride =3D (s->depth * s->width + 7) / 8; + int macfb_stride =3D s->mode->stride; macfb_draw_line_func *macfb_draw_line; =20 switch (s->depth) { @@ -278,7 +298,7 @@ static void macfb_draw_graphic(MacfbState *s) DIRTY_MEMORY_VGA); =20 ymin =3D -1; - page =3D 0; + page =3D s->mode->offset; for (y =3D 0; y < s->height; y++, page +=3D macfb_stride) { if (macfb_check_dirty(s, snap, page, macfb_stride)) { uint8_t *data_display; @@ -323,25 +343,26 @@ static uint32_t macfb_sense_read(MacfbState *s) sense =3D 0; if (!(macfb_sense->ext_sense & 1)) { /* Pins 7-4 together */ - if (~s->sense & 3) { - sense =3D (~s->sense & 7) | 3; + if (~s->regs[DAFB_MODE_SENSE >> 2] & 3) { + sense =3D (~s->regs[DAFB_MODE_SENSE >> 2] & 7) | 3; } } if (!(macfb_sense->ext_sense & 2)) { /* Pins 10-7 together */ - if (~s->sense & 6) { - sense =3D (~s->sense & 7) | 6; + if (~s->regs[DAFB_MODE_SENSE >> 2] & 6) { + sense =3D (~s->regs[DAFB_MODE_SENSE >> 2] & 7) | 6; } } if (!(macfb_sense->ext_sense & 4)) { /* Pins 4-10 together */ - if (~s->sense & 5) { - sense =3D (~s->sense & 7) | 5; + if (~s->regs[DAFB_MODE_SENSE >> 2] & 5) { + sense =3D (~s->regs[DAFB_MODE_SENSE >> 2] & 7) | 5; } } } else { /* Normal sense */ - sense =3D (~macfb_sense->sense & 7) | (~s->sense & 7); + sense =3D (~macfb_sense->sense & 7) | + (~s->regs[DAFB_MODE_SENSE >> 2] & 7); } =20 trace_macfb_sense_read(sense); @@ -350,12 +371,64 @@ static uint32_t macfb_sense_read(MacfbState *s) =20 static void macfb_sense_write(MacfbState *s, uint32_t val) { - s->sense =3D val; + s->regs[DAFB_MODE_SENSE >> 2] =3D val; =20 trace_macfb_sense_write(val); return; } =20 +static void macfb_update_mode(MacfbState *s) +{ + s->width =3D s->mode->width; + s->height =3D s->mode->height; + s->depth =3D 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 =3D 0; i < ARRAY_SIZE(macfb_mode_table); i++) { + macfb_mode =3D &macfb_mode_table[i]; + + if (s->type !=3D macfb_mode->type) { + continue; + } + + if ((s->regs[DAFB_MODE_CTRL1 >> 2] & 0xff) =3D=3D + (macfb_mode->mode_ctrl1 & 0xff) && + (s->regs[DAFB_MODE_CTRL2 >> 2] & 0xff) =3D=3D + (macfb_mode->mode_ctrl2 & 0xff)) { + s->mode =3D 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 =3D 0; i < ARRAY_SIZE(macfb_mode_table); i++) { + macfb_mode =3D &macfb_mode_table[i]; + + if (display_type =3D=3D macfb_mode->type && width =3D=3D macfb_mod= e->width && + height =3D=3D macfb_mode->height && depth =3D=3D macfb_mod= e->depth) { + return macfb_mode; + } + } + + return NULL; +} + static void macfb_update_display(void *opaque) { MacfbState *s =3D opaque; @@ -397,6 +470,12 @@ static uint64_t macfb_ctrl_read(void *opaque, uint64_t val =3D 0; =20 switch (addr) { + case DAFB_MODE_VADDR1: + case DAFB_MODE_VADDR2: + case DAFB_MODE_CTRL1: + case DAFB_MODE_CTRL2: + val =3D s->regs[addr >> 2]; + break; case DAFB_MODE_SENSE: val =3D macfb_sense_read(s); break; @@ -413,6 +492,17 @@ static void macfb_ctrl_write(void *opaque, { MacfbState *s =3D opaque; switch (addr) { + case DAFB_MODE_VADDR1: + case DAFB_MODE_VADDR2: + s->regs[addr >> 2] =3D val; + break; + case DAFB_MODE_CTRL1 ... DAFB_MODE_CTRL1 + 3: + case DAFB_MODE_CTRL2 ... DAFB_MODE_CTRL2 + 3: + s->regs[addr >> 2] =3D 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 =3D { =20 static int macfb_post_load(void *opaque, int version_id) { - macfb_invalidate_display(opaque); + macfb_mode_write(opaque); return 0; } =20 @@ -455,7 +545,7 @@ static const VMStateDescription vmstate_macfb =3D { .fields =3D (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 bool macfb_common_realize(DeviceState *dev, Mac= fbState *s, Error **errp) { DisplaySurface *surface; =20 - if (s->depth !=3D 1 && s->depth !=3D 2 && s->depth !=3D 4 && s->depth = !=3D 8 && - s->depth !=3D 16 && s->depth !=3D 24) { - error_setg(errp, "unknown guest depth %d", s->depth); + s->mode =3D 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 false; } =20 @@ -493,6 +584,7 @@ static bool macfb_common_realize(DeviceState *dev, Macf= bState *s, Error **errp) s->vram_bit_mask =3D MACFB_VRAM_SIZE - 1; memory_region_set_coalescing(&s->mem_vram); =20 + macfb_update_mode(s); return true; } =20 diff --git a/hw/display/trace-events b/hw/display/trace-events index 5753421a43..075cd4614c 100644 --- a/hw/display/trace-events +++ b/hw/display/trace-events @@ -173,3 +173,4 @@ macfb_ctrl_read(uint64_t addr, uint64_t value, unsigned= int size) "addr 0x%"PRIx macfb_ctrl_write(uint64_t addr, uint64_t value, unsigned int size) "addr 0= x%"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 =20 #define MAC_CLOCK 3686418 =20 @@ -221,6 +221,7 @@ static void q800_init(MachineState *machine) uint8_t *prom; const int io_slice_nb =3D (IO_SIZE / IO_SLICE) - 1; int i, checksum; + MacFbMode *macfb_mode; ram_addr_t ram_size =3D machine->ram_size; const char *kernel_filename =3D machine->kernel_filename; const char *initrd_filename =3D machine->initrd_filename; @@ -428,6 +429,8 @@ static void q800_init(MachineState *machine) } qdev_realize_and_unref(dev, BUS(nubus), &error_fatal); =20 + macfb_mode =3D (NUBUS_MACFB(dev)->macfb).mode; + cs =3D 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); =20 rom =3D 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 =3D 14, } MacfbDisplayType; =20 +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; =20 - uint32_t sense; + uint32_t regs[MACFB_NUM_REGS]; + MacFbMode *mode; } MacfbState; =20 #define TYPE_MACFB "sysbus-macfb" --=20 2.20.1