📄 pc_keyb.c
字号:
* Set up to try again if the keyboard asks for RESEND. */ do { kbd_write_output_w(KBD_CMD_RESET); status = kbd_wait_for_input(); if (status == KBD_REPLY_ACK) break; if (status != KBD_REPLY_RESEND) return "Keyboard reset failed, no ACK"; } while (1); if (kbd_wait_for_input() != KBD_REPLY_POR) return "Keyboard reset failed, no POR"; /* * Set keyboard controller mode. During this, the keyboard should be * in the disabled state. * * Set up to try again if the keyboard asks for RESEND. */ do { kbd_write_output_w(KBD_CMD_DISABLE); status = kbd_wait_for_input(); if (status == KBD_REPLY_ACK) break; if (status != KBD_REPLY_RESEND) return "Disable keyboard: no ACK"; } 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); /* ibm powerpc portables need this to use scan-code set 1 -- Cort */ if (!(kbd_write_command_w_and_wait(KBD_CCMD_READ_MODE) & KBD_MODE_KCC)) { /* * If the controller does not support conversion, * Set the keyboard to scan-code set 1. */ kbd_write_output_w(0xF0); kbd_wait_for_input(); kbd_write_output_w(0x01); kbd_wait_for_input(); } if (kbd_write_output_w_and_wait(KBD_CMD_ENABLE) != KBD_REPLY_ACK) return "Enable keyboard: no ACK"; /* * Finally, set the typematic rate to maximum. */ if (kbd_write_output_w_and_wait(KBD_CMD_SET_RATE) != KBD_REPLY_ACK) return "Set rate: no ACK"; if (kbd_write_output_w_and_wait(0x00) != KBD_REPLY_ACK) return "Set rate: no 2nd ACK"; return NULL;}#if 0void __init pckbd_init_hw(void){ if (!kbd_controller_present()) { kbd_exists = 0; return; } kbd_request_region(); /* Flush any pending input. */ kbd_clear_input(); if (kbd_startup_reset) { char *msg = initialize_kbd(); if (msg) printk(KERN_WARNING "initialize_kbd: %s\n", msg); }#if defined CONFIG_PSMOUSE psaux_init();#endif kbd_rate = pckbd_rate; /* Ok, finally allocate the IRQ, and off we go.. */ kbd_request_irq(keyboard_interrupt);}#elsevoid __init pckbd_init_hw(void){ /* Reset the keyboard state machine. */ unsigned char tmp; unsigned int i; wb977_open(); wb977_device_select(5); wb977_ww(0x60, 0x0060); wb977_ww(0x62, 0x0064); wb977_wb(0x70, 1); wb977_wb(0x72, 12); wb977_wb(0xf0, 0x80); wb977_device_enable(); wb977_close(); wb977_kbc_wb(0xae); //enable kb interface wb977_kbc_wb(0xaa); tmp = wb977_kbc_rb(); if(tmp==0x55) wb977_kbc_wbsys(0x4f); //enable kb interrupt k_setkeycode = pckbd_setkeycode; k_getkeycode = pckbd_getkeycode; k_translate = pckbd_translate; k_unexpected_up = pckbd_unexpected_up; k_leds = pckbd_leds;#ifdef CONFIG_MAGIC_SYSRQ k_sysrq_key = 0x54; k_sysrq_xlate = pckbd_sysrq_xlate;#endif if (request_irq (IRQ_KEY, keyboard_interrupt, 0, "keyboard", NULL) != 0) panic("Could not allocate keyboard receive IRQ!");#if defined CONFIG_PSMOUSE psaux_init();#endif return 0;}#endif#if defined CONFIG_PSMOUSEstatic int __init aux_reconnect_setup (char *str){ aux_reconnect = 1; return 1;}__setup("psaux-reconnect", aux_reconnect_setup);/* * Check if this is a dual port controller. */static int __init detect_auxiliary_port(void){ unsigned long flags; int loops = 10; int retval = 0; /* Check if the BIOS detected a device on the auxiliary port. */ 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 * Auxiliary Device Output Buffer" command (0xD3). Poll the * Status Register for a while to see if the value really * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF * bit is also set to 1 in the Status Register, we assume this * controller has an Auxiliary Port (a.k.a. Mouse Port). */ kb_wait(); kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF); kb_wait(); kbd_write_output(0x5a); /* 0x5a is a random dummy value. */ do { unsigned char status = kbd_read_status(); if (status & KBD_STAT_OBF) { (void) kbd_read_input(); if (status & KBD_STAT_MOUSE_OBF) { printk(KERN_INFO "Detected PS/2 Mouse Port.\n"); retval = 1; } break; } mdelay(1); } while (--loops); spin_unlock_irqrestore(&kbd_controller_lock, flags); return retval;}/* * Send a byte to the mouse. */static void aux_write_dev(int val){ unsigned long flags; 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);}/* * Send a byte to the mouse & handle returned ack */static void __aux_write_ack(int val){ kb_wait(); kbd_write_command(KBD_CCMD_WRITE_MOUSE); kb_wait(); kbd_write_output(val); /* we expect an ACK in response. */ mouse_reply_expected++; kb_wait();}static void aux_write_ack(int val){ unsigned long flags; spin_lock_irqsave(&kbd_controller_lock, flags); __aux_write_ack(val); spin_unlock_irqrestore(&kbd_controller_lock, flags);}static unsigned char get_from_queue(void){ unsigned char result; unsigned long flags; spin_lock_irqsave(&kbd_controller_lock, flags); result = queue->buf[queue->tail]; queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1); spin_unlock_irqrestore(&kbd_controller_lock, flags); return result;}static inline int queue_empty(void){ return queue->head == queue->tail;}static int fasync_aux(int fd, struct file *filp, int on){ int retval; retval = fasync_helper(fd, filp, on, &queue->fasync); if (retval < 0) return retval; return 0;}/* * Random magic cookie for the aux device */#define AUX_DEV ((void *)queue)static int release_aux(struct inode * inode, struct file * file){ lock_kernel(); fasync_aux(-1, file, 0); if (--aux_count) { unlock_kernel(); return 0; } kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints */ kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE); aux_free_irq(AUX_DEV); unlock_kernel(); return 0;}/* * Install interrupt handler. * Enable auxiliary device. */static int open_aux(struct inode * inode, struct file * file){ if (aux_count++) { return 0; } queue->head = queue->tail = 0; /* Flush input queue */ if (aux_request_irq(keyboard_interrupt, AUX_DEV)) { aux_count--; return -EBUSY; } kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable the auxiliary port on controller. */ aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */ kbd_write_cmd(AUX_INTS_ON); /* Enable controller ints */ mdelay(2); /* Ensure we follow the kbc access delay rules.. */ send_data(KBD_CMD_ENABLE); /* try to workaround toshiba4030cdt problem */ return 0;}/* * Put bytes from input queue to buffer. */static ssize_t read_aux(struct file * file, char * buffer, size_t count, loff_t *ppos){ DECLARE_WAITQUEUE(wait, current); ssize_t i = count; unsigned char c; if (queue_empty()) { if (file->f_flags & O_NONBLOCK) return -EAGAIN; add_wait_queue(&queue->proc_list, &wait);repeat: set_current_state(TASK_INTERRUPTIBLE); if (queue_empty() && !signal_pending(current)) { schedule(); goto repeat; } current->state = TASK_RUNNING; remove_wait_queue(&queue->proc_list, &wait); } while (i > 0 && !queue_empty()) { 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;}/* * Write to the aux device. */static ssize_t write_aux(struct file * file, const char * buffer, size_t count, loff_t *ppos){ ssize_t retval = 0; if (count) { ssize_t written = 0; if (count > 32) count = 32; /* Limit to 32 bytes. */ 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;}/* No kernel lock held - fine */static unsigned int aux_poll(struct file *file, poll_table * wait){ poll_wait(file, &queue->proc_list, wait); if (!queue_empty()) return POLLIN | POLLRDNORM; return 0;}struct file_operations psaux_fops = { read: read_aux, write: write_aux, poll: aux_poll, open: open_aux, release: release_aux, fasync: fasync_aux,};/* * Initialize driver. */static struct miscdevice psaux_mouse = { PSMOUSE_MINOR, "psaux", &psaux_fops};static int __init psaux_init(void){ int retval; if (!detect_auxiliary_port()) return -EIO; if ((retval = misc_register(&psaux_mouse))) return retval; queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL); if (queue == NULL) { printk(KERN_ERR "psaux_init(): out of memory\n"); misc_deregister(&psaux_mouse); return -ENOMEM; } memset(queue, 0, sizeof(*queue)); queue->head = queue->tail = 0; init_waitqueue_head(&queue->proc_list);#ifdef INITIALIZE_MOUSE kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */ aux_write_ack(AUX_SET_SAMPLE); aux_write_ack(100); /* 100 samples/sec */ aux_write_ack(AUX_SET_RES); aux_write_ack(3); /* 8 counts per mm */ aux_write_ack(AUX_SET_SCALE21); /* 2:1 scaling */#endif /* INITIALIZE_MOUSE */ kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */ kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */ return 0;}#endif /* CONFIG_PSMOUSE */static int blink_frequency = HZ/2;/* Tell the user who may be running in X and not see the console that we have panic'ed. This is to distingush panics from "real" lockups. Could in theory send the panic message as morse, but that is left as an exercise for the reader. */ void panic_blink(void){ static unsigned long last_jiffie; static char led; /* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is different. */ if (!blink_frequency) return; if (jiffies - last_jiffie > blink_frequency) { led ^= 0x01 | 0x04; while (kbd_read_status() & KBD_STAT_IBF) mdelay(1); kbd_write_output(KBD_CMD_SET_LEDS); mdelay(1); while (kbd_read_status() & KBD_STAT_IBF) mdelay(1); mdelay(1); kbd_write_output(led); last_jiffie = jiffies; }} static int __init panicblink_setup(char *str){ int par; if (get_option(&str,&par)) blink_frequency = par*(1000/HZ); return 1;}/* panicblink=0 disables the blinking as it caused problems with some console switches. otherwise argument is ms of a blink period. */__setup("panicblink=", panicblink_setup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -