Linux0.96c/kernel/chr_drv/keyboard.c

Compare this file to the similar file:
Show the results in this format:

/*
 * linux/kernel/chr_drv/keyboard.c
 *
 * Keyboard driver for Linux v0.96 using Latin-1.
 *
 * Written for linux by Johan Myreen as a translation from
 * the assembly version by Linus (with diacriticals added)
 */

#include <linux/sched.h>
#include <linux/ctype.h>
#include <linux/tty.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/system.h>

#define LSHIFT   0x01
#define RSHIFT   0x02
#define LCTRL    0x04
#define RCTRL    0x08
#define ALT      0x10
#define ALTGR    0x20
#define CAPS     0x40
#define CAPSDOWN 0x80

#define SCRLED   0x01
#define NUMLED   0x02
#define CAPSLED  0x04

#define NO_META_BIT 0x80

unsigned char kapplic = 0;
unsigned char ckmode = 0;
unsigned char krepeat = 1;
unsigned char kmode = 0;
unsigned char kleds = NUMLED;
unsigned char ke0 = 0;
unsigned char kraw = 0;
unsigned char kbd_flags = KBDFLAGS;
unsigned char lfnlmode = 0;

extern void do_keyboard_interrupt(void);
extern void ctrl_alt_del(void);
extern void change_console(unsigned int new_console);
extern struct tty_queue *table_list[];

typedef void (*fptr)(int);

static unsigned char old_leds = 2;
static int diacr = -1;
static int npadch = 0;
fptr key_table[];

static void put_queue(int);
void set_leds(void);
static void applkey(int);
static void cur(int);
static void kb_wait(void), kb_ack(void);
static unsigned int handle_diacr(unsigned int);

void do_keyboard(void)
{
	static unsigned char rep = 0xff, repke0 = 0;
	unsigned char scancode, x;
	struct tty_struct * tty = TTY_TABLE(0);

	scancode=inb_p(0x60);
	x=inb_p(0x61);
	outb_p(x|0x80, 0x61);
	outb_p(x&0x7f, 0x61);
	outb(0x20, 0x20);
	sti();

	if (kraw) {
		put_queue(scancode);
		do_keyboard_interrupt();
		return;
	}
	if (scancode == 0xe0) {
		ke0 = 1;
		return;
	}
	if (scancode == 0xe1) {
		ke0 = 2;
		return;
	}
	/*
	 *  The keyboard maintains its own internal caps lock and num lock
	 *  statuses. In caps lock mode E0 AA precedes make code and E0 2A
	 *  follows break code. In num lock mode, E0 2A precedes make
	 *  code and E0 AA follows break code. We do our own book-keeping,
	 *  so we will just ignore these.
	 */
	if (ke0 == 1 && (scancode == 0x2a || scancode == 0xaa)) {
		ke0 = 0;
		return;
	}
	/*
	 *  Repeat a key only if the input buffers are empty or the
	 *  characters get echoed locally. This makes key repeat usable
	 *  with slow applications and unders heavy loads.
	 */
	if (rep == 0xff) {
		if (scancode < 0x80) {
			rep = scancode;
			repke0 = ke0;
		}
	} else if (ke0 == repke0 && (scancode & 0x7f) == rep)
		if (scancode & 0x80)
			rep = 0xff;
		else if (!(krepeat && (L_ECHO(tty) || (EMPTY(tty->secondary) &&
				EMPTY(tty->read_q))))) {
			ke0 = 0;
			return;
		}
	key_table[scancode](scancode);
	do_keyboard_interrupt();
	ke0 = 0;
}

static void put_queue(int ch)
{
	register struct tty_queue *qp = table_list[0];
	unsigned long new_head;

	qp->buf[qp->head]=ch;
	if ((new_head=(qp->head+1)&(TTY_BUF_SIZE-1)) != qp->tail)
		qp->head=new_head;
	if (qp->proc_list != NULL)
		qp->proc_list->state=0;
}

static void puts_queue(char *cp)
{
	register struct tty_queue *qp = table_list[0];
	unsigned long new_head;
	char ch;

	while (ch=*cp++) {
		qp->buf[qp->head]=ch;
		if ((new_head=(qp->head+1)&(TTY_BUF_SIZE-1))
				 != qp->tail)
			qp->head=new_head;
	}
	if (qp->proc_list != NULL)
		qp->proc_list->state=0;
}

