diff mbox series

[06/12] macfb: implement mode sense to allow display type to be detected

Message ID 20211002110007.30825-7-mark.cave-ayland@ilande.co.uk (mailing list archive)
State New, archived
Headers show
Series macfb: fixes for booting MacOS | expand

Commit Message

Mark Cave-Ayland Oct. 2, 2021, 11 a.m. UTC
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>
---
 hw/display/macfb.c         | 117 ++++++++++++++++++++++++++++++++++++-
 hw/display/trace-events    |   2 +
 include/hw/display/macfb.h |  20 +++++++
 3 files changed, 137 insertions(+), 2 deletions(-)

Comments

Laurent Vivier Oct. 4, 2021, 9:20 a.m. UTC | #1
Le 02/10/2021 à 13:00, Mark Cave-Ayland a écrit :
> 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>
> ---
>  hw/display/macfb.c         | 117 ++++++++++++++++++++++++++++++++++++-
>  hw/display/trace-events    |   2 +
>  include/hw/display/macfb.h |  20 +++++++
>  3 files changed, 137 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/display/macfb.c b/hw/display/macfb.c
> index 62c2727a5b..5c95aa4a11 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

https://developer.apple.com/library/archive/technotes/hw/hw_26.html

> + * 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 },

Perhaps it could be interesting to also have the "no external monitor" entry?
But generally not to have monitor prevents the boot of MacOS.

...

Reviewed-by: Laurent Vivier <laurent@vivier.eu>
BALATON Zoltan Oct. 4, 2021, 10:32 a.m. UTC | #2
On Mon, 4 Oct 2021, Laurent Vivier wrote:
> Le 02/10/2021 à 13:00, Mark Cave-Ayland a écrit :
>> 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>
>> ---
>>  hw/display/macfb.c         | 117 ++++++++++++++++++++++++++++++++++++-
>>  hw/display/trace-events    |   2 +
>>  include/hw/display/macfb.h |  20 +++++++
>>  3 files changed, 137 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/display/macfb.c b/hw/display/macfb.c
>> index 62c2727a5b..5c95aa4a11 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
>
> https://developer.apple.com/library/archive/technotes/hw/hw_26.html

URLs may change or go away so I think it's better to reference by title in 
comments, then one can find it by that whereas a stale URL is not much 
help a few years from now.

Regards,
BALATON Zoltan

>> + * 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 },
>
> Perhaps it could be interesting to also have the "no external monitor" entry?
> But generally not to have monitor prevents the boot of MacOS.
>
> ...
>
> Reviewed-by: Laurent Vivier <laurent@vivier.eu>
>
>
Laurent Vivier Oct. 4, 2021, 10:50 a.m. UTC | #3
Le 04/10/2021 à 12:32, BALATON Zoltan a écrit :
> On Mon, 4 Oct 2021, Laurent Vivier wrote:
>> Le 02/10/2021 à 13:00, Mark Cave-Ayland a écrit :
>>> 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>
>>> ---
>>>  hw/display/macfb.c         | 117 ++++++++++++++++++++++++++++++++++++-
>>>  hw/display/trace-events    |   2 +
>>>  include/hw/display/macfb.h |  20 +++++++
>>>  3 files changed, 137 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/hw/display/macfb.c b/hw/display/macfb.c
>>> index 62c2727a5b..5c95aa4a11 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
>>
>> https://developer.apple.com/library/archive/technotes/hw/hw_26.html
> 
> URLs may change or go away so I think it's better to reference by title in comments, then one can
> find it by that whereas a stale URL is not much help a few years from now.

This URL is very stable (hosted by Apple for 30 years now...) and providing it could help to find a
copy of the document in an internet archive. I had some difficulties to find it using the title or
the TN number.

Thanks,
Laurent
diff mbox series

Patch

diff --git a/hw/display/macfb.c b/hw/display/macfb.c
index 62c2727a5b..5c95aa4a11 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;
@@ -343,6 +455,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 be1353e8e7..6e378036ab 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, int size) "addr 0x%"PRIx64 " value 0x%"PRIx64 " size %d"
 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
diff --git a/include/hw/display/macfb.h b/include/hw/display/macfb.h
index 80806b0306..febf4ce0e8 100644
--- a/include/hw/display/macfb.h
+++ b/include/hw/display/macfb.h
@@ -17,6 +17,24 @@ 
 #include "ui/console.h"
 #include "qom/object.h"
 
+typedef enum  {
+    MACFB_DISPLAY_APPLE_21_COLOR = 0,
+    MACFB_DISPLAY_APPLE_PORTRAIT = 1,
+    MACFB_DISPLAY_APPLE_12_RGB = 2,
+    MACFB_DISPLAY_APPLE_2PAGE_MONO = 3,
+    MACFB_DISPLAY_NTSC_UNDERSCAN = 4,
+    MACFB_DISPLAY_NTSC_OVERSCAN = 5,
+    MACFB_DISPLAY_APPLE_12_MONO = 6,
+    MACFB_DISPLAY_APPLE_13_RGB = 7,
+    MACFB_DISPLAY_16_COLOR = 8,
+    MACFB_DISPLAY_PAL1_UNDERSCAN = 9,
+    MACFB_DISPLAY_PAL1_OVERSCAN = 10,
+    MACFB_DISPLAY_PAL2_UNDERSCAN = 11,
+    MACFB_DISPLAY_PAL2_OVERSCAN = 12,
+    MACFB_DISPLAY_VGA = 13,
+    MACFB_DISPLAY_SVGA = 14,
+} MacfbDisplayType;
+
 typedef struct MacfbState {
     MemoryRegion mem_vram;
     MemoryRegion mem_ctrl;
@@ -28,6 +46,8 @@  typedef struct MacfbState {
     uint8_t color_palette[256 * 3];
     uint32_t width, height; /* in pixels */
     uint8_t depth;
+
+    uint32_t sense;
 } MacfbState;
 
 #define TYPE_MACFB "sysbus-macfb"