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

📄 pc_keyb.c

📁 linux下驱动winbond 839977EF的键盘和鼠标控制器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * linux/drivers/char/pc_keyb.c * * Separation of the PC low-level part by Geert Uytterhoeven, May 1997 * See keyboard.c for the whole history. * * Major cleanup by Martin Mares, May 1997 * * Combined the keyboard and PS/2 mouse handling into one file, * because they share the same hardware. * Johan Myreen <jem@iki.fi> 1998-10-08. * * Code fixes to handle mouse ACKs properly. * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29. * */#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/slab.h>#include <linux/kbd_kern.h>#include <linux/vt_kern.h>#include <linux/smp_lock.h>#include <linux/kd.h>#include <linux/pm.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>/* Some configuration switches are present in the include file... */#include <linux/pc_keyb.h>/* Simple translation table for the SysRq keys *//***********************************************************    cao   add  ************************************************************************/#define AUX_IRQ 32#define aux_request_irq(hand, dev_id)                                   \        request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)#define WB977BASE  SIO_BASE_VIRT  #define SEL	  0x3f0#define	outbm(val,port)		*((volatile unsigned char  *)(WB977BASE+((port)<<2))) = (unsigned char)(val)#define	inbm(port)		*((volatile unsigned char  *)(WB977BASE+((port)<<2)))#define  kbd_read_status()      inbm(0x64)#define  kbd_read_input()       inbm(0x60)#define  kbd_write_output(val)  outbm(val, 0x60)#define  kbd_write_command(val) outbm(val, 0x64)static void wb977_open(void){	outbm(0x87,SEL);	outbm(0x87,SEL);}static void wb977_close(void){	outbm(0xaa,SEL);}static void wb977_wb(int reg, int val){	outbm(reg,SEL);	outbm(val,SEL+1);}static void wb977_ww(int reg, int val){	outbm(reg,SEL);	outbm(val >> 8,SEL+1);	outbm(reg + 1,SEL);	outbm(val,SEL+1);}static int wb977_kbc_rb(void){	int timeout=0xffffff;	while(timeout-->0){		if(inbm(0x64)&0x01)			return inbm(0x60);	}	return -1;;}static int wb977_kbc_wb(int cmd){	int timeout=0xfffff;	while(timeout-->0){		if(!(inbm(0x64)&0x02)){			outbm(cmd,0x64);			return 0;		}	}	return -1;}static int wb977_kbc_mouse_wb(int cmd){	int timeout=0xfffff;	while(timeout-->0){		if(!(inbm(0x64)&0x02)){			outbm(0x60,0x64); //direct to auxiliary			while(inbm(0x64)&0x02);			outbm(0xd4,0x64);					outbm(cmd,0x60);			return 0;		}	}	return -1;}static int wb977_kbc_rbsys(void){	if(wb977_kbc_wb(0x20)==0){		return wb977_kbc_rb();		}	else return -1;}static int wb977_kbc_wbsys(int parm){	int timeout=0xfffff;	while(timeout-->0){		if(!(inbm(0x64)&0x02)){			outbm(0x60,0x64);			while(inbm(0x64)&0x02);			outbm(parm,0x60);			return 0;		}	}	return -1;}#define wb977_device_select(dev)	wb977_wb(0x07, dev)#define wb977_device_disable()		wb977_wb(0x30, 0x00)#define wb977_device_enable()		wb977_wb(0x30, 0x01)/***********************************************************    cao   add  end  *******************************************************************/#ifdef CONFIG_MAGIC_SYSRQunsigned char pckbd_sysrq_xlate[128] =	"\000\0331234567890-=\177\t"			/* 0x00 - 0x0f */	"qwertyuiop[]\r\000as"				/* 0x10 - 0x1f */	"dfghjkl;'`\000\\zxcv"				/* 0x20 - 0x2f */	"bnm,./\000*\000 \000\201\202\203\204\205"	/* 0x30 - 0x3f */	"\206\207\210\211\212\000\000789-456+1"		/* 0x40 - 0x4f */	"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */	"\r\000/";					/* 0x60 - 0x6f */#endifstatic void kbd_write_command_w(int data);static void kbd_write_output_w(int data);#ifdef CONFIG_PSMOUSEstatic void aux_write_ack(int val);static void __aux_write_ack(int val);static int aux_reconnect = 0;#endif#ifndef kbd_controller_present#define kbd_controller_present()	1#endifstatic spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;static unsigned char handle_kbd_event(void);/* used only by send_data - set by keyboard_interrupt */static volatile unsigned char reply_expected;static volatile unsigned char acknowledge;static volatile unsigned char resend;#if defined CONFIG_PSMOUSE/* *	PS/2 Auxiliary Device */static int __init psaux_init(void);#define AUX_RECONNECT1 0xaa	/* scancode1 when ps2 device is plugged (back) in */#define AUX_RECONNECT2 0x00	/* scancode2 when ps2 device is plugged (back) in */ static struct aux_queue *queue;	/* Mouse data buffer. */static int aux_count;/* used when we send commands to the mouse that expect an ACK. */static unsigned char mouse_reply_expected;#define AUX_INTS_OFF (KBD_MODE_KCC | KBD_MODE_DISABLE_MOUSE | KBD_MODE_SYS | KBD_MODE_KBD_INT)#define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)#define MAX_RETRIES	60		/* some aux operations take long time*/#endif /* CONFIG_PSMOUSE *//* * Wait for keyboard controller input buffer to drain. * * Don't use 'jiffies' so that we don't depend on * interrupts.. * * Quote from PS/2 System Reference Manual: * * "Address hex 0060 and address hex 0064 should be written only when * the input-buffer-full bit and output-buffer-full bit in the * Controller Status register are set 0." */static void kb_wait(void){	unsigned long timeout = KBC_TIMEOUT;	do {		/*		 * "handle_kbd_event()" will handle any incoming events		 * while we wait - keypresses or mouse movement.		 */		unsigned char status = handle_kbd_event();		if (! (status & KBD_STAT_IBF))			return;		mdelay(1);		timeout--;	} while (timeout);#ifdef KBD_REPORT_TIMEOUTS	printk(KERN_WARNING "Keyboard timed out[1]\n");#endif}/* * Translation of escaped scancodes to keycodes. * This is now user-settable. * The keycodes 1-88,96-111,119 are fairly standard, and * should probably not be changed - changing might confuse X. * X also interprets scancode 0x5d (KEY_Begin). * * For 1-88 keycode equals scancode. */#define E0_KPENTER 96#define E0_RCTRL   97#define E0_KPSLASH 98#define E0_PRSCR   99#define E0_RALT    100#define E0_BREAK   101  /* (control-pause) */#define E0_HOME    102#define E0_UP      103#define E0_PGUP    104#define E0_LEFT    105#define E0_RIGHT   106#define E0_END     107#define E0_DOWN    108#define E0_PGDN    109#define E0_INS     110#define E0_DEL     111#define E1_PAUSE   119/* * The keycodes below are randomly located in 89-95,112-118,120-127. * 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 * long as no duplication occurs for any single keyboard. */#define SC_LIM 89#define FOCUS_PF1 85           /* actual code! */#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#define FOCUS_PF9 120#define FOCUS_PF10 121#define FOCUS_PF11 122#define FOCUS_PF12 123#define JAP_86     124/* tfj@olivia.ping.dk: * The four keys are located over the numeric keypad, and are * labelled A1-A4. It's an rc930 keyboard, from * Regnecentralen/RC International, Now ICL. * Scancodes: 59, 5a, 5b, 5c. */#define RGN1 124#define RGN2 125#define RGN3 126#define RGN4 127static unsigned char high_keys[128 - SC_LIM] = {  RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */  0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */  0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */  FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */  FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */};/* BTC */#define E0_MACRO   112/* LK450 */#define E0_F13     113#define E0_F14     114#define E0_HELP    115#define E0_DO      116#define E0_F17     117#define E0_KPMINPLUS 118/* * My OmniKey generates e0 4c for  the "OMNI" key and the * right alt key does nada. [kkoller@nyx10.cs.du.edu] */#define E0_OK	124/* * New microsoft keyboard is rumoured to have * e0 5b (left window button), e0 5c (right window button), * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU] * [or: Windows_L, Windows_R, TaskMan] */#define E0_MSLW	125#define E0_MSRW	126#define E0_MSTM	127static unsigned char e0_keys[128] = {  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, E0_KPENTER, E0_RCTRL, 0, 0,	      /* 0x18-0x1f */  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, E0_KPSLASH, 0, E0_PRSCR,	      /* 0x30-0x37 */  E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,	      /* 0x38-0x3f */  E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,	      /* 0x40-0x47 */  E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */  E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,	      /* 0x50-0x57 */  0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,	      /* 0x58-0x5f */  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 */};int pckbd_setkeycode(unsigned int scancode, unsigned int keycode){	if (scancode < SC_LIM || scancode > 255 || keycode > 127)	  return -EINVAL;	if (scancode < 128)	  high_keys[scancode - SC_LIM] = keycode;	else	  e0_keys[scancode - 128] = keycode;	return 0;}int pckbd_getkeycode(unsigned int scancode){	return	  (scancode < SC_LIM || scancode > 255) ? -EINVAL :	  (scancode < 128) ? high_keys[scancode - SC_LIM] :	    e0_keys[scancode - 128];}static int do_acknowledge(unsigned char scancode){	if (reply_expected) {	  /* Unfortunately, we must recognise these codes only if we know they	   * are known to be valid (i.e., after sending a command), because there	   * are some brain-damaged keyboards (yes, FOCUS 9000 again) which have	   * keys with such codes :(	   */		if (scancode == KBD_REPLY_ACK) {			acknowledge = 1;			reply_expected = 0;			return 0;		} else if (scancode == KBD_REPLY_RESEND) {			resend = 1;			reply_expected = 0;			return 0;		}		/* Should not happen... */#if 0		printk(KERN_DEBUG "keyboard reply expected - got %02x\n",		       scancode);#endif	}	return 1;}int pckbd_translate(unsigned char scancode, unsigned char *keycode,		    char raw_mode){	static int prev_scancode;	/* special prefix scancodes.. */	if (scancode == 0xe0 || scancode == 0xe1) {		prev_scancode = scancode;		return 0;	}	/* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */	if (scancode == 0x00 || scancode == 0xff) {		prev_scancode = 0;		return 0;	}	scancode &= 0x7f;	if (prev_scancode) {	  /*	   * usually it will be 0xe0, but a Pause key generates	   * e1 1d 45 e1 9d c5 when pressed, and nothing when released	   */	  if (prev_scancode != 0xe0) {	      if (prev_scancode == 0xe1 && scancode == 0x1d) {		  prev_scancode = 0x100;		  return 0;	      } else if (prev_scancode == 0x100 && scancode == 0x45) {		  *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;	      /*	       *  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.	       */	      /*	       *  For my keyboard there is no caps lock mode, but there are	       *  both Shift-L and Shift-R modes. The former mode generates	       *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.	       *  So, we should also ignore the latter. - aeb@cwi.nl	       */	      if (scancode == 0x2a || scancode == 0x36)		return 0;	      if (e0_keys[scancode])		*keycode = e0_keys[scancode];	      else {#ifdef KBD_REPORT_UNKN		  if (!raw_mode)		    printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",

⌨️ 快捷键说明

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