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

📄 keyboard.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 2 页
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/kernel/keyboard.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

13000	/* Keyboard driver for PC's and AT's.
13001	 *
13002	 * Changed by Marcus Hampel     (04/02/1994)
13003	 *  - Loadable keymaps
13004	 */
13005	
13006	#include "kernel.h"
13007	#include <termios.h>
13008	#include <signal.h>
13009	#include <unistd.h>
13010	#include <minix/callnr.h>
13011	#include <minix/com.h>
13012	#include <minix/keymap.h>
13013	#include "tty.h"
13014	#include "keymaps/us-std.src"
13015	
13016	/* Standard and AT keyboard.  (PS/2 MCA implies AT throughout.) */
13017	#define KEYBD           0x60    /* I/O port for keyboard data */
13018	
13019	/* AT keyboard. */
13020	#define KB_COMMAND      0x64    /* I/O port for commands on AT */
13021	#define KB_GATE_A20     0x02    /* bit in output port to enable A20 line */
13022	#define KB_PULSE_OUTPUT 0xF0    /* base for commands to pulse output port */
13023	#define KB_RESET        0x01    /* bit in output port to reset CPU */
13024	#define KB_STATUS       0x64    /* I/O port for status on AT */
13025	#define KB_ACK          0xFA    /* keyboard ack response */
13026	#define KB_BUSY         0x02    /* status bit set when KEYBD port ready */
13027	#define LED_CODE        0xED    /* command to keyboard to set LEDs */
13028	#define MAX_KB_ACK_RETRIES 0x1000       /* max #times to wait for kb ack */
13029	#define MAX_KB_BUSY_RETRIES 0x1000      /* max #times to loop while kb busy */
13030	#define KBIT            0x80    /* bit used to ack characters to keyboard */
13031	
13032	/* Miscellaneous. */
13033	#define ESC_SCAN           1    /* Reboot key when panicking */
13034	#define SLASH_SCAN        53    /* to recognize numeric slash */
13035	#define HOME_SCAN         71    /* first key on the numeric keypad */
13036	#define DEL_SCAN          83    /* DEL for use in CTRL-ALT-DEL reboot */
13037	#define CONSOLE            0    /* line number for console */
13038	#define MEMCHECK_ADR   0x472    /* address to stop memory check after reboot */
13039	#define MEMCHECK_MAG  0x1234    /* magic number to stop memory check */
13040	
13041	#define kb_addr()       (&kb_lines[0])  /* there is only one keyboard */
13042	#define KB_IN_BYTES       32    /* size of keyboard input buffer */
13043	
13044	PRIVATE int alt1;               /* left alt key state */
13045	PRIVATE int alt2;               /* right alt key state */
13046	PRIVATE int capslock;           /* caps lock key state */
13047	PRIVATE int esc;                /* escape scan code detected? */
13048	PRIVATE int control;            /* control key state */
13049	PRIVATE int caps_off;           /* 1 = normal position, 0 = depressed */
13050	PRIVATE int numlock;            /* number lock key state */
13051	PRIVATE int num_off;            /* 1 = normal position, 0 = depressed */
13052	PRIVATE int slock;              /* scroll lock key state */
13053	PRIVATE int slock_off;          /* 1 = normal position, 0 = depressed */
13054	PRIVATE int shift;              /* shift key state */
13055	
13056	PRIVATE char numpad_map[] =
13057	                {'H', 'Y', 'A', 'B', 'D', 'C', 'V', 'U', 'G', 'S', 'T', '@'};
13058	
13059	/* Keyboard structure, 1 per console. */
13060	struct kb_s {
13061	  char *ihead;                  /* next free spot in input buffer */
13062	  char *itail;                  /* scan code to return to TTY */
13063	  int icount;                   /* # codes in buffer */
13064	  char ibuf[KB_IN_BYTES];       /* input buffer */
13065	};
13066	
13067	PRIVATE struct kb_s kb_lines[NR_CONS];
13068	
13069	FORWARD _PROTOTYPE( int kb_ack, (void) );
13070	FORWARD _PROTOTYPE( int kb_wait, (void) );
13071	FORWARD _PROTOTYPE( int func_key, (int scode) );
13072	FORWARD _PROTOTYPE( int scan_keyboard, (void) );
13073	FORWARD _PROTOTYPE( unsigned make_break, (int scode) );
13074	FORWARD _PROTOTYPE( void set_leds, (void) );
13075	FORWARD _PROTOTYPE( int kbd_hw_int, (int irq) );
13076	FORWARD _PROTOTYPE( void kb_read, (struct tty *tp) );
13077	FORWARD _PROTOTYPE( unsigned map_key, (int scode) );
13078	
13079	
13080	/*===========================================================================*
13081	 *                              map_key0                                     *
13082	 *===========================================================================*/
13083	/* Map a scan code to an ASCII code ignoring modifiers. */
13084	#define map_key0(scode)  \
13085	        ((unsigned) keymap[(scode) * MAP_COLS])
13086	
13087	
13088	/*===========================================================================*
13089	 *                              map_key                                      *
13090	 *===========================================================================*/
13091	PRIVATE unsigned map_key(scode)
13092	int scode;
13093	{
13094	/* Map a scan code to an ASCII code. */
13095	
13096	  int caps, column;
13097	  u16_t *keyrow;
13098	
13099	  if (scode == SLASH_SCAN && esc) return '/';   /* don't map numeric slash */
13100	
13101	  keyrow = &keymap[scode * MAP_COLS];
13102	
13103	  caps = shift;
13104	  if (numlock && HOME_SCAN <= scode && scode <= DEL_SCAN) caps = !caps;
13105	  if (capslock && (keyrow[0] & HASCAPS)) caps = !caps;
13106	
13107	  if (alt1 || alt2) {
13108	        column = 2;
13109	        if (control || alt2) column = 3;        /* Ctrl + Alt1 == Alt2 */
13110	        if (caps) column = 4;
13111	  } else {
13112	        column = 0;
13113	        if (caps) column = 1;
13114	        if (control) column = 5;
13115	  }
13116	  return keyrow[column] & ~HASCAPS;
13117	}
	
	
13120	/*===========================================================================*
13121	 *                              kbd_hw_int                                   *
13122	 *===========================================================================*/
13123	PRIVATE int kbd_hw_int(irq)
13124	int irq;
13125	{
13126	/* A keyboard interrupt has occurred.  Process it. */
13127	
13128	  int code;
13129	  unsigned km;
13130	  register struct kb_s *kb;
13131	
13132	  /* Fetch the character from the keyboard hardware and acknowledge it. */
13133	  code = scan_keyboard();
13134	
13135	  /* The IBM keyboard interrupts twice per key, once when depressed, once when
13136	   * released.  Filter out the latter, ignoring all but the shift-type keys.
13137	   * The shift-type keys 29, 42, 54, 56, 58, and 69 must be processed normally.
13138	   */
13139	
13140	  if (code & 0200) {
13141	        /* A key has been released (high bit is set). */
13142	        km = map_key0(code & 0177);
13143	        if (km != CTRL && km != SHIFT && km != ALT && km != CALOCK
13144	                        && km != NLOCK && km != SLOCK && km != EXTKEY)
13145	                return 1;
13146	  }
13147	
13148	  /* Store the character in memory so the task can get at it later. */
13149	  kb = kb_addr();
13150	  if (kb->icount < KB_IN_BYTES) {
13151	        *kb->ihead++ = code;
13152	        if (kb->ihead == kb->ibuf + KB_IN_BYTES) kb->ihead = kb->ibuf;
13153	        kb->icount++;
13154	        tty_table[current].tty_events = 1;
13155	        force_timeout();
13156	  }
13157	  /* Else it doesn't fit - discard it. */
13158	  return 1;     /* Reenable keyboard interrupt */
13159	}
	
	
13162	/*==========================================================================*
13163	 *                              kb_read                                     *
13164	 *==========================================================================*/
13165	PRIVATE void kb_read(tp)
13166	tty_t *tp;
13167	{
13168	/* Process characters from the circular keyboard buffer. */
13169	
13170	  struct kb_s *kb;
13171	  char buf[3];
13172	  int scode;
13173	  unsigned ch;
13174	
13175	  kb = kb_addr();
13176	  tp = &tty_table[current];             /* always use the current console */
13177	
13178	  while (kb->icount > 0) {
13179	        scode = *kb->itail++;                   /* take one key scan code */
13180	        if (kb->itail == kb->ibuf + KB_IN_BYTES) kb->itail = kb->ibuf;
13181	        lock();
13182	        kb->icount--;
13183	        unlock();
13184	
13185	        /* Function keys are being used for debug dumps. */
13186	        if (func_key(scode)) continue;
13187	
13188	        /* Perform make/break processing. */
13189	        ch = make_break(scode);
13190	
13191	        if (ch <= 0xFF) {
13192	                /* A normal character. */
13193	                buf[0] = ch;
13194	                (void) in_process(tp, buf, 1);
13195	        } else
13196	        if (HOME <= ch && ch <= INSRT) {
13197	                /* An ASCII escape sequence generated by the numeric pad. */
13198	                buf[0] = ESC;
13199	                buf[1] = '[';
13200	                buf[2] = numpad_map[ch - HOME];
13201	                (void) in_process(tp, buf, 3);
13202	        } else
13203	        if (ch == ALEFT) {
13204	                /* Choose lower numbered console as current console. */
13205	                select_console(current - 1);
13206	        } else
13207	        if (ch == ARIGHT) {
13208	                /* Choose higher numbered console as current console. */
13209	                select_console(current + 1);
13210	        } else
13211	        if (AF1 <= ch && ch <= AF12) {
13212	                /* Alt-F1 is console, Alt-F2 is ttyc1, etc. */
13213	                select_console(ch - AF1);
13214	        }
13215	  }
13216	}
	
	
13219	/*===========================================================================*
13220	 *                              make_break                                   *
13221	 *===========================================================================*/
13222	PRIVATE unsigned make_break(scode)
13223	int scode;                      /* scan code of key just struck or released */
13224	{
13225	/* This routine can handle keyboards that interrupt only on key depression,
13226	 * as well as keyboards that interrupt on key depression and key release.
13227	 * For efficiency, the interrupt routine filters out most key releases.
13228	 */
13229	  int ch, make;
13230	  static int CAD_count = 0;
13231	
13232	  /* Check for CTRL-ALT-DEL, and if found, halt the computer. This would
13233	   * be better done in keyboard() in case TTY is hung, except control and
13234	   * alt are set in the high level code.
13235	   */
13236	  if (control && (alt1 || alt2) && scode == DEL_SCAN)
13237	  {
13238	        if (++CAD_count == 3) wreboot(RBT_HALT);
13239	        cause_sig(INIT_PROC_NR, SIGABRT);
13240	        return -1;
13241	  }
13242	
13243	  /* High-order bit set on key release. */
13244	  make = (scode & 0200 ? 0 : 1);        /* 0 = release, 1 = press */
13245	
13246	  ch = map_key(scode & 0177);           /* map to ASCII */
13247	
13248	  switch (ch) {
13249	        case CTRL:
13250	                control = make;
13251	                ch = -1;
13252	                break;
13253	        case SHIFT:
13254	                shift = make;
13255	                ch = -1;
13256	                break;
13257	        case ALT:
13258	                if (make) {
13259	                        if (esc) alt2 = 1; else alt1 = 1;
13260	                } else {
13261	                        alt1 = alt2 = 0;
13262	                }
13263	                ch = -1;
13264	                break;
13265	        case CALOCK:
13266	                if (make && caps_off) {

⌨️ 快捷键说明

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