⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcvt_kbd.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (c) 1992, 1995 Hellmuth Michaelis and Joerg Wunsch. * * Copyright (c) 1992, 1993 Brian Dunford-Shore and Holger Veit. * * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz and Don Ahn. * * This code is derived from software contributed to 386BSD by * Holger Veit. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Hellmuth Michaelis, *	Brian Dunford-Shore and Joerg Wunsch. * 4. The name authors may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * @(#)pcvt_kbd.c, 3.20, Last Edit-Date: [Sun Apr  2 18:59:04 1995] * *//*---------------------------------------------------------------------------* * *	pcvt_kbd.c	VT220 Driver Keyboard Interface Code *	---------------------------------------------------- *	-hm	------------ Release 3.00 -------------- *	-hm	integrating NetBSD-current patches *	-jw	introduced kbd_emulate_pc() if scanset > 1 *	-hm	patch from joerg for timeout in kbd_emulate_pc() *	-hm	starting to implement alt-shift/ctrl key mappings *	-hm	Gateway 2000 Keyboard fix from Brian Moore *	-hm	some #if adjusting for NetBSD 0.9 *	-hm	split off pcvt_kbd.h *	-hm	applying Joerg's patches for FreeBSD 2.0 *	-hm	patch from Martin, PCVT_NO_LED_UPDATE *	-hm	PCVT_VT220KEYB patches from Lon Willet *	-hm	PR #399, patch from Bill Sommerfeld: Return with PCVT_META_ESC *	-hm	allow keyboard-less kernel boot for serial consoles and such .. *	-hm	patch from Lon Willett for led-update and showkey() *	-hm	patch from Lon Willett to fix mapping of Control-R scancode *	-hm	delay patch from Martin Husemann after port-i386 ml-discussion *	-hm	added PCVT_NONRESP_KEYB_TRY definition to doreset() * *---------------------------------------------------------------------------*/#include "vt.h"#include "opt_ddb.h"#if NVT > 0#include <i386/isa/pcvt/pcvt_hdr.h>	/* global include */#define LEDSTATE_UPDATE_PENDING	(1 << 3)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);static void sfkey1(void), sfkey2(void),  sfkey3(void),  sfkey4(void);static void sfkey5(void), sfkey6(void),  sfkey7(void),  sfkey8(void);static void sfkey9(void), sfkey10(void), sfkey11(void), sfkey12(void);static void cfkey1(void), cfkey2(void),  cfkey3(void),  cfkey4(void);static void cfkey5(void), cfkey6(void),  cfkey7(void),  cfkey8(void);static void cfkey9(void), cfkey10(void), cfkey11(void), cfkey12(void);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 );#elsestatic int 	set_keyboard_param( 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 );static int	setkeydef ( struct kbd_ovlkey *data );static u_char *	xlatkey2ascii( U_short key );static int	ledstate  = LEDSTATE_UPDATE_PENDING;	/* keyboard led's */static int	tpmrate   = KBD_TPD500|KBD_TPM100;static u_char	altkpflag = 0;static u_short	altkpval  = 0;#if PCVT_SHOWKEYSu_char rawkeybuf[80];#endif#include <i386/isa/pcvt/pcvt_kbd.h>	/* tables etc */#if PCVT_SHOWKEYS/*---------------------------------------------------------------------------* *	keyboard debugging: put kbd communication char into some buffer *---------------------------------------------------------------------------*/static void showkey (char delim, u_char val){	int rki;	for(rki = 3; rki < 80; rki++)		/* shift left buffer */		rawkeybuf[rki-3] = rawkeybuf[rki];	rawkeybuf[77] = delim;		/* delimiter */	rki = (val & 0xf0) >> 4;	/* ms nibble */	if(rki <= 9)		rki = rki + '0';	else		rki = rki - 10 + 'A';	rawkeybuf[78] = rki;	rki = val & 0x0f;		/* ls nibble */	if(rki <= 9)		rki = rki + '0';	else		rki = rki - 10 + 'A';	rawkeybuf[79] = rki;}#endif	/* PCVT_SHOWKEYS *//*---------------------------------------------------------------------------* *	function to switch to another virtual screen *---------------------------------------------------------------------------*/static voiddo_vgapage(int page){	if(critical_scroll)		/* executing critical region ? */		switch_page = page;	/* yes, auto switch later */	else		vgapage(page);		/* no, switch now */}/* * This code from Lon Willett enclosed in #if PCVT_UPDLED_LOSES_INTR is * abled because it crashes FreeBSD 1.1.5.1 at boot time. * The cause is obviously that the timeout queue is not yet initialized * timeout is called from here the first time. * Anyway it is a pointer in the right direction so it is included for * reference here. */#define PCVT_UPDLED_LOSES_INTR	0	/* disabled for now */#if PCVT_UPDLED_LOSES_INTR || defined(_I386_ISA_KBDIO_H_)/*---------------------------------------------------------------------------* *	check for lost keyboard interrupts *---------------------------------------------------------------------------*//* * The two commands to change the LEDs generate two KEYB_R_ACK responses * from the keyboard, which aren't explicitly checked for (maybe they * should be?).  However, when a lot of other I/O is happening, one of * the interrupts sometimes gets lost (I'm not sure of the details of * how and why and what hardware this happens with). * * This may have had something to do with spltty() previously not being * called before the kbd_cmd() calls in update_led(). * * This is a real problem, because normally the keyboard is only polled * by pcrint(), and no more interrupts will be generated until the ACK * has been read.  So the keyboard is hung.  This code polls a little * while after changing the LEDs to make sure that this hasn't happened. * * XXX Quite possibly we should poll the kbd on a regular basis anyway, * in the interest of robustness.  It may be possible that interrupts * get lost other times as well. */static int lost_intr_timeout_queued = 0;static voidcheck_for_lost_intr (void *arg){#ifndef _I386_ISA_KBDIO_H_	lost_intr_timeout_queued = 0;	if (inb(CONTROLLER_CTRL) & STATUS_OUTPBF)	{		int opri = spltty ();		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 || defined(_I386_ISA_KBDIO_H_) *//*---------------------------------------------------------------------------* *	update keyboard led's *---------------------------------------------------------------------------*/voidupdate_led(void){#if !PCVT_NO_LED_UPDATE	/* Don't update LED's unless necessary. */	int opri, new_ledstate, response1, response2;	opri = spltty();	new_ledstate = (vsp->scroll_lock) |		       (vsp->num_lock * 2) |		       (vsp->caps_lock * 4);	if (new_ledstate != ledstate)	{#ifndef _I386_ISA_KBDIO_H_		ledstate = LEDSTATE_UPDATE_PENDING;		if(kbd_cmd(KEYB_C_LEDS) != 0)		{			printf("Keyboard LED command timeout\n");			splx(opri);			return;		}		/*		 * For some keyboards or keyboard controllers, it is an		 * error to issue a command without waiting long enough		 * for an ACK for the previous command.  The keyboard		 * gets confused, and responds with KEYB_R_RESEND, but		 * we ignore that.  Wait for the ACK here.  The busy		 * waiting doesn't matter much, since we lose anyway by		 * busy waiting to send the command.		 *		 * XXX actually wait for any response, since we can't		 * handle normal scancodes here.		 *		 * XXX all this should be interrupt driven.  Issue only		 * one command at a time wait for a ACK before proceeding.		 * Retry after a timeout or on receipt of a KEYB_R_RESEND.		 * KEYB_R_RESENDs seem to be guaranteed by working		 * keyboard controllers with broken (or disconnected)		 * keyboards.  There is another code for keyboard		 * reconnects.  The keyboard hardware is very simple and		 * well designed :-).		 */		response1 = kbd_response();		if(kbd_cmd(new_ledstate) != 0) {			printf("Keyboard LED data timeout\n");			splx(opri);			return;		}		response2 = kbd_response();		if (response1 == KEYB_R_ACK && response2 == KEYB_R_ACK)			ledstate = new_ledstate;		else			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_param(KBDC_SET_LEDS, new_ledstate) == 0) 				ledstate = new_ledstate;		}#endif /* !_I386_ISA_KBDIO_H_ */#if PCVT_UPDLED_LOSES_INTR		if (lost_intr_timeout_queued)			untimeout(check_for_lost_intr, NULL);		timeout(check_for_lost_intr, NULL, hz);		lost_intr_timeout_queued = 1;#endif /* PCVT_UPDLED_LOSES_INTR */	}#ifndef _I386_ISA_KBDIO_H_	splx(opri);#endif #endif /* !PCVT_NO_LED_UPDATE */}/*---------------------------------------------------------------------------* *	set typematic rate *---------------------------------------------------------------------------*/static voidsettpmrate(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_param(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) *---------------------------------------------------------------------------*/static intkbc_8042cmd(int val){	unsigned timeo;	timeo = 100000; 	/* > 100 msec */	while (inb(CONTROLLER_CTRL) & STATUS_INPBF)		if (--timeo == 0)			return (-1);	outb(CONTROLLER_CTRL, val);	return (0);}/*---------------------------------------------------------------------------* *	Pass command to keyboard itself *---------------------------------------------------------------------------*/intkbd_cmd(int val){	unsigned timeo;	timeo = 100000; 	/* > 100 msec */	while (inb(CONTROLLER_CTRL) & STATUS_INPBF)		if (--timeo == 0)			return (-1);	outb(CONTROLLER_DATA, val);#if PCVT_SHOWKEYS	showkey ('>', val);#endif	/* PCVT_SHOWKEYS */	return (0);}/*---------------------------------------------------------------------------* *	Read response from keyboard *	NB: make sure to call spltty() before kbd_cmd(), kbd_response(). *---------------------------------------------------------------------------*/intkbd_response(void){	u_char ch;	unsigned timeo;	timeo = 500000; 	/* > 500 msec (KEYB_R_SELFOK requires 87) */	while (!(inb(CONTROLLER_CTRL) & STATUS_OUTPBF))		if (--timeo == 0)			return (-1);	PCVT_KBD_DELAY();		/* 7 us delay */	ch = inb(CONTROLLER_DATA);#if PCVT_SHOWKEYS	showkey ('<', ch);#endif	/* PCVT_SHOWKEYS */	return ch;}#elsestatic intset_keyboard_param(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();#if 0    c = get_controller_command_byte(kbdc);    if ((c == -1) 	|| !set_controller_command_byte(kbdc,             kbdc_get_device_mask(kbdc),            KBD_DISABLE_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);#endif    if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK)        send_kbd_command(kbdc, KBDC_ENABLE_KBD);#if 0    /* 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 */    }#else    splx(s);#endif    kbdc_lock(kbdc, FALSE);    return 0;}#endif /* !_I386_ISA_KBDIO_H_ */#if PCVT_SCANSET > 1/*---------------------------------------------------------------------------* *	switch PC scan code emulation mode *---------------------------------------------------------------------------*/voidkbd_emulate_pc(int do_emulation){#ifndef _I386_ISA_KBDIO_H_	int cmd, timeo = 10000;	cmd = COMMAND_SYSFLG|COMMAND_IRQEN; /* common base cmd */#if !PCVT_USEKBDSEC	cmd |= COMMAND_INHOVR;#endif	if(do_emulation)		cmd |= COMMAND_PCSCAN;	kbc_8042cmd(CONTR_WRITE);	while (inb(CONTROLLER_CTRL) & STATUS_INPBF)		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 */#ifndef PCVT_NONRESP_KEYB_TRY#define PCVT_NONRESP_KEYB_TRY	25	/* no of times to try to detect	*/#endif					/* a nonresponding keyboard	*//*---------------------------------------------------------------------------* *	try to force keyboard into a known state .. *---------------------------------------------------------------------------*/staticvoid doreset(void){#ifndef _I386_ISA_KBDIO_H_	int again = 0;	int once = 0;	int response, opri;	/* Enable interrupts and keyboard, etc. */	if (kbc_8042cmd(CONTR_WRITE) != 0)		printf("pcvt: doreset() - timeout controller write command\n");#if PCVT_USEKBDSEC		/* security enabled */#  if PCVT_SCANSET == 2#    define KBDINITCMD COMMAND_SYSFLG|COMMAND_IRQEN#  else /* PCVT_SCANSET != 2 */#    define KBDINITCMD COMMAND_PCSCAN|COMMAND_SYSFLG|COMMAND_IRQEN#  endif /* PCVT_SCANSET == 2 */#else /* ! PCVT_USEKBDSEC */	/* security disabled */#  if PCVT_SCANSET == 2#    define KBDINITCMD COMMAND_INHOVR|COMMAND_SYSFLG|COMMAND_IRQEN#  else /* PCVT_SCANSET != 2 */#    define KBDINITCMD COMMAND_PCSCAN|COMMAND_INHOVR|COMMAND_SYSFLG\	|COMMAND_IRQEN#  endif /* PCVT_SCANSET == 2 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -