# tl;dr I'd like to add new APIs to use wskbd(4) input on non-wsdisplay tty devices, especially news68k that can use a putchar function provided by firmware PROM as a kernel console device.
# Details The news68k machines have various framebuffer options, but most of them are not "dumb" framebuffer that can be handled by raspos(9) but some of them have own processors (68000 etc.) to handle various acceleration etc. so it's difficult to implement framebuffer drivers. To support "text only" framebuffer console, we can use putchar functions provided by the firmware PROM. However, to use getchar() functions we cannot use getchar provided by PROM because it always stalls until any key is pressed. NetBSD/sun3 has the similar framework in sys/arch/sun3/dev/kd.c, i.e. it uses a PROM function for putchar but use own keyboard driver (sys/dev/sun/kbd.c) to handle kernel console. I'd like to implement the similar framework on NetBSD/news68k. news68k port already has wskbd driver (delived from newsmips port), but currently a design of wskbd(9) assumes always it used with wsdisplay(9) tty (i.e. ttyE?) device and there is no API to use wskbd(9) input for other drivers than wsdisplay(9). The attached patch provides new two APIs - wskbd_consdev_kbdinput_register() - wskbd_consdev_kbdinput_deregister() to allow a kernel to use wskbd(9) for non-wsdisplay tty device. Once "sc_consdev_kbdinput()" callback funtion is registered via the wskbd_consdev_kbdinput_register() by the MD attachment, MI wskbd(9) just puts the input data from wskbd(9) to the callback fundtions, if NWSDISPLAY is not configured. I think the change is minimum and it doesn't break any existing ports that use wsdisplay(9) ttys, but I'd like to call for comments about these implementation design. Supporting non-serial console on news68k port has been in my TODO list for ~20 years so I'd like to commit this if there is no particular objection. There is a video of NetBSD/news68k 9.3 with the similar patch: https://www.youtube.com/watch?v=kPOiHG20Ye8 Index: sys/dev/wscons/wskbd.c =================================================================== RCS file: /cvsroot/src/sys/dev/wscons/wskbd.c,v retrieving revision 1.143 diff -u -p -d -r1.143 wskbd.c --- sys/dev/wscons/wskbd.c 5 Feb 2019 10:04:49 -0000 1.143 +++ sys/dev/wscons/wskbd.c 6 Apr 2024 06:59:50 -0000 @@ -214,6 +214,9 @@ struct wskbd_softc { /* optional table to translate scancodes in event mode */ int sc_evtrans_len; keysym_t *sc_evtrans; + + wskbd_consdev_kbdinput *sc_consdev_kbdinput; + device_t sc_consdev; }; #define MOD_SHIFT_L (1 << 0) @@ -420,6 +423,8 @@ wskbd_attach(device_t parent, device_t s sc->sc_hotkeycookie = NULL; sc->sc_evtrans_len = 0; sc->sc_evtrans = NULL; + sc->sc_consdev_kbdinput = NULL; + sc->sc_consdev = NULL; #if NWSMUX > 0 || NWSDISPLAY > 0 sc->sc_base.me_ops = &wskbd_srcops; @@ -664,9 +669,7 @@ void wskbd_input(device_t dev, u_int type, int value) { struct wskbd_softc *sc = device_private(dev); -#if NWSDISPLAY > 0 int num, i; -#endif if (sc->sc_repeating) { sc->sc_repeating = 0; @@ -706,6 +709,24 @@ wskbd_input(device_t dev, u_int type, in } #endif +#if NWSDISPLAY == 0 + if (sc->sc_translating) { + keysym_t ks; + + if (sc->sc_consdev_kbdinput) { + num = wskbd_translate(sc->id, type, value); + for (i = 0; i < num; i++) { + ks = sc->id->t_symbols[i]; + if (KS_GROUP(ks) == KS_GROUP_Plain && + KS_VALUE(ks) <= 0x7f) + (*sc->sc_consdev_kbdinput)( + sc->sc_consdev, KS_VALUE(ks)); + } + return; + } + } +#endif + wskbd_deliver_event(sc, type, value); #if defined(WSKBD_EVENT_AUTOREPEAT) @@ -1683,6 +1704,36 @@ wskbd_hotkey_deregister(device_t self) sc->sc_hotkeycookie = NULL; } +device_t +wskbd_consdev_kbdinput_register(device_t self, wskbd_consdev_kbdinput *kifn, + device_t cons_dv) +{ + struct wskbd_softc *sc = device_private(self); + + if (sc == NULL) + return NULL; + + if (kifn == NULL) + return NULL; + + sc->sc_consdev_kbdinput = kifn; + sc->sc_consdev = cons_dv; + aprint_verbose_dev(self, "connecting to %s\n", device_xname(cons_dv)); + + return sc->sc_base.me_dv; +} + +void +wskbd_consdev_kbdinput_deregister(device_t self) +{ + struct wskbd_softc *sc = device_private(self); + + KASSERT(sc != NULL); + + sc->sc_consdev_kbdinput = NULL; + sc->sc_consdev = NULL; +} + static int wskbd_translate(struct wskbd_internal *id, u_int type, int value) { Index: sys/dev/wscons/wskbdvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/wscons/wskbdvar.h,v retrieving revision 1.19 diff -u -p -d -r1.19 wskbdvar.h --- sys/dev/wscons/wskbdvar.h 2 Sep 2012 21:14:56 -0000 1.19 +++ sys/dev/wscons/wskbdvar.h 6 Apr 2024 06:59:50 -0000 @@ -104,6 +104,14 @@ device_t wskbd_hotkey_register(device_t, void wskbd_hotkey_deregister(device_t); /* + * Callbacks from the keyboard driver to non-wscons console drivers. + */ +typedef void (wskbd_consdev_kbdinput)(device_t, int); +device_t wskbd_consdev_kbdinput_register(device_t, wskbd_consdev_kbdinput *, + device_t); +void wskbd_consdev_kbdinput_deregister(device_t); + +/* * set a translation table for scancodes in event mode * parameters are a pointer to the table and its length * pass length zero to turn translation off Index: sys/arch/news68k/conf/GENERIC =================================================================== RCS file: /cvsroot/src/sys/arch/news68k/conf/GENERIC,v retrieving revision 1.133 diff -u -p -d -r1.133 GENERIC --- sys/arch/news68k/conf/GENERIC 26 Apr 2019 21:40:31 -0000 1.133 +++ sys/arch/news68k/conf/GENERIC 6 Apr 2024 06:59:50 -0000 @@ -202,7 +202,7 @@ ss* at scsibus? target ? lun ? # SCSI s uk* at scsibus? target ? lun ? # unknown SCSI devices # PROM console support -#romcons0 at mainbus0 +romcons0 at mainbus0 # # accept filters Index: sys/arch/news68k/conf/INSTALL =================================================================== RCS file: /cvsroot/src/sys/arch/news68k/conf/INSTALL,v retrieving revision 1.65.4.1 diff -u -p -d -r1.65.4.1 INSTALL --- sys/arch/news68k/conf/INSTALL 10 Feb 2020 18:28:33 -0000 1.65.4.1 +++ sys/arch/news68k/conf/INSTALL 6 Apr 2024 06:59:50 -0000 @@ -134,7 +134,7 @@ st* at scsibus? target ? lun ? # SCSI t cd* at scsibus? target ? lun ? # SCSI CD-ROMs # PROM console support -#romcons0 at mainbus0 +romcons0 at mainbus0 # Misc. pseudo-device bpfilter # Berkeley Packet Filter Index: sys/arch/news68k/news68k/romcons.c =================================================================== RCS file: /cvsroot/src/sys/arch/news68k/news68k/romcons.c,v retrieving revision 1.3 diff -u -p -d -r1.3 romcons.c --- sys/arch/news68k/news68k/romcons.c 25 Jul 2014 08:10:34 -0000 1.3 +++ sys/arch/news68k/news68k/romcons.c 6 Apr 2024 06:59:50 -0000 @@ -37,6 +37,8 @@ #include <sys/cdefs.h> __KERNEL_RCSID(0, "$NetBSD: romcons.c,v 1.3 2014/07/25 08:10:34 dholland Exp $"); +#include "wskbd.h" + #include <sys/param.h> #include <sys/conf.h> #include <sys/device.h> @@ -47,6 +49,9 @@ __KERNEL_RCSID(0, "$NetBSD: romcons.c,v #include <sys/kauth.h> #include <dev/cons.h> +#if NWSKBD > 0 +#include <dev/wscons/wskbdvar.h> +#endif #include <machine/autoconf.h> #include <machine/romcall.h> @@ -59,6 +64,8 @@ struct romcons_softc { struct callout sc_poll_ch; int sc_flags; #define CONS_POLL 1 + + device_t sc_kbdinput_dv; }; #define BURSTLEN 128 /* max number of bytes to write in one chunk */ @@ -79,7 +86,10 @@ dev_type_ioctl(romcons_ioctl); dev_type_tty(romcons_tty); dev_type_poll(romcons_poll); -void romcons_kbdinput(int); +#if NWSKBD > 0 +static void romcons_attach_deferred(device_t); +static void romcons_kbdinput(device_t, int); +#endif const struct cdevsw romcons_cdevsw = { .d_open = romcons_open, @@ -129,8 +139,35 @@ romcons_attach(device_t parent, device_t aprint_normal("\n"); callout_init(&sc->sc_poll_ch, 0); + +#if NWSKBD > 0 + config_defer(self, romcons_attach_deferred); +#endif } +#if NWSKBD > 0 +static void +romcons_attach_deferred(device_t self) +{ + struct romcons_softc *sc; + device_t wskbd_dev; + + sc = device_private(self); + KASSERT(sc != NULL); + + /* XXX assume only one keyboard at wskbd0 */ + wskbd_dev = device_lookup(&wskbd_cd, 0); + if (wskbd_dev == NULL) { + aprint_error_dev(self, "no wskbd0 is attached\n"); + return; + } + + /* attach wskbd hook for tty(4) of userland processes */ + sc->sc_kbdinput_dv = + wskbd_consdev_kbdinput_register(wskbd_dev, romcons_kbdinput, self); +} +#endif + static void romcons_start(struct tty *); static int romcons_param(struct tty *, struct termios *); static void romcons_pollin(void *); @@ -294,17 +331,19 @@ romcons_pollin(void *aux) callout_reset(&sc->sc_poll_ch, 1, romcons_pollin, sc); } -void -romcons_kbdinput(int ks) +#if NWSKBD > 0 +static void +romcons_kbdinput(device_t self, int ks) { - struct romcons_softc *sc; + struct romcons_softc *sc = device_private(self); struct tty *tp; - sc = device_lookup_private(&romcons_cd, 0); + KASSERT(sc != NULL); tp = sc->sc_tty; if (tp && (tp->t_state & TS_ISOPEN)) (*tp->t_linesw->l_rint)(ks, tp); } +#endif void romcons_cnprobe(struct consdev *cd) --- Thanks, --- Izumi Tsutsui