Subject: Fix kd driver (kdcngetc/kdcnputc functions)
To: None <hls@oce.nl, port-sun3@netbsd.org>
From: Gordon W. Ross <gwr@jericho.mc.com>
List: port-sun3
Date: 12/17/1994 15:10:32
> > Besides this I have the following minor problem:
> >
> > Pressing 'L1-A' drops me into the debugger.
> >
> > Stopped at _Debugger+0x6: unlk a6
> > db>
> >
> > At this point NetBSD doesn't respond to any keys pressed on
> > the keyboard!
>
> Ugh. I'm not sure this ever worked. In sun3/dev/kd.c there is a
> kdcngetc routine that tries to use the PROM to read the keyboard
> (cheat) and the PROM quite likely requires the clock interupts at
> level 7 (NMI) enabled to poll the keyboard. The "right" way to
> fix it is make kdcngetc poll just like zs.c:zscngetc() to get a
> scan code, then translate it (as done by kbd.c) then return it.
>
> > When I start NetBSD with -d, this also gets me into the debugger.
> > In this case everything works fine!
> Really! You mean, later L1-A then works correctly? Hmmmm...
I tried this out, and just as you say, it was broken. The PROM
can not read the console unless the NMI clock is turned on...
Here's a fix:
diff -rc sun3.orig/dev/kbd.c sun3/dev/kbd.c
*** sun3.orig/dev/kbd.c Thu Dec 15 06:20:07 1994
--- sun3/dev/kbd.c Sat Dec 17 03:41:46 1994
***************
*** 208,213 ****
--- 208,214 ----
void (*k_open) __P((struct tty *)); /* enable dataflow */
void (*k_close) __P((struct tty *)); /* disable dataflow */
int k_evmode; /* set if we should produce events */
+ int k_isopen; /* set if open has been done */
struct kbd_state k_state; /* ASCII decode state */
struct evvar k_events; /* event queue state */
} kbd_softc;
***************
*** 215,223 ****
/* Prototypes */
void kbd_ascii(struct tty *);
void kbd_serial(struct tty *, void (*)(), void (*)());
! int kbd_init(void);
! void kbd_reset(struct kbd_state *);
! static int kbd_translate(int, struct kbd_state *);
void kbd_rint(int);
int kbdopen(dev_t, int, int, struct proc *);
int kbdclose(dev_t, int, int, struct proc *);
--- 216,224 ----
/* Prototypes */
void kbd_ascii(struct tty *);
void kbd_serial(struct tty *, void (*)(), void (*)());
! int kbd_iopen(void);
! void kbd_reset(struct kbd_softc *);
! int kbd_translate(int);
void kbd_rint(int);
int kbdopen(dev_t, int, int, struct proc *);
int kbdclose(dev_t, int, int, struct proc *);
***************
*** 228,233 ****
--- 229,250 ----
int kbd_docmd(int, int);
/*
+ * Initialization done by either kdcninit or kbd_iopen
+ */
+ void
+ kbd_init_tables()
+ {
+ struct kbd_state *ks;
+
+ ks = &kbd_softc.k_state;
+ if (ks->kbd_cur == NULL) {
+ ks->kbd_cur = kbd_unshifted;
+ ks->kbd_unshifted = kbd_unshifted;
+ ks->kbd_shifted = kbd_shifted;
+ }
+ }
+
+ /*
* Attach the console keyboard ASCII (up-link) interface.
* This is called by the "kd" (keyboard/display) driver to
* tell this module where to send read-side data.
***************
*** 253,259 ****
k->k_open = iopen;
k->k_close = iclose;
! /* Now attach the Keyboard/Display (kd) pseudo-driver. */
kd_attach(1); /* This calls kbd_ascii() */
}
--- 270,279 ----
k->k_open = iopen;
k->k_close = iclose;
! /* Do this before any calls to kbd_rint(). */
! kbd_init_tables();
!
! /* Now attach the (kd) pseudo-driver. */
kd_attach(1); /* This calls kbd_ascii() */
}
***************
*** 262,276 ****
* This is called from kbdopen or kdopen (in kd.c)
*/
int
! kbd_init()
{
! register struct kbd_softc *k;
int error, s;
k = &kbd_softc;
/* Tolerate extra calls. */
! if (k->k_state.kbd_cur)
return (0);
/* Make sure "down" link (to zs1a) is established. */
--- 282,296 ----
* This is called from kbdopen or kdopen (in kd.c)
*/
int
! kbd_iopen()
{
! struct kbd_softc *k;
int error, s;
k = &kbd_softc;
/* Tolerate extra calls. */
! if (k->k_isopen)
return (0);
/* Make sure "down" link (to zs1a) is established. */
***************
*** 285,297 ****
(void) ttyoutput(KBD_CMD_RESET, k->k_kbd);
(*k->k_kbd->t_oproc)(k->k_kbd);
/* The wakeup for this sleep is in kbd_reset(). */
! error = tsleep((caddr_t)&kbd_softc.k_state, PZERO | PCATCH,
devopn, hz);
! if (error == EWOULDBLOCK) /* no response */
! error = ENXIO;
if (error == 0)
! k->k_state.kbd_cur = kbd_unshifted;
splx(s);
return error;
--- 305,319 ----
(void) ttyoutput(KBD_CMD_RESET, k->k_kbd);
(*k->k_kbd->t_oproc)(k->k_kbd);
/* The wakeup for this sleep is in kbd_reset(). */
! error = tsleep((caddr_t)k, PZERO | PCATCH,
devopn, hz);
! if (error == EWOULDBLOCK) { /* no response */
! printf("keyboard not responding\n");
! error = EIO;
! }
if (error == 0)
! k->k_isopen = 1;
splx(s);
return error;
***************
*** 298,315 ****
}
void
! kbd_reset(register struct kbd_state *ks)
{
/*
* On first identification, wake up anyone waiting for type
* and set up the table pointers.
*/
! if (ks->kbd_unshifted == NULL) {
! wakeup((caddr_t)ks);
! ks->kbd_unshifted = kbd_unshifted;
! ks->kbd_shifted = kbd_shifted;
! ks->kbd_cur = ks->kbd_unshifted;
! }
/* Restore keyclick, if necessary */
switch (ks->kbd_id) {
--- 320,338 ----
}
void
! kbd_reset(k)
! struct kbd_softc *k;
{
+ struct kbd_state *ks;
+
+ ks = &k->k_state;
+
/*
* On first identification, wake up anyone waiting for type
* and set up the table pointers.
*/
! if (k->k_isopen == 0)
! wakeup((caddr_t)k);
/* Restore keyclick, if necessary */
switch (ks->kbd_id) {
***************
*** 335,345 ****
/*
* Turn keyboard up/down codes into ASCII.
*/
! static int
! kbd_translate(register int c, register struct kbd_state *ks)
{
register int down;
if (ks->kbd_cur == NULL) {
/*
* Do not know how to translate yet.
--- 358,370 ----
/*
* Turn keyboard up/down codes into ASCII.
*/
! int
! kbd_translate(register int c)
{
+ register struct kbd_state *ks;
register int down;
+ ks = &kbd_softc.k_state;
if (ks->kbd_cur == NULL) {
/*
* Do not know how to translate yet.
***************
*** 420,426 ****
if (k->k_state.kbd_takeid) {
k->k_state.kbd_takeid = 0;
k->k_state.kbd_id = c;
! kbd_reset(&k->k_state);
return;
}
--- 445,451 ----
if (k->k_state.kbd_takeid) {
k->k_state.kbd_takeid = 0;
k->k_state.kbd_id = c;
! kbd_reset(k);
return;
}
***************
*** 437,443 ****
* open and we do not know its type.
*/
if (!k->k_evmode) {
! c = kbd_translate(c, &k->k_state);
if (c >= 0 && k->k_cons != NULL)
ttyinput(c, k->k_cons);
return;
--- 462,468 ----
* open and we do not know its type.
*/
if (!k->k_evmode) {
! c = kbd_translate(c);
if (c >= 0 && k->k_cons != NULL)
ttyinput(c, k->k_cons);
return;
***************
*** 481,487 ****
return (EBUSY);
kbd_softc.k_events.ev_io = p;
! if ((error = kbd_init()) != 0) {
kbd_softc.k_events.ev_io = NULL;
return (error);
}
--- 506,512 ----
return (EBUSY);
kbd_softc.k_events.ev_io = p;
! if ((error = kbd_iopen()) != 0) {
kbd_softc.k_events.ev_io = NULL;
return (error);
}
diff -rc sun3.orig/dev/kd.c sun3/dev/kd.c
*** sun3.orig/dev/kd.c Thu Dec 15 06:20:07 1994
--- sun3/dev/kd.c Sat Dec 17 03:39:00 1994
***************
*** 90,97 ****
if (tp == NULL)
return ENXIO;
! if ((error = kbd_init()) != 0)
return (error);
tp->t_oproc = kdstart;
tp->t_param = kdparam;
--- 90,101 ----
if (tp == NULL)
return ENXIO;
! if ((error = kbd_iopen()) != 0) {
! #ifdef DIAGNOSTIC
! printf("kd: kbd_iopen, error=%d\n", error);
! #endif
return (error);
+ }
tp->t_oproc = kdstart;
tp->t_param = kdparam;
***************
*** 232,242 ****
/*
* kd console support
- *
- * XXX - Using prom routines for now...
*/
! extern int zscnprobe_kbd();
kdcnprobe(cp)
struct consdev *cp;
--- 236,244 ----
/*
* kd console support
*/
! extern int zscnprobe_kbd(), zscngetc(), kbd_translate();
kdcnprobe(cp)
struct consdev *cp;
***************
*** 256,261 ****
--- 258,270 ----
kdcninit(cp)
struct consdev *cp;
{
+
+ /* This prepares zscngetc() */
+ zs_set_conschan(1, 0);
+
+ /* This prepares kbd_translate() */
+ kbd_init_tables();
+
mon_printf("console on kd0 (keyboard/display)\n");
}
***************
*** 262,277 ****
kdcngetc(dev)
dev_t dev;
{
! int c, s;
! /* XXX - Does mon_may_getchar() require the NMI clock? */
! s = splhigh();
! do c = mon_may_getchar();
! while (c < 0);
! splx(s);
- if (c == '\r')
- c = '\n';
return (c);
}
--- 271,283 ----
kdcngetc(dev)
dev_t dev;
{
! int c;
! do {
! c = zscngetc(0);
! c = kbd_translate(c);
! } while (c == -1);
return (c);
}
diff -rc sun3.orig/dev/zs.c sun3/dev/zs.c
*** sun3.orig/dev/zs.c Thu Dec 15 06:20:09 1994
--- sun3/dev/zs.c Sat Dec 17 02:54:50 1994
***************
*** 457,476 ****
return (zscnprobe(cn, 1));
}
! /* Attach as console. Also set zs_conschan */
! int
! zscninit(struct consdev *cn)
{
- int unit;
volatile struct zsdevice *addr;
! unit = minor(cn->cn_dev) & 1;
! addr = zsaddr[0];
! zs_conschan = ((unit == 0) ?
&addr->zs_chan[CHAN_A] :
&addr->zs_chan[CHAN_B] );
! mon_printf("console on zs0 (tty%c)\n", unit + 'a');
}
--- 457,482 ----
return (zscnprobe(cn, 1));
}
! /* Called by kdcninit() or below. */
! void
! zs_set_conschan(unit, ab)
! int unit, ab;
{
volatile struct zsdevice *addr;
! addr = zsaddr[unit];
! zs_conschan = ((ab == 0) ?
&addr->zs_chan[CHAN_A] :
&addr->zs_chan[CHAN_B] );
+ }
! /* Attach as console. Also set zs_conschan */
! int
! zscninit(struct consdev *cn)
! {
! int ab = minor(cn->cn_dev) & 1;
! zs_set_conschan(0, ab);
! mon_printf("console on zs0 (tty%c)\n", 'a' + ab);
}
***************
*** 498,503 ****
--- 504,514 ----
ZS_DELAY();
splx(s);
+
+ /*
+ * This is used by the kd driver to read scan codes,
+ * so don't translate '\r' ==> '\n' here...
+ */
return (c);
}