NetBSD-Bugs archive

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

kern/60948: WSDISPLAYIO_GMODE returns wrong value once MODE_DUMBFB is set



>Number:         60948
>Category:       kern
>Synopsis:       WSDISPLAYIO_GMODE returns wrong value once MODE_DUMBFB is set
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Oct 31 17:00:00 +0000 2026
>Originator:     Izumi Tsutsui
>Release:        NetBSD 11.0
>Organization:
>Environment:
System: NetBSD mirage 11.0 NetBSD 11.0 (GENERIC) #0:
Architecture: all
Machine: all (with wscons)
>Description:

wscons(4) WSDISPLAYIO_GMODE ioctl returns a incorrect value in
some case (see below).

>How-To-Repeat:

Save and build the following test code:

```c
#include <sys/types.h>
#include <sys/ioctl.h>

#include <dev/wscons/wsconsio.h>

#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char **argv)
{
	const int modes[] = {
		WSDISPLAYIO_MODE_DUMBFB,
		WSDISPLAYIO_MODE_EMUL,
		WSDISPLAYIO_MODE_MAPPED
	};
	const char *names[] = { "DUMBFB", "EMUL", "MAPPED" };
	int fd, saved, mode, got[3], i, n = 0, status = 0;

	if (argc != 2)
		errx(EXIT_FAILURE, "usage: %s /dev/ttyE0", argv[0]);
	if ((fd = open(argv[1], O_RDWR)) == -1)
		err(EXIT_FAILURE, "%s", argv[1]);
	if (ioctl(fd, WSDISPLAYIO_GMODE, &saved) == -1)
		err(EXIT_FAILURE, "initial GMODE");

	/* SMODE (write) then GMODE (read back) */
	for (i = 0; i < 3; i++) {
		mode = modes[i];
		if (ioctl(fd, WSDISPLAYIO_SMODE, &mode) == -1) {
			warn("SMODE %s", names[i]);
			status = 1;
			break;
		}
		if (ioctl(fd, WSDISPLAYIO_GMODE, &got[i]) == -1) {
			warn("GMODE after %s", names[i]);
			status = 1;
			break;
		}
		n++;
		if (got[i] != modes[i])
			status = 1;
	}
	/* Restore SMODE */
	if (ioctl(fd, WSDISPLAYIO_SMODE, &saved) == -1) {
		warn("restore SMODE");
		status = 1;
	}
	close(fd);
	/* Print results */
	for (i = 0; i < n; i++)
		printf("%s: requested %d, GMODE returned %d (%s)\n",
		    names[i], modes[i], got[i],
		    got[i] == modes[i] ? "OK" : "FAIL");
	return status;
}
```

# cc -O -o wsdisplay-mode-test wsdisplay-mode-test.c
#  ./wsdisplay-mode-test
wsdisplay-mode-test: usage: ./wsdisplay-mode-test /dev/ttyE0
# ./wsdisplay-mode-test /dev/ttyE0
DUMBFB: requested 2, GMODE returned 2 (OK)
EMUL: requested 0, GMODE returned 0 (OK)
MAPPED: requested 1, GMODE returned 2 (FAIL)
#  uname -mrs
NetBSD 11.99.8 news68k
# 

>Fix:

Clear not only SCR_GRAPHICS but also SCR_DUMBFB in both
wsdisplayclose() and wsdisplay_internal_ioctl()?

https://nxr.netbsd.org/xref/src/sys/dev/wscons/wsdisplay.c?r=1.167#1111
```
   1072 wsdisplayclose(dev_t dev, int flag, int mode, struct lwp *l)

   1110 	if (WSSCREEN_HAS_EMULATOR(scr)) {
   1111 		scr->scr_flags &= ~SCR_GRAPHICS;
```

https://nxr.netbsd.org/xref/src/sys/dev/wscons/wsdisplay.c?r=1.167#1364
```
   1313 wsdisplay_internal_ioctl(struct wsdisplay_softc *sc, struct wsscreen *scr,
   1314 	u_long cmd, void *data, int flag, struct lwp *l)

   1363 	    if (WSSCREEN_HAS_EMULATOR(scr)) {
   1364 		    scr->scr_flags &= ~SCR_GRAPHICS;
   1365 		    if (d == WSDISPLAYIO_MODE_MAPPED ||
   1366 			d == WSDISPLAYIO_MODE_DUMBFB)
   1367 			    scr->scr_flags |= SCR_GRAPHICS |
   1368 				    ((d == WSDISPLAYIO_MODE_DUMBFB) ? SCR_DUMBFB : 0);
   1369 	    } else if (d == WSDISPLAYIO_MODE_EMUL)
   1370 		    return EINVAL;
```

---
Izumi Tsutsui




Home | Main Index | Thread Index | Old Index