NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

port-mac68k/60717: mac68k: genfb_grfbus registers no mode callback, so nothing on the port can react to WSDISPLAYIO_SMODE



>Number:         60717
>Category:       port-mac68k
>Synopsis:       mac68k: genfb_grfbus registers no mode callback, so nothing on the port can react to WSDISPLAYIO_SMODE
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    port-mac68k-maintainer
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Sep 11 23:15:01 +0000 2026
>Originator:     Ray Tran
>Release:        11.0
>Organization:
Diamond Creek Digital
>Environment:
Hardware: Apple Macintosh Centris 650
Kernel: NetBSD 11.0 and CURRENT
>Description:
genfb(4) has a hook for the one transition a framebuffer driver has to
know about.  That is WSDISPLAYIO_SMODE, the ioctl by which X, wsfb
clients and image viewers take the display into mapped mode and hand
it back.  When a genfb_mode_callback is registered, genfb calls
gmc_setmode() with the new mode at attach and on every change
(dev/wsfb/genfb.c, genfb_init() and the WSDISPLAYIO_SMODE case in
genfb_ioctl()).

That is the point at which chipset-specific state has to be handed over
and reclaimed: a hardware cursor hidden or restored, a palette saved and
put back, a CRTC or scanout register parked where a linear mmap expects
it and released afterwards, a blanking or power state changed.  x86
(arch/x86/pci/pci_machdep.c), Hyper-V (arch/x86/x86/hyperv.c) and
drmfb (external/bsd/drm2/drm/drmfb.c) all register one for these
reasons.

mac68k does not.  genfb_grfbus_attach() registers the colormap callback
("cmap_callback") and stops there, so on this port sc_modecb is always
NULL and the transition is invisible to everything below wsdisplay.
Nor can a driver make up for it later: genfb reads the callback pointer
from the device properties once, in genfb_init(), so it has to exist
before genfb attaches.  A chipset driver that attaches after genfb, or
is loaded with modload(8), has nowhere to hook.

The change registers a mode callback in genfb_grfbus_attach()
unconditionally, next to the colormap one, and forwards it through a
hook pointer that any driver on the port can claim and release at any
time.  It adds no userland interface and changes nothing for a kernel
in which nothing claims the hook.
>How-To-Repeat:
On any mac68k machine with internal video, note that genfb attaches
with "colormap callback provided" and nothing equivalent for the mode
callback, and that dev/wsfb/genfb.c's scp->sc_modecb is therefore NULL
for the life of the device.  There is no way for a driver on this port
to be told that WSDISPLAYIO_SMODE happened.
>Fix:
Applies to sys/arch/mac68k/dev/genfb_grfbus.c and
sys/arch/mac68k/include/video.h, on top of the genfb_grfbus console
pitch change in port-mac68k/60695.  It applies to NetBSD 11.0 and to
-current with no fuzz.

Tested on a Macintosh Centris 650 (DAFB, 640x480x8) under NetBSD 11.0
with an out-of-tree DAFB console driver as the consumer I am developing. 
My console driver claims the hook on load and releases it on unload, 
and receives the mode on both.
It parks and restores the scanout across X and a sixel viewer entering
and leaving mapped mode, with no change to either program.  A kernel
with the change and nothing claiming the hook behaves as before.

Applies with "patch -p1" from the top of usr/src; verified with -F0
(no fuzz) against NetBSD-current 11.99.8 (20260830003849Z) and 11.0.

--- a/sys/arch/mac68k/dev/genfb_grfbus.c
+++ b/sys/arch/mac68k/dev/genfb_grfbus.c
@@ -103,6 +103,39 @@
 
 static struct genfb_colormap_callback gfb_cmcb;
 
+void (*mac68k_genfb_mode_hook)(void *, int) = NULL;
+void *mac68k_genfb_mode_arg = NULL;
+
+static bool
+genfb_grfbus_setmode(struct genfb_softc *sc, int mode)
+{
+
+	if (mac68k_genfb_mode_hook != NULL)
+		(*mac68k_genfb_mode_hook)(mac68k_genfb_mode_arg, mode);
+	return true;
+}
+
+static struct genfb_mode_callback gfb_modecb = {
+	.gmc_setmode = genfb_grfbus_setmode,
+};
+
 static int __unused
 genfb_grfbus_is_console(paddr_t addr)
 {
@@ -207,6 +240,9 @@
 		    (uint64_t)(uintptr_t)&gfb_cmcb);
 	}
 
+	prop_dictionary_set_uint64(dict, "mode_callback",
+	    (uint64_t)(uintptr_t)&gfb_modecb);
+
 	genfb_init(&sc->sc_gen);
 
 	if (sc->sc_gen.sc_width == 0 || sc->sc_gen.sc_fbsize == 0) {
--- a/sys/arch/mac68k/include/video.h
+++ b/sys/arch/mac68k/include/video.h
@@ -56,4 +56,13 @@
 
 extern struct mac68k_video mac68k_video;
 
+extern void (*mac68k_genfb_mode_hook)(void *, int);
+extern void *mac68k_genfb_mode_arg;
+
 #endif /* _CPU_VIDEO_H_ */




Home | Main Index | Thread Index | Old Index