summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/atkbdc/atkbd.c11
-rw-r--r--sys/dev/atkbdc/atkbdc.c24
-rw-r--r--sys/dev/atkbdc/atkbdc_isa.c31
3 files changed, 61 insertions, 5 deletions
diff --git a/sys/dev/atkbdc/atkbd.c b/sys/dev/atkbdc/atkbd.c
index eedc469..9987787 100644
--- a/sys/dev/atkbdc/atkbd.c
+++ b/sys/dev/atkbdc/atkbd.c
@@ -282,11 +282,12 @@ atkbd_configure(int flags)
int arg[2];
int i;
- /* probe the keyboard controller */
- atkbdc_configure();
-
- /* if the driver is disabled, unregister the keyboard if any */
- if (resource_disabled("atkbd", ATKBD_DEFAULT)) {
+ /*
+ * Probe the keyboard controller, if not present or if the driver
+ * is disabled, unregister the keyboard if any.
+ */
+ if (atkbdc_configure() != 0 ||
+ resource_disabled("atkbd", ATKBD_DEFAULT)) {
i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT);
if (i >= 0) {
kbd = kbd_get_keyboard(i);
diff --git a/sys/dev/atkbdc/atkbdc.c b/sys/dev/atkbdc/atkbdc.c
index b32a218..247a116 100644
--- a/sys/dev/atkbdc/atkbdc.c
+++ b/sys/dev/atkbdc/atkbdc.c
@@ -153,6 +153,10 @@ atkbdc_configure(void)
bus_space_tag_t tag;
bus_space_handle_t h0;
bus_space_handle_t h1;
+#if defined(__i386__)
+ volatile int i;
+ register_t flags;
+#endif
#ifdef __sparc64__
char name[32];
phandle_t chosen, node;
@@ -219,6 +223,26 @@ atkbdc_configure(void)
h1 = (bus_space_handle_t)port1;
#endif
#endif
+
+#if defined(__i386__)
+ /*
+ * Check if we really have AT keyboard controller. Poll status
+ * register until we get "all clear" indication. If no such
+ * indication comes, it probably means that there is no AT
+ * keyboard controller present. Give up in such case. Check relies
+ * on the fact that reading from non-existing in/out port returns
+ * 0xff on i386. May or may not be true on other platforms.
+ */
+ flags = intr_disable();
+ for (i = 0; i != 65535; i++) {
+ if ((bus_space_read_1(tag, h1, 0) & 0x2) == 0)
+ break;
+ }
+ intr_restore(flags);
+ if (i == 65535)
+ return ENXIO;
+#endif
+
return atkbdc_setup(atkbdc_softc[0], tag, h0, h1);
}
diff --git a/sys/dev/atkbdc/atkbdc_isa.c b/sys/dev/atkbdc/atkbdc_isa.c
index deeb7a0..96abfb5 100644
--- a/sys/dev/atkbdc/atkbdc_isa.c
+++ b/sys/dev/atkbdc/atkbdc_isa.c
@@ -93,6 +93,12 @@ atkbdc_isa_probe(device_t dev)
u_long count;
int error;
int rid;
+#if defined(__i386__)
+ bus_space_tag_t tag;
+ bus_space_handle_t ioh1;
+ volatile int i;
+ register_t flags;
+#endif
/* check PnP IDs */
if (ISA_PNP_PROBE(device_get_parent(dev), dev, atkbdc_ids) == ENXIO)
@@ -127,6 +133,31 @@ atkbdc_isa_probe(device_t dev)
bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
return ENXIO;
}
+
+#if defined(__i386__)
+ /*
+ * Check if we really have AT keyboard controller. Poll status
+ * register until we get "all clear" indication. If no such
+ * indication comes, it probably means that there is no AT
+ * keyboard controller present. Give up in such case. Check relies
+ * on the fact that reading from non-existing in/out port returns
+ * 0xff on i386. May or may not be true on other platforms.
+ */
+ tag = rman_get_bustag(port0);
+ ioh1 = rman_get_bushandle(port1);
+ flags = intr_disable();
+ for (i = 0; i != 65535; i++) {
+ if ((bus_space_read_1(tag, ioh1, 0) & 0x2) == 0)
+ break;
+ }
+ intr_restore(flags);
+ if (i == 65535) {
+ bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
+ bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
+ return ENXIO;
+ }
+#endif
+
device_verbose(dev);
error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);
OpenPOWER on IntegriCloud