static void ctrl(int sc)
{
	if (ke0)
		kmode|=RCTRL;
	else
		kmode|=LCTRL;
}

static void alt(int sc)
{
	if (ke0)
		kmode|=ALTGR;
	else
		kmode|=ALT;
}

static void unctrl(int sc)
{
	if (ke0)
		kmode&=(~RCTRL);
	else
		kmode&=(~LCTRL);
}

static void unalt(int sc)
{
	if (ke0)
		kmode&=(~ALTGR);
	else {
		kmode&=(~ALT);
		if (npadch != 0) {
			put_queue(npadch);
			npadch=0;
		}
	}
}

static void lshift(int sc)
{
	kmode|=LSHIFT;
}

static void unlshift(int sc)
{
	kmode&=(~LSHIFT);
}

static void rshift(int sc)
{
	kmode|=RSHIFT;
}

static void unrshift(int sc)
{
	kmode&=(~RSHIFT);
}

static void caps(int sc)
{
	if (!(kmode & CAPSDOWN)) {
		kleds ^= CAPSLED;
		kmode ^= CAPS;
		kmode |= CAPSDOWN;
		set_leds();
	}
}

void set_leds(void)
{
	if (kleds != old_leds) {
		old_leds = kleds;
		kb_wait();
		outb(0xed, 0x60);	/* set leds command */
		kb_ack();
		kb_wait();
		outb(kleds, 0x60);
		kb_ack();
	}
}

static void uncaps(int sc)
{
	kmode &= ~CAPSDOWN;
}

static void scroll(int sc)
{
	if (kmode & (LSHIFT | RSHIFT))
		show_mem();
	else
		show_state();
	kleds ^= SCRLED;
	set_leds();
}

static void num(int sc)
{
	if (kapplic)
		applkey(0x50);
	else {
		kleds ^= NUMLED;
		set_leds();
	}
}

static void applkey(int key)
{
	char buf[] = { 0x1b, 0x4f, 0x00, 0x00 };

	buf[2] = key;
	puts_queue(buf);
}


#if defined KBD_FINNISH

static unsigned char key_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0',  '+', '\'',  127,    9,
	'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',
	'o',  'p',  '}',    0,   13,    0,  'a',  's',
	'd',  'f',  'g',  'h',  'j',  'k',  'l',  '|',
	'{',    0,    0, '\'',  'z',  'x',  'c',  'v',
	'b',  'n',  'm',  ',',  '.',  '-',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0,
          0,    0,    0,    0,    0,    0,  '<',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

static unsigned char shift_map[] = {
	  0,   27,  '!', '\"',  '#',  '$',  '%',  '&',
	'/',  '(',  ')',  '=',  '?',  '`',  127,    9, 
	'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',
	'O',  'P',  ']',  '^',   13,    0,  'A',  'S',
	'D',  'F',  'G',  'H',  'J',  'K',  'L', '\\',
	'[',    0,    0,  '*',  'Z',  'X',  'C',  'V',
        'B',  'N',  'M',  ';',  ':',  '_',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0,    0,  '-',    0,    0,    0,  '+',    0,
	  0,    0,    0,    0,    0,    0,  '>',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  '@',  163,  '$',    0,    0,
        '{',   '[',  ']', '}', '\\',    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  '~',   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,  '|',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

#elif defined KBD_FINNISH_LATIN1

static unsigned char key_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0',  '+',  180,  127,    9,
	'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',
        'o',  'p',  229,  168,   13,    0,  'a',  's',
        'd',  'f',  'g',  'h',  'j',  'k',  'l',  246,
	228,  167,    0, '\'',  'z',  'x',  'c',  'v',
        'b',  'n',  'm',  ',',  '.',  '-',    0,  '*',
          0,   32,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0,
          0,    0,    0,    0,    0,    0,  '<',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };
  
