aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorMark Cave-Ayland <mark.cave-ayland@ilande.co.uk>2021-10-07 23:12:47 +0100
committerLaurent Vivier <laurent@vivier.eu>2021-10-08 13:31:03 +0200
commite6108b96363bda0704ca69e5dfdb4b07dc589336 (patch)
tree2009220bd32b19b97ce4950567586a506dd05b69 /hw
parent4ec27073fd0e5a82a87b1122dfdca7a820cb1561 (diff)
downloadqemu-e6108b96363bda0704ca69e5dfdb4b07dc589336.zip
qemu-e6108b96363bda0704ca69e5dfdb4b07dc589336.tar.gz
qemu-e6108b96363bda0704ca69e5dfdb4b07dc589336.tar.bz2
macfb: implement mode sense to allow display type to be detected
The MacOS toolbox ROM uses the monitor sense to detect the display type and then offer a fixed set of resolutions and colour depths accordingly. Implement the monitor sense using information found in Apple Technical Note HW26: "Macintosh Quadra Built-In Video" along with some local experiments. Since the default configuration is 640 x 480 with 8-bit colour then hardcode the sense register to return MACFB_DISPLAY_VGA for now. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Reviewed-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20211007221253.29024-8-mark.cave-ayland@ilande.co.uk> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'hw')
-rw-r--r--hw/display/macfb.c117
-rw-r--r--hw/display/trace-events2
2 files changed, 117 insertions, 2 deletions
diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index 1128a51..6e485d7 100644
--- a/hw/display/macfb.c
+++ b/hw/display/macfb.c
@@ -28,8 +28,66 @@
#define MACFB_PAGE_SIZE 4096
#define MACFB_VRAM_SIZE (4 * MiB)
-#define DAFB_RESET 0x200
-#define DAFB_LUT 0x213
+#define DAFB_MODE_SENSE 0x1c
+#define DAFB_RESET 0x200
+#define DAFB_LUT 0x213
+
+
+/*
+ * Quadra sense codes taken from Apple Technical Note HW26:
+ * "Macintosh Quadra Built-In Video". The sense codes and
+ * extended sense codes have different meanings:
+ *
+ * Sense:
+ * bit 2: SENSE2 (pin 10)
+ * bit 1: SENSE1 (pin 7)
+ * bit 0: SENSE0 (pin 4)
+ *
+ * 0 = pin tied to ground
+ * 1 = pin unconnected
+ *
+ * Extended Sense:
+ * bit 2: pins 4-10
+ * bit 1: pins 10-7
+ * bit 0: pins 7-4
+ *
+ * 0 = pins tied together
+ * 1 = pins unconnected
+ *
+ * Reads from the sense register appear to be active low, i.e. a 1 indicates
+ * that the pin is tied to ground, a 0 indicates the pin is disconnected.
+ *
+ * Writes to the sense register appear to activate pulldowns i.e. a 1 enables
+ * a pulldown on a particular pin.
+ *
+ * The MacOS toolbox appears to use a series of reads and writes to first
+ * determine if extended sense is to be used, and then check which pins are
+ * tied together in order to determine the display type.
+ */
+
+typedef struct MacFbSense {
+ uint8_t type;
+ uint8_t sense;
+ uint8_t ext_sense;
+} MacFbSense;
+
+static MacFbSense macfb_sense_table[] = {
+ { MACFB_DISPLAY_APPLE_21_COLOR, 0x0, 0 },
+ { MACFB_DISPLAY_APPLE_PORTRAIT, 0x1, 0 },
+ { MACFB_DISPLAY_APPLE_12_RGB, 0x2, 0 },
+ { MACFB_DISPLAY_APPLE_2PAGE_MONO, 0x3, 0 },
+ { MACFB_DISPLAY_NTSC_UNDERSCAN, 0x4, 0 },
+ { MACFB_DISPLAY_NTSC_OVERSCAN, 0x4, 0 },
+ { MACFB_DISPLAY_APPLE_12_MONO, 0x6, 0 },
+ { MACFB_DISPLAY_APPLE_13_RGB, 0x6, 0 },
+ { MACFB_DISPLAY_16_COLOR, 0x7, 0x3 },
+ { MACFB_DISPLAY_PAL1_UNDERSCAN, 0x7, 0x0 },
+ { MACFB_DISPLAY_PAL1_OVERSCAN, 0x7, 0x0 },
+ { MACFB_DISPLAY_PAL2_UNDERSCAN, 0x7, 0x6 },
+ { MACFB_DISPLAY_PAL2_OVERSCAN, 0x7, 0x6 },
+ { MACFB_DISPLAY_VGA, 0x7, 0x5 },
+ { MACFB_DISPLAY_SVGA, 0x7, 0x5 },
+};
typedef void macfb_draw_line_func(MacfbState *s, uint8_t *d, uint32_t addr,
@@ -253,6 +311,50 @@ static void macfb_invalidate_display(void *opaque)
memory_region_set_dirty(&s->mem_vram, 0, MACFB_VRAM_SIZE);
}
+static uint32_t macfb_sense_read(MacfbState *s)
+{
+ MacFbSense *macfb_sense;
+ uint8_t sense;
+
+ macfb_sense = &macfb_sense_table[MACFB_DISPLAY_VGA];
+ if (macfb_sense->sense == 0x7) {
+ /* Extended sense */
+ sense = 0;
+ if (!(macfb_sense->ext_sense & 1)) {
+ /* Pins 7-4 together */
+ if (~s->sense & 3) {
+ sense = (~s->sense & 7) | 3;
+ }
+ }
+ if (!(macfb_sense->ext_sense & 2)) {
+ /* Pins 10-7 together */
+ if (~s->sense & 6) {
+ sense = (~s->sense & 7) | 6;
+ }
+ }
+ if (!(macfb_sense->ext_sense & 4)) {
+ /* Pins 4-10 together */
+ if (~s->sense & 5) {
+ sense = (~s->sense & 7) | 5;
+ }
+ }
+ } else {
+ /* Normal sense */
+ sense = (~macfb_sense->sense & 7) | (~s->sense & 7);
+ }
+
+ trace_macfb_sense_read(sense);
+ return sense;
+}
+
+static void macfb_sense_write(MacfbState *s, uint32_t val)
+{
+ s->sense = val;
+
+ trace_macfb_sense_write(val);
+ return;
+}
+
static void macfb_update_display(void *opaque)
{
MacfbState *s = opaque;
@@ -290,8 +392,15 @@ static uint64_t macfb_ctrl_read(void *opaque,
hwaddr addr,
unsigned int size)
{
+ MacfbState *s = opaque;
uint64_t val = 0;
+ switch (addr) {
+ case DAFB_MODE_SENSE:
+ val = macfb_sense_read(s);
+ break;
+ }
+
trace_macfb_ctrl_read(addr, val, size);
return val;
}
@@ -303,6 +412,9 @@ static void macfb_ctrl_write(void *opaque,
{
MacfbState *s = opaque;
switch (addr) {
+ case DAFB_MODE_SENSE:
+ macfb_sense_write(s, val);
+ break;
case DAFB_RESET:
s->palette_current = 0;
break;
@@ -342,6 +454,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_END_OF_LIST()
}
};
diff --git a/hw/display/trace-events b/hw/display/trace-events
index f227de1..30cb460 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -171,3 +171,5 @@ sm501_2d_engine_write(uint32_t addr, uint32_t val) "addr=0x%x, val=0x%x"
# macfb.c
macfb_ctrl_read(uint64_t addr, uint64_t value, unsigned int size) "addr 0x%"PRIx64 " value 0x%"PRIx64 " size %u"
macfb_ctrl_write(uint64_t addr, uint64_t value, unsigned int size) "addr 0x%"PRIx64 " value 0x%"PRIx64 " size %u"
+macfb_sense_read(uint32_t value) "video sense: 0x%"PRIx32
+macfb_sense_write(uint32_t value) "video sense: 0x%"PRIx32