* linux/drivers/char/pc_keyb.c
* Combined the keyboard and PS/2 mouse handling into one file,
*/
#include <linux/config.h>
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/mm.h>
#include <linux/signal.h>
#include <linux/init.h>
#include <linux/kbd_ll.h>
#include <linux/delay.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/miscdevice.h>
#include <linux/malloc.h>
#include <linux/kbd_kern.h>
#include <linux/smp_lock.h>
#include <asm/keyboard.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/io.h>
#include <linux/pc_keyb.h>
#ifdef CONFIG_MAGIC_SYSRQ
unsigned char pckbd_sysrq_xlate[128] =
"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 -
0x5f */
#endif
#ifdef CONFIG_PSMOUSE
#endif
/*
*/
#endif /* CONFIG_PSMOUSE */
/*
*
* Don't use 'jiffies' so that we don't depend on
* interrupts..
* "Address hex 0060 and address hex 0064 should be written only when
*/
do {
/*
*/
return;
mdelay(1);
timeout--;
} while (timeout);
#ifdef KBD_REPORT_TIMEOUTS
#endif
/*
*/
#define E0_KPENTER 96
#define E0_RCTRL 97
#define E0_KPSLASH 98
#define E0_PRSCR 99
/*
* They could be thrown away (and all occurrences below replaced by 0),
* but that would force many users to use the `setkeycodes' utility, where
* they needed not before. It does not matter that there are duplicates, as
*/
#define SC_LIM 89
#define FOCUS_PF2 89
#define FOCUS_PF3 90
#define FOCUS_PF4 91
#define FOCUS_PF5 92
#define FOCUS_PF6 93
#define FOCUS_PF7 94
#define FOCUS_PF8 95
/* tfj@olivia.ping.dk:
* The four keys are located over the numeric keypad, and are
*/
0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
};
/* BTC */
/* LK450 */
/*
*/
/*
*/
0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0f */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2f */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */
0, 0, 0, 0, 0, 0, 0, E0_MACRO, /* 0x68-0x6f */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */
0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7f */
};
return -EINVAL;
if (scancode < 128)
else
return 0;
return
e0_keys[scancode - 128];
if (reply_expected) {
* are some brain-damaged keyboards (yes, FOCUS 9000 again) which have
*/
if (scancode == KBD_REPLY_ACK) {
acknowledge = 1;
reply_expected = 0;
return 0;
resend = 1;
reply_expected = 0;
return 0;
#if 0
scancode);
#endif
return 1;
char raw_mode)
prev_scancode = scancode;
return 0;
}
prev_scancode = 0;
return 0;
if (prev_scancode) {
/*
*/
if (prev_scancode != 0xe0) {
prev_scancode = 0x100;
return 0;
*keycode = E1_PAUSE;
prev_scancode = 0;
} else {
#ifdef KBD_REPORT_UNKN
if (!raw_mode)
printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
#endif
prev_scancode = 0;
return 0;
} else {
prev_scancode = 0;
/*
*/
/*
*/
return 0;
if (e0_keys[scancode])
*keycode = e0_keys[scancode];
else {
#ifdef KBD_REPORT_UNKN
if (!raw_mode)
scancode);
#endif
return 0;
55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
if (!*keycode) {
if (!raw_mode) {
#ifdef KBD_REPORT_UNKN
printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
#endif
return 0;
} else
*keycode = scancode;
return 1;
/* unexpected, but this can happen: maybe this was a key release for a
return 0;
else
return 0200;
/*PPC*/
#ifdef CONFIG_CUECAT_MODULE
#include <linux/module.h>
EXPORT_SYMBOL(handle_keyboard_event);
EXPORT_SYMBOL(handle_mouse_event);
#endif
#include <linux/cuecat_driver.h>
#else
/*\PPC*/
/*PPC*/
#endif
/*\PPC*/
#ifdef CONFIG_PSMOUSE
if (mouse_reply_expected) {
if (scancode == AUX_ACK) {
mouse_reply_expected--;
return;
mouse_reply_expected = 0;
}
else if(scancode == AUX_RECONNECT){
return;
add_mouse_randomness(scancode);
if (aux_count) {
queue->buf[head] = scancode;
if (head != queue->tail) {
queue->head = head;
wake_up_interruptible(&queue->proc_list);
#endif
/*PPC*/
#else
/*\PPC*/
/*PPC*/
#endif
/*\PPC*/
#ifdef CONFIG_VT
kbd_exists = 1;
if (do_acknowledge(scancode))
#endif
tasklet_schedule(&keyboard_tasklet);
/*
* appropriate action.
* spinlock.
*/
{
unsigned char status = kbd_read_status();
scancode = kbd_read_input();
#if 1
#endif
/*PPC*/
#ifdef CONFIG_CUECAT_MODULE
if(cuecat_pckeyb_scancode_processor!=NULL)
if(!cuecat_pckeyb_scancode_processor(
scancode,CUECAT_PSMOUSE))
handle_mouse_event(scancode);
}
else
handle_mouse_event(scancode);
#else
#ifdef CONFIG_CUECAT
if(!cuecat_process_scancode(scancode,
CUECAT_PSMOUSE))
handle_mouse_event(scancode);
#else
handle_mouse_event(scancode);
#endif
#endif
/*\PPC*/
/*PPC handle_mouse_event(scancode);*/
else
/*PPC*/
#ifdef CONFIG_CUECAT_MODULE
if(cuecat_pckeyb_scancode_processor!=NULL)
if(!cuecat_pckeyb_scancode_processor
(scancode,CUECAT_PCKBD))
handle_keyboard_event(scancode);
}
else
handle_keyboard_event(scancode);
#else
#ifdef CONFIG_CUECAT
if(!cuecat_process_scancode(scancode,
CUECAT_PCKBD))
handle_keyboard_event(scancode);
#else
handle_keyboard_event(scancode);
#endif
#endif
/*\PPC*/
/*PPC handle_keyboard_event(scancode);*/
status = kbd_read_status();
if (!work)
#ifdef CONFIG_VT
kbd_pt_regs = regs;
#endif
spin_lock_irq(&kbd_controller_lock);
handle_kbd_event();
spin_unlock_irq(&kbd_controller_lock);
/*
*/
int retries = 3;
do {
resend = 0;
reply_expected = 1;
kbd_write_output_w(data);
for (;;) {
if (acknowledge)
return 1;
if (resend)
break;
mdelay(1);
if (!--timeout) {
#ifdef KBD_REPORT_TIMEOUTS
#endif
return 0;
#ifdef KBD_REPORT_TIMEOUTS
#endif
return 0;
kbd_exists = 0;
/*
* [Ranger]
*/
#ifdef __i386__
#else
#endif
/* for "kbd-reset" cmdline param */
kbd_startup_reset = 1;
return 1;
__setup("kbd-reset", kbd_reset_setup);
status = kbd_read_status();
retval = data;
retval = KBD_BAD_DATA;
}
return retval;
do {
if (kbd_read_data() == KBD_NO_DATA)
break;
} while (--maxread);
do {
if (retval >= 0)
return retval;
mdelay(1);
} while (--timeout);
return -1;
}
spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_command(data);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_output(data);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
{
unsigned long flags;
spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_MODE);
kb_wait();
kbd_write_output(cmd);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
#endif /* CONFIG_PSMOUSE */
int status;
/*
*/
kbd_write_command_w(KBD_CCMD_SELF_TEST);
if (kbd_wait_for_input() != 0x55)
/*
* Perform a keyboard interface test. This causes the controller
* to test the keyboard clock and data lines. The results of the
*/
kbd_write_command_w(KBD_CCMD_KBD_TEST);
if (kbd_wait_for_input() != 0x00)
/*
*/
kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
/*
*/
do {
kbd_write_output_w(KBD_CMD_RESET);
status = kbd_wait_for_input();
if (status == KBD_REPLY_ACK)
break;
if (status != KBD_REPLY_RESEND)
} while (1);
if (kbd_wait_for_input() != KBD_REPLY_POR)
/*
*/
do {
kbd_write_output_w(KBD_CMD_DISABLE);
status = kbd_wait_for_input();
if (status == KBD_REPLY_ACK)
break;
if (status != KBD_REPLY_RESEND)
} while (1);
kbd_write_command_w(KBD_CCMD_WRITE_MODE);
kbd_write_output_w(KBD_MODE_KBD_INT
| KBD_MODE_SYS
| KBD_MODE_DISABLE_MOUSE
| KBD_MODE_KCC);
kbd_write_command_w(KBD_CCMD_READ_MODE);
/*
*/
kbd_write_output_w(0xF0);
kbd_wait_for_input();
kbd_write_output_w(0x01);
kbd_wait_for_input();
kbd_write_output_w(KBD_CMD_ENABLE);
if (kbd_wait_for_input() != KBD_REPLY_ACK)
/*
*/
kbd_write_output_w(KBD_CMD_SET_RATE);
if (kbd_wait_for_input() != KBD_REPLY_ACK)
kbd_write_output_w(0x00);
if (kbd_wait_for_input() != KBD_REPLY_ACK)
return NULL;
kbd_request_region();
kbd_clear_input();
if (kbd_startup_reset) {
if (msg)
psaux_init();
#endif
kbd_request_irq(keyboard_interrupt);
/*
*/
int retval = 0;
if (aux_device_present == 0xaa)
return 1;
spin_lock_irqsave(&kbd_controller_lock, flags);
/* Put the value 0x5A in the output buffer using the "Write
*/
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
kb_wait();
do {
(void) kbd_read_input();
retval = 1;
break;
mdelay(1);
} while (--loops);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
return retval;
/*
*/
spin_lock_irqsave(&kbd_controller_lock, flags);
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_MOUSE);
kb_wait();
kbd_write_output(val);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
/*
*/
kb_wait();
kbd_write_command(KBD_CCMD_WRITE_MOUSE);
kb_wait();
kbd_write_output(val);
mouse_reply_expected++;
kb_wait();
spin_lock_irqsave(&kbd_controller_lock, flags);
__aux_write_ack(val);
spin_unlock_irqrestore(&kbd_controller_lock, flags);
spin_lock_irqsave(&kbd_controller_lock, flags);
result = queue->buf[queue->tail];
return result;
int retval;
if (retval < 0)
return retval;
return 0;
/*
*/
lock_kernel();
if (--aux_count) {
unlock_kernel();
return 0;
kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
aux_free_irq(AUX_DEV);
unlock_kernel();
return 0;
/*
*/
if (aux_count++) {
return 0;
}
if (aux_request_irq(keyboard_interrupt, AUX_DEV)) {
aux_count--;
return -EBUSY;
auxiliary port on
controller. */
return 0;
/*
*/
DECLARE_WAITQUEUE(wait, current);
ssize_t i = count;
unsigned char c;
if (queue_empty()) {
return -EAGAIN;
add_wait_queue(&queue->proc_list, &wait);
repeat:
set_current_state(TASK_INTERRUPTIBLE);
schedule();
goto repeat;
current->state = TASK_RUNNING;
remove_wait_queue(&queue->proc_list, &wait);
c = get_from_queue();
put_user(c, buffer++);
i--;
if (count-i) {
file->f_dentry->d_inode->i_atime = CURRENT_TIME;
return count-i;
}
if (signal_pending(current))
return -ERESTARTSYS;
return 0;
/*
*/
ssize_t retval = 0;
if (count) {
ssize_t written = 0;
do {
char c;
get_user(c, buffer++);
aux_write_dev(c);
written++;
} while (--count);
retval = -EIO;
if (written) {
retval = written;
file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
return retval;
if (!queue_empty())
return 0;
read: read_aux,
write: write_aux,
poll: aux_poll,
open: open_aux,
release:release_aux,
fasync: fasync_aux,
};
/*
* Initialize driver.
*/
};
if (!detect_auxiliary_port())
return -EIO;
misc_register(&psaux_mouse);
memset(queue, 0, sizeof(*queue));
queue->head = queue->tail = 0;
init_waitqueue_head(&queue->proc_list);
#ifdef INITIALIZE_MOUSE
aux_write_ack(AUX_SET_SAMPLE);
#endif /* INITIALIZE_MOUSE */
return 0;
#endif /* CONFIG_PSMOUSE */