summaryrefslogtreecommitdiffstats
path: root/sys/dev/atkbdc/atkbd.c
diff options
context:
space:
mode:
authoryokota <yokota@FreeBSD.org>2000-01-10 08:52:32 +0000
committeryokota <yokota@FreeBSD.org>2000-01-10 08:52:32 +0000
commitcb9328b9a1d6af5d1d27524bf8e1ccfeac0d7471 (patch)
tree9f4f4a80e58f8e4e7df229ebf9dfb6184b202d21 /sys/dev/atkbdc/atkbd.c
parent828713d689d63c48bcbf7f931a7f9770808ec7ed (diff)
downloadFreeBSD-src-cb9328b9a1d6af5d1d27524bf8e1ccfeac0d7471.zip
FreeBSD-src-cb9328b9a1d6af5d1d27524bf8e1ccfeac0d7471.tar.gz
Obtain the initial key repeat rate setting via BIOS in i386 if
possible.
Diffstat (limited to 'sys/dev/atkbdc/atkbd.c')
-rw-r--r--sys/dev/atkbdc/atkbd.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/sys/dev/atkbdc/atkbd.c b/sys/dev/atkbdc/atkbd.c
index 9d15fc4..4280da6 100644
--- a/sys/dev/atkbdc/atkbd.c
+++ b/sys/dev/atkbdc/atkbd.c
@@ -39,6 +39,16 @@
#include <sys/proc.h>
#include <sys/malloc.h>
+#ifdef __i386__
+#include <machine/md_var.h>
+#include <machine/psl.h>
+#include <machine/vm86.h>
+#include <machine/pc/bios.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#endif /* __i386__ */
+
#include <dev/kbd/kbdreg.h>
#include <dev/kbd/atkbdreg.h>
#include <dev/kbd/atkbdcreg.h>
@@ -214,6 +224,7 @@ keyboard_switch_t atkbdsw = {
KEYBOARD_DRIVER(atkbd, atkbdsw, atkbd_configure);
/* local functions */
+static int get_typematic(keyboard_t *kbd);
static int setup_kbd_port(KBDC kbdc, int port, int intr);
static int get_kbd_echo(KBDC kbdc);
static int probe_keyboard(KBDC kbdc, int flags);
@@ -323,6 +334,7 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
accentmap_t *accmap;
fkeytab_t *fkeymap;
int fkeymap_size;
+ int delay[2];
int *data = (int *)arg;
/* XXX */
@@ -406,6 +418,10 @@ atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
&& (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD))
return ENXIO;
atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
+ get_typematic(kbd);
+ delay[0] = kbd->kb_delay1;
+ delay[1] = kbd->kb_delay2;
+ atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
KBD_INIT_DONE(kbd);
}
if (!KBD_IS_CONFIGURED(kbd)) {
@@ -430,6 +446,7 @@ static int
atkbd_intr(keyboard_t *kbd, void *arg)
{
atkbd_state_t *state;
+ int delay[2];
int c;
if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
@@ -451,6 +468,10 @@ atkbd_intr(keyboard_t *kbd, void *arg)
init_keyboard(state->kbdc, &kbd->kb_type,
kbd->kb_config);
atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
+ get_typematic(kbd);
+ delay[0] = kbd->kb_delay1;
+ delay[1] = kbd->kb_delay2;
+ atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
KBD_FOUND_DEVICE(kbd);
}
}
@@ -974,6 +995,39 @@ atkbd_poll(keyboard_t *kbd, int on)
/* local functions */
static int
+get_typematic(keyboard_t *kbd)
+{
+#ifdef __i386__
+ /*
+ * Only some systems allow us to retrieve the keyboard repeat
+ * rate previously set via the BIOS...
+ */
+ struct vm86frame vmf;
+ u_int32_t p;
+
+ bzero(&vmf, sizeof(vmf));
+ vmf.vmf_ax = 0xc000;
+ vm86_intcall(0x15, &vmf);
+ if ((vmf.vmf_eflags & PSL_C) || vmf.vmf_ah)
+ return ENODEV;
+ p = BIOS_PADDRTOVADDR(((u_int32_t)vmf.vmf_es << 4) + vmf.vmf_bx);
+ if ((readb(p + 6) & 0x40) == 0) /* int 16, function 0x09 supported? */
+ return ENODEV;
+ vmf.vmf_ax = 0x0900;
+ vm86_intcall(0x16, &vmf);
+ if ((vmf.vmf_al & 0x08) == 0) /* int 16, function 0x0306 supported? */
+ return ENODEV;
+ vmf.vmf_ax = 0x0306;
+ vm86_intcall(0x16, &vmf);
+ kbd->kb_delay1 = typematic_delay(vmf.vmf_bh << 5);
+ kbd->kb_delay2 = typematic_rate(vmf.vmf_bl);
+ return 0;
+#else
+ return ENODEV;
+#endif /* __i386__ */
+}
+
+static int
setup_kbd_port(KBDC kbdc, int port, int intr)
{
if (!set_controller_command_byte(kbdc,
OpenPOWER on IntegriCloud