static unsigned char shift_map[] = {
	  0,   27,  '!',  '"',  '#',  '$',  '%',  '&',
        '/',  '(',  ')',  '=',  '?',  '`',  127,    9,
        'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',
	'O',  'P',  197,  '^',   13,    0,  'A',  'S',
	'D',  'F',  'G',  'H',  'J',  'K',  'L',  214,
	196,  189,    0,  '*',  'Z',  'X',  'C',  'V',
	'B',  'N',  'M',  ';',  ':',  '_',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0,    0,  '-',    0,    0,    0,  '+',    0,
	  0,    0,    0,    0,    0,    0,  '>',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  '@',  163,  '$',    0,    0,
        '{',  '[',  ']',  '}', '\\',    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  '~',   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,  '|',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

#elif defined KBD_US

static unsigned char key_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0',  '-',  '=',  127,    9,
	'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',
	'o',  'p',  '[',  ']',   13,    0,  'a',  's',
	'd',  'f',  'g',  'h',  'j',  'k',  'l',  ';',
       '\'',  '`',    0, '\\',  'z',  'x',  'c',  'v',
	'b',  'n',  'm',  ',',  '.',  '/',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0, 
          0,    0,    0,    0,    0,    0,  '<',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char shift_map[] = {
	  0,   27,  '!',  '@',  '#',  '$',  '%',  '^',
	'&',  '*',  '(',  ')',  '_',  '+',  127,    9,
	'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',
	'O',  'P',  '{',  '}',   13,    0,  'A',  'S',
	'D',  'F',  'G',  'H',  'J',  'K',  'L',  ':',
        '"',  '~',  '0',  '|',  'Z',  'X',  'C',  'V',
	'B',  'N',  'M',  '<',  '>',  '?',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0, 
          0,    0,    0,    0,    0,    0,  '>',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  '@',    0,  '$',    0,    0,
        '{',   '[',  ']', '}', '\\',    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  '~',   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,  '|',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

#elif defined KBD_UK

static unsigned char key_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0',  '-',  '=',  127,    9,
	'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',
	'o',  'p',  '[',  ']',   13,    0,  'a',  's',
	'd',  'f',  'g',  'h',  'j',  'k',  'l',  ';',
       '\'',  '`',    0,  '#',  'z',  'x',  'c',  'v',
	'b',  'n',  'm',  ',',  '.',  '/',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0, 
          0,    0,    0,    0,    0,    0, '\\',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char shift_map[] = {
	  0,   27,  '!',  '"',  163,  '$',  '%',  '^',
	'&',  '*',  '(',  ')',  '_',  '+',  127,    9,
	'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',
	'O',  'P',  '{',  '}',   13,    0,  'A',  'S',
	'D',  'F',  'G',  'H',  'J',  'K',  'L',  ':',
        '@',  '~',  '0',  '~',  'Z',  'X',  'C',  'V',
	'B',  'N',  'M',  '<',  '>',  '?',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0, 
          0,    0,    0,    0,    0,    0,  '|',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  '@',    0,  '$',    0,    0,
        '{',   '[',  ']', '}', '\\',    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  '~',   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,  '|',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

#elif defined KBD_GR

static unsigned char key_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0', '\\', '\'',  127,    9,
	'q',  'w',  'e',  'r',  't',  'z',  'u',  'i',
	'o',  'p',  '@',  '+',   13,    0,  'a',  's',
	'd',  'f',  'g',  'h',  'j',  'k',  'l',  '[',
	']',  '^',    0,  '#',  'y',  'x',  'c',  'v',
	'b',  'n',  'm',  ',',  '.',  '-',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0,
          0,    0,    0,    0,    0,    0,  '<',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

static unsigned char shift_map[] = {
	  0,   27,  '!',  '"',  '#',  '$',  '%',  '&',
	'/',  '(',  ')',  '=',  '?',  '`',  127,    9, 
	'Q',  'W',  'E',  'R',  'T',  'Z',  'U',  'I',
	'O',  'P', '\\',  '*',   13,    0,  'A',  'S',
	'D',  'F',  'G',  'H',  'J',  'K',  'L',  '{',
	'}',  '~',    0, '\'',  'Y',  'X',  'C',  'V',
        'B',  'N',  'M',  ';',  ':',  '_',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0,    0,  '-',    0,    0,    0,  '+',    0,
	  0,    0,    0,    0,    0,    0,  '>',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  '@',    0,  '$',    0,    0,
        '{',   '[',  ']', '}', '\\',    0,    0,    0,
        '@',    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  '~',   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,  '|',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

#elif defined KBD_GR_LATIN1

static unsigned char key_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0', 223,  180,  127,    9,
	'q',  'w',  'e',  'r',  't',  'z',  'u',  'i',
	'o',  'p',  252,  '+',   13,    0,  'a',  's',
	'd',  'f',  'g',  'h',  'j',  'k',  'l', 246,
	228,   94,    0,  '#',  'y',  'x',  'c',  'v',
	'b',  'n',  'm',  ',',  '.',  '-',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0,
          0,    0,    0,    0,    0,    0,  '<',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

static unsigned char shift_map[] = {
	  0,   27,  '!',  '"',  167,  '$',  '%',  '&',
	'/',  '(',  ')',  '=',  '?',  '`',  127,    9, 
	'Q',  'W',  'E',  'R',  'T',  'Z',  'U',  'I',
	'O',  'P',  220,  '*',   13,    0,  'A',  'S',
	'D',  'F',  'G',  'H',  'J',  'K',  'L',  214,
        196,  176,    0, '\'',  'Y',  'X',  'C',  'V',
        'B',  'N',  'M',  ';',  ':',  '_',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0,    0,  '-',    0,    0,    0,  '+',    0,
	  0,    0,    0,    0,    0,    0,  '>',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  178,  179,  '$',    0,    0,
        '{',   '[',  ']', '}', '\\',    0,    0,    0,
        '@',    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  '~',   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  181,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,  '|',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

#elif defined KBD_FR

static unsigned char key_map[] = {
	  0,   27,  '&',  '{',  '"', '\'',  '(',  '-',
	'}',  '_',  '/',  '@',  ')',  '=',  127,    9,
	'a',  'z',  'e',  'r',  't',  'y',  'u',  'i',
	'o',  'p',  '^',  '$',   13,    0,  'q',  's',
	'd',  'f',  'g',  'h',  'j',  'k',  'l',  'm',
	'|',  '`',    0,   42,  'w',  'x',  'c',  'v',
	'b',  'n',  ',',  ';',  ':',  '!',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0,
          0,    0,    0,    0,    0,    0,  '<',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

static unsigned char shift_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0',  ']',  '+',  127,    9, 
	'A',  'Z',  'E',  'R',  'T',  'Y',  'U',  'I',
	'O',  'P',  '<',  '>',   13,    0,  'Q',  'S',
	'D',  'F',  'G',  'H',  'J',  'K',  'L',  'M',
	'%',  '~',    0,  '#',  'W',  'X',  'C',  'V',
        'B',  'N',  '?',  '.',  '/', '\\',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0,    0,  '-',    0,    0,    0,  '+',    0,
	  0,    0,    0,    0,    0,    0,  '>',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  '~',  '#',  '{',  '[',  '|',
        '`', '\\',   '^',  '@', ']',  '}',    0,    0,
        '@',    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  '~',   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,  '|',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

#elif defined KBD_FR_LATIN1

static unsigned char key_map[] = {
	  0,   27,  '&',  233,  '"', '\'',  '(',  '-',
        232,  '_',  231,  224,  ')',  '=',  127,    9,
	'a',  'z',  'e',  'r',  't',  'y',  'u',  'i',
	'o',  'p',  '^',  '$',   13,    0,  'q',  's',
	'd',  'f',  'g',  'h',  'j',  'k',  'l',  'm',
	249,  178,    0,   42,  'w',  'x',  'c',  'v',
	'b',  'n',  ',',  ';',  ':',  '!',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0,
          0,    0,    0,    0,    0,    0,  '<',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

static unsigned char shift_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0',  176,  '+',  127,    9, 
	'A',  'Z',  'E',  'R',  'T',  'Y',  'U',  'I',
	'O',  'P',  168,  163,   13,    0,  'Q',  'S',
	'D',  'F',  'G',  'H',  'J',  'K',  'L',  'M',
	'%',    0,    0,  181,  'W',  'X',  'C',  'V',
        'B',  'N',  '?',  '.',  '/',  167,    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0,    0,  '-',    0,    0,    0,  '+',    0,
	  0,    0,    0,    0,    0,    0,  '>',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  '~',  '#',  '{',  '[',  '|',
        '`', '\\',   '^',  '@', ']',  '}',    0,    0,
        '@',    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  164,   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,  '|',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

#elif defined KBD_DK

static unsigned char key_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0',  '+', '\'',  127,    9,
	'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',
	'o',  'p',  229,    0,   13,    0,  'a',  's',
	'd',  'f',  'g',  'h',  'j',  'k',  'l',  230,
	162,    0,    0, '\'',  'z',  'x',  'c',  'v',
	'b',  'n',  'm',  ',',  '.',  '-',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0,
          0,    0,    0,    0,    0,    0,  '<',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

static unsigned char shift_map[] = {
	  0,   27,  '!', '\"',  '#',  '$',  '%',  '&',
	'/',  '(',  ')',  '=',  '?',  '`',  127,    9, 
	'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',
	'O',  'P',  197,  '^',   13,    0,  'A',  'S',
	'D',  'F',  'G',  'H',  'J',  'K',  'L',  198,
	165,    0,    0,  '*',  'Z',  'X',  'C',  'V',
        'B',  'N',  'M',  ';',  ':',  '_',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0,    0,  '-',    0,    0,    0,  '+',    0,
	  0,    0,    0,    0,    0,    0,  '>',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  '@',  163,  '$',    0,    0,
        '{',   '[',  ']', '}',    0,  '|',    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  '~',   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,  '\\',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

#elif defined KBD_DK_LATIN1

static unsigned char key_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0',  '+',  180,  127,    9,
	'q',  'w',  'e',  'r',  't',  'y',  'u',  'i',
	'o',  'p',  229,  168,   13,    0,  'a',  's',
	'd',  'f',  'g',  'h',  'j',  'k',  'l',  230,
	162,  189,    0, '\'',  'z',  'x',  'c',  'v',
	'b',  'n',  'm',  ',',  '.',  '-',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,  '-',    0,    0,    0,  '+',    0,
          0,    0,    0,    0,    0,    0,  '<',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

static unsigned char shift_map[] = {
	  0,   27,  '!', '\"',  '#',  '$',  '%',  '&',
	'/',  '(',  ')',  '=',  '?',  '`',  127,    9, 
	'Q',  'W',  'E',  'R',  'T',  'Y',  'U',  'I',
	'O',  'P',  197,  '^',   13,    0,  'A',  'S',
	'D',  'F',  'G',  'H',  'J',  'K',  'L',  198,
	165,  167,    0,  '*',  'Z',  'X',  'C',  'V',
        'B',  'N',  'M',  ';',  ':',  '_',    0,  '*',
	  0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0,    0,  '-',    0,    0,    0,  '+',    0,
	  0,    0,    0,    0,    0,    0,  '>',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  '@',  163,  '$',    0,    0,
        '{',   '[',  ']', '}',    0,  '|',    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  '~',   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0, '\\',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

#elif defined KBD_DVORAK

static unsigned char key_map[] = {
	  0,   27,  '1',  '2',  '3',  '4',  '5',  '6',
	'7',  '8',  '9',  '0', '\\',  '=',  127,    9,
       '\'',  ',',  '.',  'p',  'y',  'f',  'g',  'c',
        'r',  'l',  '/',  ']',   13,    0,  'a',  'o',
	'e',  'u',  'i',  'd',  'h',  't',  'n',  's',
        '-',  '`',    0,  '[',  ';',  'q',  'j',  'k',
	'x',  'b',  'm',  'w',  'v',  'z',    0,  '*',
          0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0,    0,  '-',    0,    0,    0,  '+',    0,
	  0,    0,    0,    0,    0,    0,  '<',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0 };

static unsigned char shift_map[] = {
	  0,   27,  '!',  '@',  '#',  '$',  '%',  '^',
	'&',  '*',  '(',  ')',  '|',  '+',  127,    9,
        '"',  '<',  '>',  'P',  'Y',  'F',  'G',  'C',
	'R',  'L',  '?',  '}',   13,    0,  'A',  'O',
	'E',  'U',  'I',  'D',  'H',  'T',  'N',  'S',
	'_',  '~',    0,  '{',  ':',  'Q',  'J',  'K',
	'X',  'B',  'M',  'W',  'V',  'Z',    0,  '*',
          0,   32,    0,    0,    0,    0,    0,    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
	  0,    0,  '-',    0,    0,    0,  '+',    0,
	  0,    0,    0,    0,    0,    0,  '<',    0,
	  0,    0,    0,    0,    0,    0,    0,    0,
          0 };

static unsigned char alt_map[] = {
	  0,    0,    0,  '@',    0,  '$',    0,    0,
        '{',   '[',  ']', '}', '\\',    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,  '~',   13,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0,    0,    0,    0,    0,    0,  '|',    0,
          0,    0,    0,    0,    0,    0,    0,    0,
          0 };

#else
#error "KBD-type not defined"
#endif

static void do_self(int sc)
{
	unsigned char ch;

	if (kmode & ALTGR)
		ch = alt_map[sc];
	else if (kmode & (LSHIFT | RSHIFT | LCTRL | RCTRL))
		ch = shift_map[sc];
	else
		ch = key_map[sc];

	if (ch == 0)
		return;

	if ((ch = handle_diacr(ch)) == 0)
		return;

	if (kmode & (LCTRL | RCTRL | CAPS))	/* ctrl or caps */
		if ((ch >= 'a' && ch <= 'z') || (ch >= 224 && ch <= 254))
			ch -= 32;
	if (kmode & (LCTRL | RCTRL))		/* ctrl */
		ch &= 0x1f;

	if (kmode & ALT)
		if (kbd_flags & NO_META_BIT) {
			put_queue('\033');
			put_queue(ch);
		} else
			put_queue(ch|0x80);
	else
		put_queue(ch);
}

unsigned char accent_table[5][64] = {
	" \300BCD\310FGH\314JKLMN\322PQRST\331VWXYZ[\\]^_"
	"`\340bcd\350fgh\354jklmn\362pqrst\371vwxyz{|}~",   /* accent grave */

	" \301BCD\311FGH\315JKLMN\323PQRST\332VWX\335Z[\\]^_"
	"`\341bcd\351fgh\355jklmn\363pqrst\372vwxyz{|}~",   /* accent acute */

	" \302BCD\312FGH\316JKLMN\324PQRST\333VWXYZ[\\]^_"
	"`\342bcd\352fgh\356jklmn\364pqrst\373vwxyz{|}~",   /* circumflex */

	" \303BCDEFGHIJKLMN\325PQRSTUVWXYZ[\\]^_"
	"`\343bcdefghijklm\361\365pqrstuvwxyz{|}~",	    /* tilde */

	" \304BCD\313FGH\316JKLMN\326PQRST\334VWXYZ[\\]^_"
	"`\344bcd\353fgh\357jklmn\366pqrst\374vwx\377z{|}~" /* dieresis */
};


/*
 * Check if dead key pressed. If so, check if same key pressed twice;
 * in that case return the char, otherwise store char and return 0.
 * If dead key not pressed, check if accented character pending. If
 * not: return the char, otherwise check if char is a space. If it is
 * a space return the diacritical. Else combine char with diacritical
 * mark and return.
 */

unsigned int handle_diacr(unsigned int ch)
{
	static unsigned char diacr_table[] =
		{'`', 180, '^', '~', 168, 0};           /* Must end with 0 */
	int i;

	for(i=0; diacr_table[i]; i++)
		if (ch==diacr_table[i] && ((1<<i)&kbd_flags)) {
			if (diacr == i) {
				diacr=-1;
				return ch;		/* pressed twice */
			} else {
				diacr=i;		/* key is dead */
				return 0;
			}
		}
	if (diacr == -1)
		return ch;
	else if (ch == ' ') {
		ch=diacr_table[diacr];
		diacr=-1;
		return ch;
	} else if (ch<64 || ch>122) {
		diacr=-1;
		return ch;
	} else {
		ch=accent_table[diacr][ch-64];
		diacr=-1;
		return ch;
	}
}
		

#if defined KBD_FR || defined KBD_US
static unsigned char num_table[] = "789-456+1230.";
#else
static unsigned char num_table[] = "789-456+1230,";
#endif

static unsigned char cur_table[] = "HA5-DGC+YB623";
static unsigned int pad_table[] = { 7,8,9,0,4,5,6,0,1,2,3,0,0 };

/*	
    Keypad /         		35	B7	Q
    Keypad *  (PrtSc)		37	B7	R
    Keypad NumLock     		45	??	P
    Keypad 7  (Home)		47	C7	w
    Keypad 8  (Up arrow)	48	C8	x
    Keypad 9  (PgUp)		49	C9	y
    Keypad -			4A	CA	S
    Keypad 4  (Left arrow)	4B	CB	t
    Keypad 5			4C	CC	u
    Keypad 6  (Right arrow)	4D	CD	v
    Keypad +			4E	CE	l
    Keypad 1  (End) 		4F	CF	q
    Keypad 2  (Down arrow)	50	D0	r
    Keypad 3  (PgDn)		51	D1	s
    Keypad 0  (Ins)		52	D2	p
    Keypad .  (Del) 		53	D3	n
*/    

static unsigned char appl_table[] = "wxyStuvlqrspn";

static char *func_table[] = {
	"\033[[A", "\033[[B", "\033[[C", "\033[[D",
	"\033[[E", "\033[[F", "\033[[G", "\033[[H",
	"\033[[I", "\033[[J", "\033[[K", "\033[[L" 
};


static void cursor(int sc)
{
	if (sc < 0x47 || sc > 0x53)
		return;
	sc-=0x47;
	if (sc == 12 && (kmode&(LCTRL|RCTRL)) && (kmode&(ALT|ALTGR))) {
		ctrl_alt_del();
		return;
	}
	if (ke0 == 1) {
		cur(sc);
		return;
	}

	if ((kmode&ALT) && sc!=12) {		      /* Alt-numpad */
		npadch=npadch*10+pad_table[sc];
		return;
	}

	if (kapplic && !(kmode&(LSHIFT|RSHIFT))) {    /* shift forces cursor */
		applkey(appl_table[sc]);
		return;
	}

	if (kleds&NUMLED) {
		put_queue(num_table[sc]);
	} else
		cur(sc);
}

static void cur(int sc)
{
	char buf[] = { 0x1b, '[', 0, 0, 0 };          /* must not be static */

	buf[2]=cur_table[sc];
	if (buf[2] < '9')
		buf[3]='~';
	if ((buf[2] >= 'A' && buf[2] <= 'D') ? ckmode : kapplic)
		buf[1]='O';
	puts_queue(buf);
}

static void func(int sc)
{
	if (sc < 0x3b)
		return;
	sc-=0x3b;
	if (sc > 9) {
		sc-=18;
		if (sc < 10 || sc > 11)
			return;
	}
	if (kmode&ALT)
		change_console(sc);
	else
		puts_queue(func_table[sc]);
}	
	

static void slash(int sc)
{
	if (ke0 != 1)
		do_self(sc);
	else if (kapplic)
		applkey('Q');
	else
		put_queue('/');
}

static void star(int sc)
{
	if (kapplic)
		applkey('R');
	else
		do_self(sc);
}

static void enter(int sc)
{
	if (ke0 == 1 && kapplic)
		applkey('M');
	else {
		put_queue(13);
		if (lfnlmode)
			put_queue(10);
	}
}

static void minus(int sc)
{
	if (kapplic)
		applkey('S');
	else
		do_self(sc);
}

static void plus(int sc)
{
	if (kapplic)
		applkey('l');
	else
		do_self(sc);
}


static void none(int sc)
{
}


/*
 * kb_wait waits for the keyboard controller buffer to empty.
 */

static void kb_wait(void)
{
	int i;

	for (i=0; i<0x10000; i++)
		if ((inb(0x64)&0x02) == 0)
			break;
}

/*
 * kb_ack waits for 0xfa to appear in port 0x60
 *
 * Suggested by Bruce Evans
 * Added by Niels Skou Olsen [NSO]
 * April 21, 1992
 *
 * Heavily inspired by kb_wait :-)
 * I don't know how much waiting actually is required,
 * but this seems to work
 */

void kb_ack(void)
{
	int i;

	for(i=0; i<0x10000; i++)
		if (inb(0x60) == 0xfa)
			break;
}

long no_idt[2] = {0, 0};

/*
 * This routine reboots the machine by asking the keyboard
 * controller to pulse the reset-line low. We try that for a while,
 * and if it doesn't work, we do some other stupid things.
 */
void hard_reset_now(void)
{
	int i;

	sti();
	for (;;) {
		for (i=0; i<100; i++) {
			kb_wait();
			*((unsigned short *)0x472)=0x1234;
			outb(0xfe,0x64);	 /* pulse reset low */
		}
		__asm__("\tlidt _no_idt"::);
	}
}
	

static fptr key_table[] = {
	none,do_self,do_self,do_self,		/* 00-03 s0 esc 1 2 */
	do_self,do_self,do_self,do_self,	/* 04-07 3 4 5 6 */
	do_self,do_self,do_self,do_self,	/* 08-0B 7 8 9 0 */
	do_self,do_self,do_self,do_self,	/* 0C-0F + ' bs tab */
	do_self,do_self,do_self,do_self,	/* 10-13 q w e r */
	do_self,do_self,do_self,do_self,	/* 14-17 t y u i */
	do_self,do_self,do_self,do_self,	/* 18-1B o p } ^ */
	enter,ctrl,do_self,do_self,		/* 1C-1F enter ctrl a s */
	do_self,do_self,do_self,do_self,	/* 20-23 d f g h */
	do_self,do_self,do_self,do_self,	/* 24-27 j k l | */
	do_self,do_self,lshift,do_self,		/* 28-2B { para lshift , */
	do_self,do_self,do_self,do_self,	/* 2C-2F z x c v */
	do_self,do_self,do_self,do_self,	/* 30-33 b n m , */
	do_self,slash,rshift,star,		/* 34-37 . - rshift * */
	alt,do_self,caps,func,			/* 38-3B alt sp caps f1 */
	func,func,func,func,			/* 3C-3F f2 f3 f4 f5 */
	func,func,func,func,			/* 40-43 f6 f7 f8 f9 */
	func,num,scroll,cursor,			/* 44-47 f10 num scr home */
	cursor,cursor,minus,cursor,		/* 48-4B up pgup - left */
	cursor,cursor,plus,cursor,		/* 4C-4F n5 right + end */
	cursor,cursor,cursor,cursor,		/* 50-53 dn pgdn ins del */
	none,none,do_self,func,			/* 54-57 sysreq ? < f11 */
	func,none,none,none,			/* 58-5B f12 ? ? ? */
	none,none,none,none,			/* 5C-5F ? ? ? ? */
	none,none,none,none,			/* 60-63 ? ? ? ? */
	none,none,none,none,			/* 64-67 ? ? ? ? */
	none,none,none,none,			/* 68-6B ? ? ? ? */
	none,none,none,none,			/* 6C-6F ? ? ? ? */
	none,none,none,none,			/* 70-73 ? ? ? ? */
	none,none,none,none,			/* 74-77 ? ? ? ? */
	none,none,none,none,			/* 78-7B ? ? ? ? */
	none,none,none,none,			/* 7C-7F ? ? ? ? */
	none,none,none,none,			/* 80-83 ? br br br */
	none,none,none,none,			/* 84-87 br br br br */
	none,none,none,none,			/* 88-8B br br br br */
	none,none,none,none,			/* 8C-8F br br br br */
	none,none,none,none,			/* 90-93 br br br br */
	none,none,none,none,			/* 94-97 br br br br */
	none,none,none,none,			/* 98-9B br br br br */
	none,unctrl,none,none,			/* 9C-9F br unctrl br br */
	none,none,none,none,			/* A0-A3 br br br br */
	none,none,none,none,			/* A4-A7 br br br br */
	none,none,unlshift,none,		/* A8-AB br br unlshift br */
	none,none,none,none,			/* AC-AF br br br br */
	none,none,none,none,			/* B0-B3 br br br br */
	none,none,unrshift,none,		/* B4-B7 br br unrshift br */
	unalt,none,uncaps,none,			/* B8-BB unalt br uncaps br */
	none,none,none,none,			/* BC-BF br br br br */
	none,none,none,none,			/* C0-C3 br br br br */
	none,none,none,none,			/* C4-C7 br br br br */
	none,none,none,none,			/* C8-CB br br br br */
	none,none,none,none,			/* CC-CF br br br br */
	none,none,none,none,			/* D0-D3 br br br br */
	none,none,none,none,			/* D4-D7 br br br br */
	none,none,none,none,			/* D8-DB br ? ? ? */
	none,none,none,none,			/* DC-DF ? ? ? ? */
	none,none,none,none,			/* E0-E3 e0 e1 ? ? */
	none,none,none,none,			/* E4-E7 ? ? ? ? */
	none,none,none,none,			/* E8-EB ? ? ? ? */
	none,none,none,none,			/* EC-EF ? ? ? ? */
	none,none,none,none,			/* F0-F3 ? ? ? ? */
	none,none,none,none,			/* F4-F7 ? ? ? ? */
	none,none,none,none,			/* F8-FB ? ? ? ? */
	none,none,none,none			/* FC-FF ? ? ? ? */
};