[RFC] new APIs to use wskbd(4) input on non-wsdisplay tty devices
# 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 - 1.143 +++ sys/dev/wscons/wskbd.c 6 Apr 2024 06:59:50 - @@ -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/wsc
Re: [RFC] new APIs to use wskbd(4) input on non-wsdisplay tty devices
On Sat, Apr 06, 2024 at 23:56:27 +0900, Izumi Tsutsui wrote: > To support "text only" framebuffer console, we can use putchar > functions provided by the firmware PROM. Is that a console-typewriter--like device without addressable cursor terminal emulation? Can you use wsemul_dumb to avoid rasops &c? It still uses copy/erase, but with trivial argument values that can be reversed back to puchar calls for tab/lf (from a very quick look). > 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. AFAIU, there's nothing console-specific in this (except that it's first use is going to be for a console), so may be it would be better to drop the "consdev" from the name? > 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.c5 Feb 2019 10:04:49 - 1.143 > +++ sys/dev/wscons/wskbd.c6 Apr 2024 06:59:50 - [...] > @@ -706,6 +709,24 @@ wskbd_input(device_t dev, u_int type, in > } > #endif > > +#if NWSDISPLAY == 0 > + if (sc->sc_translating) { The #endif above is for NWSDISPLAY > 0, so may be get rid of the ifdefs and use plain ifs? Thanks. -uwe
Re: [RFC] new APIs to use wskbd(4) input on non-wsdisplay tty devices
Hello, On Sat, 6 Apr 2024 23:56:27 +0900 Izumi Tsutsui wrote: > 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. You can use wsdisplay without rasops or a mappable framebuffer. Examples would be things like newport or crmfb on sgimips. > To support "text only" framebuffer console, we can use putchar > functions provided by the firmware PROM. Does it let you draw characters wherever you want with colours of inverse attrubute? If so, that's enough for wsdisplay - sti on hppa does just that. have fun Michael
Re: [RFC] new APIs to use wskbd(4) input on non-wsdisplay tty devices
uwe@ wrote: > On Sat, Apr 06, 2024 at 23:56:27 +0900, Izumi Tsutsui wrote: > > > To support "text only" framebuffer console, we can use putchar > > functions provided by the firmware PROM. > > Is that a console-typewriter--like device without addressable cursor > terminal emulation? Can you use wsemul_dumb to avoid rasops &c? It > still uses copy/erase, but with trivial argument values that can be > reversed back to puchar calls for tab/lf (from a very quick look). The PROM provides (at least I can use) only a "putchar()" function. No other framebuffer ops like bitblt. For now I cannot find any proper implementation example in such case.. > > 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. > > AFAIU, there's nothing console-specific in this (except that it's > first use is going to be for a console), so may be it would be better > to drop the "consdev" from the name? Hmm. Actually it is not a "console" device (by sys/dev/cons.c) of the kernel, but I just intended it as a "screen console (not a serial one)". What name should we use in such case? dispdev? scrndev? putchar? "wskbd_ttyinput_register()" and "ttydev" (for members) or something? > > 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 - 1.143 > > +++ sys/dev/wscons/wskbd.c 6 Apr 2024 06:59:50 - > [...] > > @@ -706,6 +709,24 @@ wskbd_input(device_t dev, u_int type, in > > } > > #endif > > > > +#if NWSDISPLAY == 0 > > + if (sc->sc_translating) { > > The #endif above is for NWSDISPLAY > 0, so may be get rid of the > ifdefs and use plain ifs? It looks wskbd(9) assumes always attached to wsdisplay(9) (ttyE?) if wsdisplay(4) is configured (in the above #if NWSDISPLAY >0 block) even if no wsdisplay(4) devices are actually attached. In my news68k case, I thought we should not override the current assumptions even in the wskbd_consdev_kbdinput_register() case. I have a feeling we should have separate 'if (sc->sc_translating)' blocks for both case. Maybe we can simply use #else like: #if NWSDISPLAY > 0 [send kbd inputs to wsdisplay_kbdinput() and return unconditionally] #else [send kbd inputs to sc_consdev_kbdinput() and return if it's registered] #endif Thanks, --- Izumi Tsutsui
Re: [RFC] new APIs to use wskbd(4) input on non-wsdisplay tty devices
On Sat, Apr 06, 2024 at 11:56:27PM +0900, Izumi Tsutsui wrote: > > 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. Wouldn't a tty be a better abstraction for this? Lots of minicomputers had incredibly dumb serial consoles.
Re: [RFC] new APIs to use wskbd(4) input on non-wsdisplay tty devices
On Fri, Apr 12, 2024 at 09:13:17AM -0400, Thor Lancelot Simon wrote: > On Sat, Apr 06, 2024 at 11:56:27PM +0900, Izumi Tsutsui wrote: > > > > 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. > > Wouldn't a tty be a better abstraction for this? Lots of minicomputers > had incredibly dumb serial consoles. I think the above is not clear. To rephrase my question: what is the wscons layer actually adding here? Would it not be simpler to interface at the tty layer instead? Thor
Re: [RFC] new APIs to use wskbd(4) input on non-wsdisplay tty devices
tls@ wrote: > On Fri, Apr 12, 2024 at 09:13:17AM -0400, Thor Lancelot Simon wrote: > > On Sat, Apr 06, 2024 at 11:56:27PM +0900, Izumi Tsutsui wrote: > > > > > > 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. > > > > Wouldn't a tty be a better abstraction for this? Lots of minicomputers > > had incredibly dumb serial consoles. > > I think the above is not clear. To rephrase my question: what is the > wscons layer actually adding here? Would it not be simpler to interface > at the tty layer instead? - The tty layer requires both getchar() and putchar(). - For a glass console, completely different two drivers are necessary, i.e. keyboard driver for getchar() and display driver for putchar(). - On news68k, it's not easy to implement framebuffer driver due to lack of information, but we can use a putchar() function provided by a NEWS PROM firmware because it also supports VT emulation. - On the other hand, we cannot use getchar() function provided by a NEWS PROM firmware for useland because it uses busy loop to wait keyboard input. But we already has a wskbd driver for NEWS machines. - So I would like propose adding APIs "to use wskbd driver just for keyboard inputs" for non-wscons(4) tty drivers See sys/arch/sun3/dev/kd.c for another example that use "PROM function for putchar() to display and sys/dev/sun/kbd.c via zs(4) for getchar() from keyboard". https://github.com/NetBSD/src/blob/6053b8d/sys/arch/sun3/dev/kd.c --- static void kdstart(struct tty *tp) { struct clist *cl; int s1, s2; s1 = splsoftclock(); s2 = spltty(); if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT)) goto out; cl = &tp->t_outq; if (ttypull(tp)) { if (kd_is_console) { tp->t_state |= TS_BUSY; if ((s1 & PSL_IPL) == 0) { /* called at level zero - update screen now. */ splx(s2); kd_putfb(tp); [...] } [...] /* * Put text on the screen using the PROM monitor. * This can take a while, so to avoid missing * interrupts, this is called at splsoftclock. */ static void kd_putfb(struct tty *tp) { char buf[PUT_WSIZE]; struct clist *cl = &tp->t_outq; char *p, *end; int len; while ((len = q_to_b(cl, buf, PUT_WSIZE-1)) > 0) { /* PROM will barf if high bits are set. */ p = buf; end = buf + len; while (p < end) *p++ &= 0x7f; (romVectorPtr->fbWriteStr)(buf, len); } } [...] /* * Our "interrupt" routine for input. This is called by * the keyboard driver (dev/sun/kbd.c) at spltty. */ void kd_cons_input(int c) { struct kd_softc *kd = &kd_softc; struct tty *tp; /* XXX: Make sure the device is open. */ tp = kd->kd_tty; if (tp == NULL) return; if ((tp->t_state & TS_ISOPEN) == 0) return; (*tp->t_linesw->l_rint)(c, tp); } --- sys/arch/news68k/news68k/romcons.c has the similar implementation: https://github.com/tsutsui/netbsd-src/blob/c74b64a/sys/arch/news68k/news68k/romcons.c --- static void romcons_start(struct tty *tp) { int s, len; uint8_t buf[BURSTLEN]; s = spltty(); if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { splx(s); return; } tp->t_state |= TS_BUSY; splx(s); len = q_to_b(&tp->t_outq, buf, BURSTLEN); s = splhigh(); rom_write(1, buf, len); splx(s); s = spltty(); tp->t_state &= ~TS_BUSY; if (ttypull(tp)) { tp->t_state |= TS_TIMEOUT; callout_schedule(&tp->t_rstrt_ch, 1); } splx(s); } [...] #if NWSKBD > 0 static void romcons_kbdinput(device_t self, int ks) { struct romcons_softc *sc = device_private(self); struct tty *tp; KASSERT(sc != NULL); tp = sc->sc_tty; if (tp && (tp->t_state & TS_ISOPEN)) (*tp->t_linesw->l_rint)(ks, tp); } #endif --- Izumi Tsutsui