diff options
author | joerg <joerg@FreeBSD.org> | 1997-03-06 22:34:24 +0000 |
---|---|---|
committer | joerg <joerg@FreeBSD.org> | 1997-03-06 22:34:24 +0000 |
commit | 70864abe498fed77a9760b6cbd5a7aad13d14ccd (patch) | |
tree | 93c06f535ef17c023e8ae9f2dea053b1a9bc6905 /sys/i386/isa/pcvt/pcvt_kbd.c | |
parent | 14893dc54adf8220f897480d08384e372762301c (diff) | |
download | FreeBSD-src-70864abe498fed77a9760b6cbd5a7aad13d14ccd.zip FreeBSD-src-70864abe498fed77a9760b6cbd5a7aad13d14ccd.tar.gz |
Move pcvt towards using kbdio (finally!).
Warning: this won't work yet with PCVT_SCANSET=2 along in early
console mode (boot -c, or boot -d).
A big thanks to Kazutaka, and a word of apologies for delaying the
review for that long time...
Submitted by: yokota@zodiac.mech.utsunomiya-u.ac.jp (Kazutaka YOKOTA)
Diffstat (limited to 'sys/i386/isa/pcvt/pcvt_kbd.c')
-rw-r--r-- | sys/i386/isa/pcvt/pcvt_kbd.c | 322 |
1 files changed, 318 insertions, 4 deletions
diff --git a/sys/i386/isa/pcvt/pcvt_kbd.c b/sys/i386/isa/pcvt/pcvt_kbd.c index 312b912..17bdea8 100644 --- a/sys/i386/isa/pcvt/pcvt_kbd.c +++ b/sys/i386/isa/pcvt/pcvt_kbd.c @@ -75,8 +75,6 @@ #define LEDSTATE_UPDATE_PENDING (1 << 3) -extern int kbd_response __P((void)); - static void fkey1(void), fkey2(void), fkey3(void), fkey4(void); static void fkey5(void), fkey6(void), fkey7(void), fkey8(void); static void fkey9(void), fkey10(void), fkey11(void), fkey12(void); @@ -93,7 +91,11 @@ static void doreset ( void ); static void ovlinit ( int force ); static void settpmrate ( int rate ); static void setlockkeys ( int snc ); +#ifndef _I386_ISA_KBDIO_H_ static int kbc_8042cmd ( int val ); +#else +static int set_keyboard( int command, int data ); +#endif /* !_I386_ISA_KBDIO_H_ */ static int getokeydef ( unsigned key, struct kbd_ovlkey *thisdef ); static int getckeydef ( unsigned key, struct kbd_ovlkey *thisdef ); static int rmkeydef ( int key ); @@ -168,7 +170,7 @@ do_vgapage(int page) #define PCVT_UPDLED_LOSES_INTR 0 /* disabled for now */ -#if PCVT_UPDLED_LOSES_INTR +#if PCVT_UPDLED_LOSES_INTR || defined(_I386_ISA_KBDIO_H_) /*---------------------------------------------------------------------------* * check for lost keyboard interrupts @@ -199,6 +201,7 @@ static int lost_intr_timeout_queued = 0; static void check_for_lost_intr (void *arg) { +#ifndef _I386_ISA_KBDIO_H_ lost_intr_timeout_queued = 0; if (inb(CONTROLLER_CTRL) & STATUS_OUTPBF) { @@ -206,9 +209,23 @@ check_for_lost_intr (void *arg) pcrint (); splx (opri); } +#else + int opri; + + lost_intr_timeout_queued = 0; + if (kbdc_lock(kbdc, TRUE)) { + opri = spltty (); + kbdc_lock(kbdc, FALSE); + if (kbdc_data_ready(kbdc)) + pcrint (0); + splx (opri); + } + timeout(check_for_lost_intr, (void *)NULL, hz); + lost_intr_timeout_queued = 1; +#endif /* !_I386_ISA_KBDIO_H_ */ } -#endif /* PCVT_UPDLED_LOSES_INTR */ +#endif /* PCVT_UPDLED_LOSES_INTR || defined(_I386_ISA_KBDIO_H_) */ /*---------------------------------------------------------------------------* * update keyboard led's @@ -229,6 +246,8 @@ update_led(void) if (new_ledstate != ledstate) { +#ifndef _I386_ISA_KBDIO_H_ + ledstate = LEDSTATE_UPDATE_PENDING; if(kbd_cmd(KEYB_C_LEDS) != 0) @@ -274,6 +293,19 @@ update_led(void) printf( "Keyboard LED command not ACKed (responses %#x %#x)\n", response1, response2); +#else /* _I386_ISA_KBDIO_H_ */ + + if (kbdc == NULL) { + ledstate = new_ledstate; + splx(opri); + } else { + ledstate = LEDSTATE_UPDATE_PENDING; + splx(opri); + if (set_keyboard(KBDC_SET_LEDS, new_ledstate) == 0) + ledstate = new_ledstate; + } + +#endif /* !_I386_ISA_KBDIO_H_ */ #if PCVT_UPDLED_LOSES_INTR if (lost_intr_timeout_queued) @@ -285,7 +317,9 @@ update_led(void) } +#ifndef _I386_ISA_KBDIO_H_ splx(opri); +#endif #endif /* !PCVT_NO_LED_UPDATE */ } @@ -296,13 +330,20 @@ update_led(void) static void settpmrate(int rate) { +#ifndef _I386_ISA_KBDIO_H_ tpmrate = rate & 0x7f; if(kbd_cmd(KEYB_C_TYPEM) != 0) printf("Keyboard TYPEMATIC command timeout\n"); else if(kbd_cmd(tpmrate) != 0) printf("Keyboard TYPEMATIC data timeout\n"); +#else + tpmrate = rate & 0x7f; + if (set_keyboard(KBDC_SET_TYPEMATIC, tpmrate) != 0) + printf("pcvt: failed to set keyboard TYPEMATIC.\n"); +#endif /* !_I386_ISA_KBDIO_H_ */ } +#ifndef _I386_ISA_KBDIO_H_ /*---------------------------------------------------------------------------* * Pass command to keyboard controller (8042) *---------------------------------------------------------------------------*/ @@ -364,6 +405,55 @@ kbd_response(void) return ch; } +#else +static int +set_keyboard(int command, int data) +{ + int s; + int c; + + if (kbdc == NULL) + return 1; + + /* prevent the timeout routine from polling the keyboard */ + if (!kbdc_lock(kbdc, TRUE)) + return 1; + + /* disable the keyboard and mouse interrupt */ + s = spltty(); + c = get_controller_command_byte(kbdc); + if ((c == -1) + || !set_controller_command_byte(kbdc, + kbdc_get_device_mask(kbdc), + KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT + | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { + /* CONTROLLER ERROR */ + kbdc_lock(kbdc, FALSE); + splx(s); + return 1; + } + /* + * Now that the keyboard controller is told not to generate + * the keyboard and mouse interrupts, call `splx()' to allow + * the other tty interrupts. The clock interrupt may also occur, + * but the timeout routine (`scrn_timer()') will be blocked + * by the lock flag set via `kbdc_lock()' + */ + splx(s); + + send_kbd_command_and_data(kbdc, command, data); + + /* restore the interrupts */ + if (!set_controller_command_byte(kbdc, + kbdc_get_device_mask(kbdc), + c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { + /* CONTROLLER ERROR */ + } + kbdc_lock(kbdc, FALSE); + + return 0; +} +#endif /* !_I386_ISA_KBDIO_H_ */ #if PCVT_SCANSET > 1 /*---------------------------------------------------------------------------* @@ -372,6 +462,7 @@ kbd_response(void) void kbd_emulate_pc(int do_emulation) { +#ifndef _I386_ISA_KBDIO_H_ int cmd, timeo = 10000; cmd = COMMAND_SYSFLG|COMMAND_IRQEN; /* common base cmd */ @@ -388,6 +479,10 @@ kbd_emulate_pc(int do_emulation) if (--timeo == 0) break; outb(CONTROLLER_DATA, cmd); +#else + set_controller_command_byte(kbdc, KBD_TRANSLATION, + (do_emulation) ? KBD_TRANSLATION : 0); +#endif /* !_I386_ISA_KBDIO_H_ */ } #endif /* PCVT_SCANSET > 1 */ @@ -403,6 +498,7 @@ kbd_emulate_pc(int do_emulation) static void doreset(void) { +#ifndef _I386_ISA_KBDIO_H_ int again = 0; int once = 0; int response, opri; @@ -563,6 +659,164 @@ r_entry: #endif /* PCVT_KEYBDID */ +#else /* _I386_ISA_KBDIO_H_ */ + int c; + int m; + int s; + + if (!reset_keyboard) /* no, we are not ready to reset */ + return; + + if (lost_intr_timeout_queued) { + untimeout(check_for_lost_intr, (void *)NULL); + lost_intr_timeout_queued = 0; + } + + if (kbdc == NULL) + kbdc = kbdc_open(IO_KBD); + + if (!kbdc_lock(kbdc, TRUE)) /* strange, somebody got there first */ + return; + + /* remove any noise */ + empty_both_buffers(kbdc, 10); + + s = spltty(); + + /* save the current controller command byte */ + m = kbdc_get_device_mask(kbdc) & ~KBD_KBD_CONTROL_BITS; + c = get_controller_command_byte(kbdc); + if (c == -1) { + /* CONTROLLER ERROR */ + kbdc_set_device_mask(kbdc, m); + kbdc_lock(kbdc, FALSE); + kbdc = NULL; + splx(s); + printf("pcvt: unable to get the command byte.\n"); + return; + } + +#if PCVT_USEKBDSEC /* security enabled */ + +# if PCVT_SCANSET == 2 +# define KBDINITCMD 0 +# else /* PCVT_SCANSET != 2 */ +# define KBDINITCMD KBD_TRANSLATION +# endif /* PCVT_SCANSET == 2 */ + +#else /* ! PCVT_USEKBDSEC */ /* security disabled */ + +# if PCVT_SCANSET == 2 +# define KBDINITCMD KBD_OVERRIDE_KBD_LOCK +# else /* PCVT_SCANSET != 2 */ +# define KBDINITCMD KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK +# endif /* PCVT_SCANSET == 2 */ + +#endif /* PCVT_USEKBDSEC */ + + /* disable the keyboard interrupt and the aux port and interrupt */ + if (!set_controller_command_byte(kbdc, + KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS + | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK, + KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT + | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT + | KBDINITCMD)) { + /* CONTROLLER ERROR: there is very little we can do... */ + kbdc_set_device_mask(kbdc, m); + kbdc_lock(kbdc, FALSE); + kbdc = NULL; + splx(s); + printf("pcvt: unable to set the command byte.\n"); + return; + } + splx(s); + + /* reset keyboard hardware */ + ledstate = LEDSTATE_UPDATE_PENDING; + if (!reset_kbd(kbdc)) { + /* KEYBOARD ERROR */ + empty_both_buffers(kbdc, 10); + test_controller(kbdc); + test_kbd_port(kbdc); + /* + * We could disable the keyboard port and interrupt now... + * but, the keyboard may still exist. + */ + printf("pcvt: failed to reset the keyboard.\n"); + /* try to restore the original command byte */ + set_controller_command_byte(kbdc, 0xff, c); + kbdc_set_device_mask(kbdc, m); + kbdc_lock(kbdc, FALSE); + kbdc = NULL; + return; + } + +#if PCVT_KEYBDID + + keyboard_type = KB_UNKNOWN; + if (send_kbd_command(kbdc, KBDC_SEND_DEV_ID) == KBD_ACK) { + DELAY(10000); /* 10msec delay */ + switch (read_kbd_data(kbdc)) { + case KEYB_R_MF2ID1: + switch (read_kbd_data(kbdc)) { + case KEYB_R_MF2ID2: + case KEYB_R_MF2ID2HP: + keyboard_type = KB_MFII; + break; + case -1: + default: + break; + } + break; + case -1: + keyboard_type = KB_AT; + /* fall through */ + default: + /* XXX: should we read the second byte? */ + empty_both_buffers(kbdc, 10); /* XXX */ + break; + } + } else { + /* + * The send ID command failed. This error is considered + * benign, but may need recovery. + */ + empty_both_buffers(kbdc, 10); + test_controller(kbdc); + test_kbd_port(kbdc); + } + +#else /* PCVT_KEYBDID */ + + keyboard_type = KB_MFII; /* force it .. */ + +#endif /* PCVT_KEYBDID */ + + /* enable the keyboard port and intr. */ + if (!set_controller_command_byte(kbdc, + KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS, + (c & KBD_AUX_CONTROL_BITS) + | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) { + /* CONTROLLER ERROR + * This is serious; we are left with the disabled + * keyboard intr. + */ + printf("pcvt: failed to enable the keyboard port and intr.\n"); + kbdc_set_device_mask(kbdc, m); + kbdc_lock(kbdc, FALSE); + kbdc = NULL; + return; + } + + kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS); + kbdc_lock(kbdc, FALSE); + + update_led(); + + timeout(check_for_lost_intr, (void *)NULL, hz); + lost_intr_timeout_queued = 1; + +#endif /* !_I386_ISA_KBDIO_H_ */ } /*---------------------------------------------------------------------------* @@ -984,10 +1238,16 @@ sgetc(int noblock) static char keybuf[2] = {0}; /* the second 0 is a delimiter! */ #endif /* XSERVER */ +#ifdef _I386_ISA_KBDIO_H_ + int c; +#endif /* _I386_ISA_KBDIO_H_ */ + loop: #ifdef XSERVER +#ifndef _I386_ISA_KBDIO_H_ + #if PCVT_KBD_FIFO /* see if there is data from the keyboard available either from */ @@ -1021,6 +1281,32 @@ loop: #endif /* !PCVT_KBD_FIFO */ +#else /* _I386_ISA_KBDIO_H_ */ + +#if PCVT_KBD_FIFO + if (pcvt_kbd_count) { + dt = pcvt_kbd_fifo[pcvt_kbd_rptr++]; + PCVT_DISABLE_INTR(); + pcvt_kbd_count--; + PCVT_ENABLE_INTR(); + if (pcvt_kbd_rptr >= PCVT_KBD_FIFO_SZ) + pcvt_kbd_rptr = 0; + } else +#endif /* PCVT_KBD_FIFO */ + if (!noblock) { + while ((c = read_kbd_data(kbdc)) == -1) + ; + dt = c; + } else { + if ((c = read_kbd_data_no_wait(kbdc)) == -1) + return NULL; + dt = c; + } + + { + +#endif /* !_I386_ISA_KBDIO_H_ */ + /* * If x mode is active, only care for locking keys, then * return the scan code instead of any key translation. @@ -1297,6 +1583,8 @@ no_mouse_event: #else /* !XSERVER */ +#ifndef _I386_ISA_KBDIO_H_ + # if PCVT_KBD_FIFO /* see if there is data from the keyboard available either from */ @@ -1332,8 +1620,33 @@ no_mouse_event: #endif /* !PCVT_KBD_FIFO */ +#else /* _I386_ISA_KBDIO_H_ */ + +#if PCVT_KBD_FIFO + if (pcvt_kbd_count) { + dt = pcvt_kbd_fifo[pcvt_kbd_rptr++]; + PCVT_DISABLE_INTR(); + pcvt_kbd_count--; + PCVT_ENABLE_INTR(); + if (pcvt_kbd_rptr >= PCVT_KBD_FIFO_SZ) + pcvt_kbd_rptr = 0; + } else +#endif /* PCVT_KBD_FIFO */ + if (!noblock) { + while ((c = read_kbd_data(kbdc)) == -1) + ; + dt = c; + } else { + if ((c = read_kbd_data_no_wait(kbdc)) == -1) + return NULL; + dt = c; + } + +#endif /* !_I386_ISA_KBDIO_H_ */ + #endif /* !XSERVER */ +#ifndef _I386_ISA_KBDIO_H_ else { if(noblock) @@ -1341,6 +1654,7 @@ no_mouse_event: else goto loop; } +#endif /* !_I386_ISA_KBDIO_H_ */ #if PCVT_SHOWKEYS showkey (' ', dt); |