summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-08-25 19:16:37 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-08-25 19:16:37 +0000
commitdcac4981327d5f2226b4ad42521261acedea253d (patch)
tree8c150797c17decccaede74d6b2de4b3f21ba25b3
parent5f8c06662258b3f3472b38b0a6d4fba9e519c4a0 (diff)
Legacy-free PC hardware do not have a real PS/2 keyboard controller, but
rather have the USB HCI emulate it during boot, while legacy mode is enabled. This causes pckbd0 to attach as the console device, but is lost as soon as the USB HCI driver attaches. The disappearance of the emulated PS/2 controller can however be detected in pckbc(4) - which is supposed to attach after [eou]hci(4), with the controller refusing to ack commands and replying ``please resend'' instead. In that case, the kernel will now no longer attach pckbd, and will perform a new console input device selection, allowing the (real) usb keyboard to become the console. Thanks to krw@ for countless tests on legacy-free hardware; also tested on more conventional hardware by naddy@ and I. Only amd64 and i386 platforms are affected by this change.
-rw-r--r--sys/arch/amd64/amd64/wscons_machdep.c107
-rw-r--r--sys/arch/i386/i386/wscons_machdep.c106
-rw-r--r--sys/dev/ic/pckbc.c37
-rw-r--r--sys/dev/pckbc/pckbd.c12
4 files changed, 189 insertions, 73 deletions
diff --git a/sys/arch/amd64/amd64/wscons_machdep.c b/sys/arch/amd64/amd64/wscons_machdep.c
index a5fb88593bc..0ada759ddb5 100644
--- a/sys/arch/amd64/amd64/wscons_machdep.c
+++ b/sys/arch/amd64/amd64/wscons_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wscons_machdep.c,v 1.7 2008/07/16 20:03:22 miod Exp $ */
+/* $OpenBSD: wscons_machdep.c,v 1.8 2009/08/25 19:16:34 miod Exp $ */
/*
* Copyright (c) 2001 Aaron Campbell
@@ -68,12 +68,16 @@
#endif
#include "pckbd.h"
#include "ukbd.h"
-#if (NPCKBD > 0) || (NUKBD > 0)
-#include <dev/wscons/wskbdvar.h>
-#endif
#if (NUKBD > 0)
#include <dev/usb/ukbdvar.h>
#endif
+#include "wskbd.h"
+#if NWSKBD > 0
+#include <dev/wscons/wskbdvar.h>
+#endif
+
+void wscn_video_init(void);
+void wscn_input_init(int);
cons_decl(ws);
@@ -100,39 +104,14 @@ wscnprobe(struct consdev *cp)
void
wscninit(struct consdev *cp)
{
- static int initted;
+ static int initted = 0;
if (initted)
return;
-
initted = 1;
-#if (NVGA > 0) || (NEGA > 0) || (NPCDISPLAY > 0)
-#if (NVGA > 0)
- if (!vga_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM, -1, 1))
- goto dokbd;
-#endif
-#if (NEGA > 0)
- if (!ega_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM))
- goto dokbd;
-#endif
-#if (NPCDISPLAY > 0)
- if (!pcdisplay_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM))
- goto dokbd;
-#endif
- if (0) goto dokbd; /* XXX stupid gcc */
-dokbd:
-#if (NPCKBC > 0)
- if (!pckbc_cnattach(X86_BUS_SPACE_IO, IO_KBD, KBCMDP, PCKBC_KBD_SLOT,
- 0))
- return;
-#endif
-#if (NUKBD > 0)
- if (!ukbd_cnattach())
- return;
-#endif
-#endif /* VGA | EGA | PCDISPLAY */
- return;
+ wscn_video_init();
+ wscn_input_init(0);
}
void
@@ -152,3 +131,67 @@ wscnpollc(dev_t dev, int on)
{
wskbd_cnpollc(dev, on);
}
+
+/*
+ * Configure the display part of the console.
+ */
+void
+wscn_video_init()
+{
+#if (NVGA > 0)
+ if (vga_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM, -1, 1) == 0)
+ return;
+#endif
+#if (NEGA > 0)
+ if (ega_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM) == 0)
+ return;
+#endif
+#if (NPCDISPLAY > 0)
+ if (pcdisplay_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM) == 0)
+ return;
+#endif
+}
+
+/*
+ * Configure the keyboard part of the console.
+ * This is tricky, because of the games USB controllers play.
+ *
+ * On a truly legacy-free design, no PS/2 keyboard controller will be
+ * found, so we'll settle for the first USB keyboard as the console
+ * input device.
+ *
+ * Otherwise, the PS/2 controller will claim console, even if no PS/2
+ * keyboard is plugged into it. This is intentional, so that a PS/2
+ * keyboard can be plugged late (even though this is theoretically not
+ * allowed, most PS/2 controllers survive this).
+ *
+ * However, if there isn't any PS/2 keyboard connector, but an USB
+ * controller in Legacy mode, the kernel will detect a PS/2 keyboard
+ * connected (while there really isn't any), until the USB controller
+ * driver attaches. At that point the ghost of the legacy keyboard
+ * flees away.
+ *
+ * The pckbc(4) driver will, however, detect that the keyboard is gone
+ * missing, and will invoke this function again, allowing a new console
+ * input device choice.
+ */
+
+void
+wscn_input_init(int pass)
+{
+ if (pass != 0) {
+#if NWSKBD > 0
+ wskbd_cndetach();
+#endif
+ }
+
+#if (NPCKBC > 0)
+ if (pass == 0 && pckbc_cnattach(X86_BUS_SPACE_IO, IO_KBD, KBCMDP,
+ PCKBC_KBD_SLOT, 0) == 0)
+ return;
+#endif
+#if (NUKBD > 0)
+ if (ukbd_cnattach() == 0)
+ return;
+#endif
+}
diff --git a/sys/arch/i386/i386/wscons_machdep.c b/sys/arch/i386/i386/wscons_machdep.c
index 79f1c6aef55..31648cbb9b6 100644
--- a/sys/arch/i386/i386/wscons_machdep.c
+++ b/sys/arch/i386/i386/wscons_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wscons_machdep.c,v 1.15 2008/07/16 20:03:22 miod Exp $ */
+/* $OpenBSD: wscons_machdep.c,v 1.16 2009/08/25 19:16:36 miod Exp $ */
/*
* Copyright (c) 2001 Aaron Campbell
@@ -68,12 +68,16 @@
#endif
#include "pckbd.h"
#include "ukbd.h"
-#if (NPCKBD > 0) || (NUKBD > 0)
-#include <dev/wscons/wskbdvar.h>
-#endif
#if (NUKBD > 0)
#include <dev/usb/ukbdvar.h>
#endif
+#include "wskbd.h"
+#if NWSKBD > 0
+#include <dev/wscons/wskbdvar.h>
+#endif
+
+void wscn_video_init(void);
+void wscn_input_init(int);
cons_decl(ws);
@@ -100,39 +104,14 @@ wscnprobe(struct consdev *cp)
void
wscninit(struct consdev *cp)
{
- static int initted;
+ static int initted = 0;
if (initted)
return;
-
initted = 1;
-#if (NVGA > 0) || (NEGA > 0) || (NPCDISPLAY > 0)
-#if (NVGA > 0)
- if (!vga_cnattach(I386_BUS_SPACE_IO, I386_BUS_SPACE_MEM, -1, 1))
- goto dokbd;
-#endif
-#if (NEGA > 0)
- if (!ega_cnattach(I386_BUS_SPACE_IO, I386_BUS_SPACE_MEM))
- goto dokbd;
-#endif
-#if (NPCDISPLAY > 0)
- if (!pcdisplay_cnattach(I386_BUS_SPACE_IO, I386_BUS_SPACE_MEM))
- goto dokbd;
-#endif
- if (0) goto dokbd; /* XXX stupid gcc */
-dokbd:
-#if (NPCKBC > 0)
- if (!pckbc_cnattach(I386_BUS_SPACE_IO, IO_KBD, KBCMDP, PCKBC_KBD_SLOT,
- 0))
- return;
-#endif
-#if (NUKBD > 0)
- if (!ukbd_cnattach())
- return;
-#endif
-#endif /* VGA | EGA | PCDISPLAY */
- return;
+ wscn_video_init();
+ wscn_input_init(0);
}
void
@@ -152,3 +131,66 @@ wscnpollc(dev_t dev, int on)
{
wskbd_cnpollc(dev, on);
}
+
+/*
+ * Configure the display part of the console.
+ */
+void
+wscn_video_init()
+{
+#if (NVGA > 0)
+ if (vga_cnattach(I386_BUS_SPACE_IO, I386_BUS_SPACE_MEM, -1, 1) == 0)
+ return;
+#endif
+#if (NEGA > 0)
+ if (ega_cnattach(I386_BUS_SPACE_IO, I386_BUS_SPACE_MEM) == 0)
+ return;
+#endif
+#if (NPCDISPLAY > 0)
+ if (pcdisplay_cnattach(I386_BUS_SPACE_IO, I386_BUS_SPACE_MEM) == 0)
+ return;
+#endif
+}
+
+/*
+ * Configure the keyboard part of the console.
+ * This is tricky, because of the games USB controllers play.
+ *
+ * On a truly legacy-free design, no PS/2 keyboard controller will be
+ * found, so we'll settle for the first USB keyboard as the console
+ * input device.
+ *
+ * Otherwise, the PS/2 controller will claim console, even if no PS/2
+ * keyboard is plugged into it. This is intentional, so that a PS/2
+ * keyboard can be plugged late (even though this is theoretically not
+ * allowed, most PS/2 controllers survive this).
+ *
+ * However, if there isn't any PS/2 keyboard connector, but an USB
+ * controller in Legacy mode, the kernel will detect a PS/2 keyboard
+ * connected (while there really isn't any), until the USB controller
+ * driver attaches. At that point the ghost of the legacy keyboard
+ * flees away.
+ *
+ * The pckbc(4) driver will, however, detect that the keyboard is gone
+ * missing, and will invoke this function again, allowing a new console
+ * input device choice.
+ */
+void
+wscn_input_init(int pass)
+{
+ if (pass != 0) {
+#if NWSKBD > 0
+ wskbd_cndetach();
+#endif
+ }
+
+#if (NPCKBC > 0)
+ if (pass == 0 && pckbc_cnattach(I386_BUS_SPACE_IO, IO_KBD, KBCMDP,
+ PCKBC_KBD_SLOT, 0) == 0)
+ return;
+#endif
+#if (NUKBD > 0)
+ if (ukbd_cnattach() == 0)
+ return;
+#endif
+}
diff --git a/sys/dev/ic/pckbc.c b/sys/dev/ic/pckbc.c
index 58ef989ddbc..36c2599570c 100644
--- a/sys/dev/ic/pckbc.c
+++ b/sys/dev/ic/pckbc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pckbc.c,v 1.18 2008/09/10 14:01:22 blambert Exp $ */
+/* $OpenBSD: pckbc.c,v 1.19 2009/08/25 19:16:36 miod Exp $ */
/* $NetBSD: pckbc.c,v 1.5 2000/06/09 04:58:35 soda Exp $ */
/*
@@ -44,7 +44,7 @@
#include "pckbd.h"
-#if (NPCKBD > 0)
+#if NPCKBD > 0
#include <dev/pckbc/pckbdvar.h>
#endif
@@ -290,7 +290,7 @@ pckbc_attach(sc)
struct pckbc_internal *t;
bus_space_tag_t iot;
bus_space_handle_t ioh_d, ioh_c;
- int res;
+ int haskbd = 0, res;
u_char cmdbits = 0;
t = sc->id;
@@ -333,16 +333,39 @@ pckbc_attach(sc)
if (res != 0)
printf("kbc: returned %x on kbd slot test\n", res);
#endif
- if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT))
+ if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT)) {
cmdbits |= KC8_KENABLE;
+ haskbd = 1;
+ }
} else {
printf("kbc: kbd port test: %x\n", res);
return;
}
#else
- if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT))
+ if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT)) {
cmdbits |= KC8_KENABLE;
+ haskbd = 1;
+ }
#endif /* 0 */
+ if (haskbd == 0) {
+#if defined(__i386__) || defined(__amd64__)
+ /*
+ * If there is no keyboard present, yet we are the console,
+ * we might be on a legacy-free PC where the PS/2 emulated
+ * keyboard was elected as console, but went away as soon
+ * as the USB controller drivers attached.
+ *
+ * In that case, we want to release ourselves from console
+ * duties.
+ */
+ if (pckbc_console != 0) {
+ extern void wscn_input_init(int);
+
+ pckbc_console = 0;
+ wscn_input_init(1);
+ }
+#endif
+ }
/*
* Check aux port ok.
@@ -607,7 +630,7 @@ pckbc_poll_cmd1(t, slot, cmd)
#ifdef PCKBCDEBUG
printf("pckbc: cmd failed\n");
#endif
- cmd->status = EIO;
+ cmd->status = ENXIO;
return;
}
}
@@ -794,7 +817,7 @@ pckbc_cmdresponse(t, slot, data)
#ifdef PCKBCDEBUG
printf("pckbc: cmd failed\n");
#endif
- cmd->status = EIO;
+ cmd->status = ENXIO;
/* dequeue */
}
} else {
diff --git a/sys/dev/pckbc/pckbd.c b/sys/dev/pckbc/pckbd.c
index c2b4c2c176d..207c56de737 100644
--- a/sys/dev/pckbc/pckbd.c
+++ b/sys/dev/pckbc/pckbd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pckbd.c,v 1.19 2009/08/13 21:46:23 pirofti Exp $ */
+/* $OpenBSD: pckbd.c,v 1.20 2009/08/25 19:16:36 miod Exp $ */
/* $NetBSD: pckbd.c,v 1.24 2000/06/05 22:20:57 sommerfeld Exp $ */
/*-
@@ -330,6 +330,15 @@ pckbdprobe(parent, match, aux)
* Let the probe succeed if the keyboard is used
* as console input - it can be connected later.
*/
+#if defined(__i386__) || defined(__amd64__)
+ /*
+ * However, on legacy-free PCs, there might really
+ * be no PS/2 connector at all; in that case, do not
+ * even try to attach; ukbd will take over as console.
+ */
+ if (res == ENXIO)
+ return 0;
+#endif
return (pckbd_is_console(pa->pa_tag, pa->pa_slot) ? 1 : 0);
}
if (resp[0] != KBR_RSTDONE) {
@@ -401,7 +410,6 @@ pckbdattach(parent, self, aux)
/*
* Attach the wskbd, saving a handle to it.
- * XXX XXX XXX
*/
sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
}