Page MenuHomeFreeBSD

D1802.id3705.diff
No OneTemporary

D1802.id3705.diff

Index: sys/dev/atkbdc/atkbd.c
===================================================================
--- sys/dev/atkbdc/atkbd.c
+++ sys/dev/atkbdc/atkbd.c
@@ -77,6 +77,10 @@
static void atkbd_timeout(void *arg);
static void atkbd_shutdown_final(void *v);
+static int atkbd_reset(KBDC kbdc, int flags, int c);
+
+#define HAS_QUIRK(p, q) (((atkbdc_softc_t *)(p))->quirks & q)
+#define ALLOW_DISABLE_KBD(kbdc) !HAS_QUIRK(kbdc, KBDC_QUIRK_KEEP_ACTIVATED)
int
atkbd_probe_unit(device_t dev, int irq, int flags)
@@ -1095,6 +1099,39 @@
#endif
}
+static int
+atkbd_reset(KBDC kbdc, int flags, int c)
+{
+ /* reset keyboard hardware */
+ if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) {
+ /*
+ * KEYBOARD ERROR
+ * Keyboard reset may fail either because the keyboard
+ * doen't exist, or because the keyboard doesn't pass
+ * the self-test, or the keyboard controller on the
+ * motherboard and the keyboard somehow fail to shake hands.
+ * It is just possible, particularly in the last case,
+ * that the keyboard controller may be left in a hung state.
+ * test_controller() and test_kbd_port() appear to bring
+ * the keyboard controller back (I don't know why and how,
+ * though.)
+ */
+ empty_both_buffers(kbdc, 10);
+ test_controller(kbdc);
+ test_kbd_port(kbdc);
+ /*
+ * We could disable the keyboard port and interrupt... but,
+ * the keyboard may still exist (see above).
+ */
+ set_controller_command_byte(kbdc,
+ ALLOW_DISABLE_KBD(kbdc) ? 0xff : KBD_KBD_CONTROL_BITS, c);
+ if (bootverbose)
+ printf("atkbd: failed to reset the keyboard.\n");
+ return (EIO);
+ }
+ return (0);
+}
+
/* local functions */
static int
@@ -1250,13 +1287,14 @@
kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS);
} else {
/* try to restore the command byte as before */
- set_controller_command_byte(kbdc, 0xff, c);
+ set_controller_command_byte(kbdc,
+ ALLOW_DISABLE_KBD(kbdc) ? 0xff : KBD_KBD_CONTROL_BITS, c);
kbdc_set_device_mask(kbdc, m);
}
#endif
kbdc_lock(kbdc, FALSE);
- return err;
+ return (HAS_QUIRK(kbdc, KBDC_QUIRK_IGNORE_PROBE_RESULT) ? 0 : err);
}
static int
@@ -1299,6 +1337,12 @@
return EIO;
}
+ if (HAS_QUIRK(kbdc, KBDC_QUIRK_RESET_AFTER_PROBE) &&
+ atkbd_reset(kbdc, flags, c)) {
+ kbdc_lock(kbdc, FALSE);
+ return EIO;
+ }
+
/*
* Check if we have an XT keyboard before we attempt to reset it.
* The procedure assumes that the keyboard and the controller have
@@ -1343,31 +1387,9 @@
if (bootverbose)
printf("atkbd: keyboard ID 0x%x (%d)\n", id, *type);
- /* reset keyboard hardware */
- if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) {
- /*
- * KEYBOARD ERROR
- * Keyboard reset may fail either because the keyboard
- * doen't exist, or because the keyboard doesn't pass
- * the self-test, or the keyboard controller on the
- * motherboard and the keyboard somehow fail to shake hands.
- * It is just possible, particularly in the last case,
- * that the keyboard controller may be left in a hung state.
- * test_controller() and test_kbd_port() appear to bring
- * the keyboard controller back (I don't know why and how,
- * though.)
- */
- empty_both_buffers(kbdc, 10);
- test_controller(kbdc);
- test_kbd_port(kbdc);
- /*
- * We could disable the keyboard port and interrupt... but,
- * the keyboard may still exist (see above).
- */
- set_controller_command_byte(kbdc, 0xff, c);
+ if (!HAS_QUIRK(kbdc, KBDC_QUIRK_RESET_AFTER_PROBE) &&
+ atkbd_reset(kbdc, flags, c)) {
kbdc_lock(kbdc, FALSE);
- if (bootverbose)
- printf("atkbd: failed to reset the keyboard.\n");
return EIO;
}
@@ -1387,7 +1409,8 @@
* The XT kbd isn't usable unless the proper scan
* code set is selected.
*/
- set_controller_command_byte(kbdc, 0xff, c);
+ set_controller_command_byte(kbdc, ALLOW_DISABLE_KBD(kbdc)
+ ? 0xff : KBD_KBD_CONTROL_BITS, c);
kbdc_lock(kbdc, FALSE);
printf("atkbd: unable to set the XT keyboard mode.\n");
return EIO;
@@ -1402,6 +1425,17 @@
c |= KBD_TRANSLATION;
#endif
+ /*
+ * Some keyboards require a SETLEDS command to be sent after
+ * the reset command before they will send keystrokes to us
+ */
+ if (HAS_QUIRK(kbdc, KBDC_QUIRK_SETLEDS_ON_INIT) &&
+ send_kbd_command_and_data(kbdc, KBDC_SET_LEDS, 0) != KBD_ACK) {
+ printf("atkbd: setleds failed\n");
+ }
+ if (!ALLOW_DISABLE_KBD(kbdc))
+ send_kbd_command(kbdc, KBDC_ENABLE_KBD);
+
/* enable the keyboard port and intr. */
if (!set_controller_command_byte(kbdc,
KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK,
@@ -1412,7 +1446,9 @@
* This is serious; we are left with the disabled
* keyboard intr.
*/
- set_controller_command_byte(kbdc, 0xff, c);
+ set_controller_command_byte(kbdc, ALLOW_DISABLE_KBD(kbdc)
+ ? 0xff : (KBD_KBD_CONTROL_BITS | KBD_TRANSLATION |
+ KBD_OVERRIDE_KBD_LOCK), c);
kbdc_lock(kbdc, FALSE);
printf("atkbd: unable to enable the keyboard port and intr.\n");
return EIO;
Index: sys/dev/atkbdc/atkbdc.c
===================================================================
--- sys/dev/atkbdc/atkbdc.c
+++ sys/dev/atkbdc/atkbdc.c
@@ -114,6 +114,41 @@
static int wait_for_aux_data(atkbdc_softc_t *kbdc);
static int wait_for_aux_ack(atkbdc_softc_t *kbdc);
+struct atkbdc_quirks {
+ const char* bios_vendor;
+ const char* maker;
+ const char* product;
+ int quirk;
+};
+
+static struct atkbdc_quirks quirks[] = {
+ {"coreboot", "Acer", "Peppy",
+ KBDC_QUIRK_KEEP_ACTIVATED | KBDC_QUIRK_IGNORE_PROBE_RESULT |
+ KBDC_QUIRK_RESET_AFTER_PROBE | KBDC_QUIRK_SETLEDS_ON_INIT},
+
+ {NULL, NULL, NULL, 0}
+};
+
+#define QUIRK_STR_MATCH(s1, s2) (s1 == NULL || \
+ (s2 != NULL && !strcmp(s1, s2)))
+
+static int
+atkbdc_getquirks(void)
+{
+ int i;
+ char* bios_vendor = kern_getenv("smbios.bios.vendor");
+ char* maker = kern_getenv("smbios.system.maker");
+ char* product = kern_getenv("smbios.system.product");
+
+ for (i=0; quirks[i].quirk != 0; ++i)
+ if (QUIRK_STR_MATCH(quirks[i].bios_vendor, bios_vendor) &&
+ QUIRK_STR_MATCH(quirks[i].maker, maker) &&
+ QUIRK_STR_MATCH(quirks[i].product, product))
+ return (quirks[i].quirk);
+
+ return (0);
+}
+
atkbdc_softc_t
*atkbdc_get_softc(int unit)
{
@@ -295,6 +330,7 @@
#else
sc->retry = 5000;
#endif
+ sc->quirks = atkbdc_getquirks();
return 0;
}
@@ -1124,7 +1160,8 @@
kbdc_set_device_mask(KBDC p, int mask)
{
kbdcp(p)->command_mask =
- mask & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS);
+ mask & (((kbdcp(p)->quirks & KBDC_QUIRK_KEEP_ACTIVATED)
+ ? 0 : KBD_KBD_CONTROL_BITS) | KBD_AUX_CONTROL_BITS);
}
int
Index: sys/dev/atkbdc/atkbdcreg.h
===================================================================
--- sys/dev/atkbdc/atkbdcreg.h
+++ sys/dev/atkbdc/atkbdcreg.h
@@ -202,6 +202,11 @@
kqueue kbd; /* keyboard data queue */
kqueue aux; /* auxiliary data queue */
int retry;
+ int quirks; /* controller doesn't like deactivate */
+#define KBDC_QUIRK_KEEP_ACTIVATED (1 << 0)
+#define KBDC_QUIRK_IGNORE_PROBE_RESULT (1 << 1)
+#define KBDC_QUIRK_RESET_AFTER_PROBE (1 << 2)
+#define KBDC_QUIRK_SETLEDS_ON_INIT (1 << 3)
} atkbdc_softc_t;
enum kbdc_device_ivar {
Index: sys/dev/atkbdc/psm.c
===================================================================
--- sys/dev/atkbdc/psm.c
+++ sys/dev/atkbdc/psm.c
@@ -371,6 +371,10 @@
/* other flags (flags) */
#define PSM_FLAGS_FINGERDOWN 0x0001 /* VersaPad finger down */
+#define kbdcp(p) ((atkbdc_softc_t *)(p))
+#define ALWAYS_RESTORE_CONTROLLER(kbdc) !(kbdcp(kbdc)->quirks \
+ & KBDC_QUIRK_KEEP_ACTIVATED)
+
/* Tunables */
static int tap_enabled = -1;
TUNABLE_INT("hw.psm.tap_enabled", &tap_enabled);
@@ -1231,7 +1235,8 @@
* this is CONTROLLER ERROR; I don't know how to recover
* from this error...
*/
- restore_controller(sc->kbdc, command_byte);
+ if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
+ restore_controller(sc->kbdc, command_byte);
printf("psm%d: unable to set the command byte.\n", unit);
endprobe(ENXIO);
}
@@ -1270,7 +1275,8 @@
recover_from_error(sc->kbdc);
if (sc->config & PSM_CONFIG_IGNPORTERROR)
break;
- restore_controller(sc->kbdc, command_byte);
+ if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
+ restore_controller(sc->kbdc, command_byte);
if (verbose)
printf("psm%d: the aux port is not functioning (%d).\n",
unit, i);
@@ -1293,7 +1299,8 @@
*/
if (!reset_aux_dev(sc->kbdc)) {
recover_from_error(sc->kbdc);
- restore_controller(sc->kbdc, command_byte);
+ if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
+ restore_controller(sc->kbdc, command_byte);
if (verbose)
printf("psm%d: failed to reset the aux "
"device.\n", unit);
@@ -1315,7 +1322,8 @@
if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {
/* MOUSE ERROR */
recover_from_error(sc->kbdc);
- restore_controller(sc->kbdc, command_byte);
+ if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
+ restore_controller(sc->kbdc, command_byte);
if (verbose)
printf("psm%d: failed to enable the aux device.\n",
unit);
@@ -1337,7 +1345,8 @@
/* verify the device is a mouse */
sc->hw.hwid = get_aux_id(sc->kbdc);
if (!is_a_mouse(sc->hw.hwid)) {
- restore_controller(sc->kbdc, command_byte);
+ if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
+ restore_controller(sc->kbdc, command_byte);
if (verbose)
printf("psm%d: unknown device type (%d).\n", unit,
sc->hw.hwid);
@@ -1443,7 +1452,8 @@
* this is CONTROLLER ERROR; I don't know the proper way to
* recover from this error...
*/
- restore_controller(sc->kbdc, command_byte);
+ if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
+ restore_controller(sc->kbdc, command_byte);
printf("psm%d: unable to set the command byte.\n", unit);
endprobe(ENXIO);
}

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 25, 9:37 PM (4 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24191876
Default Alt Text
D1802.id3705.diff (9 KB)

Event Timeline