Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133317161
D1802.id3705.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D1802.id3705.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D1802: Port keyboard driver changes from DragonFly to allow using keyboard on Chromebook
Attached
Detach File
Event Timeline
Log In to Comment