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

📄 pc_keyb.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			}		}	} while (retries-- > 0);#ifdef KBD_REPORT_TIMEOUTS	printk(KERN_WARNING "keyboard: Too many NACKs -- noisy kbd cable?\n");#endif	return 0;}void pckbd_leds(unsigned char leds){	if (kbd_exists && (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))) {		send_data(KBD_CMD_ENABLE);	/* re-enable kbd if any errors */		kbd_exists = 0;	}}/* * In case we run on a non-x86 hardware we need to initialize both the * keyboard controller and the keyboard.  On a x86, the BIOS will * already have initialized them. * * Some x86 BIOSes do not correctly initialize the keyboard, so the * "kbd-reset" command line options can be given to force a reset. * [Ranger] */#ifdef __i386__ int kbd_startup_reset __initdata = 0;#else int kbd_startup_reset __initdata = 1;#endif/* for "kbd-reset" cmdline param */static int __init kbd_reset_setup(char *str){	kbd_startup_reset = 1;	return 1;}__setup("kbd-reset", kbd_reset_setup);#define KBD_NO_DATA	(-1)	/* No data */#define KBD_BAD_DATA	(-2)	/* Parity or other error */static int __init kbd_read_data(void){	int retval = KBD_NO_DATA;	unsigned char status;	status = kbd_read_status();	if (status & KBD_STAT_OBF) {		unsigned char data = kbd_read_input();		retval = data;		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))			retval = KBD_BAD_DATA;	}	return retval;}static void __init kbd_clear_input(void){	int maxread = 100;	/* Random number */	do {		if (kbd_read_data() == KBD_NO_DATA)			break;	} while (--maxread);}static int __init kbd_wait_for_input(void){	long timeout = KBD_INIT_TIMEOUT;	do {		int retval = kbd_read_data();		if (retval >= 0)			return retval;		mdelay(1);	} while (--timeout);	return -1;}static void kbd_write_command_w(int data){	unsigned long flags;	spin_lock_irqsave(&kbd_controller_lock, flags);	kb_wait();	kbd_write_command(data);	spin_unlock_irqrestore(&kbd_controller_lock, flags);}static void kbd_write_output_w(int data){	unsigned long flags;	spin_lock_irqsave(&kbd_controller_lock, flags);	kb_wait();	kbd_write_output(data);	spin_unlock_irqrestore(&kbd_controller_lock, flags);}#if defined CONFIG_PSMOUSEstatic void kbd_write_cmd(int cmd){	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 */static char * __init initialize_kbd(void){	int status;	/*	 * Test the keyboard interface.	 * This seems to be the only way to get it going.	 * If the test is successful a x55 is placed in the input buffer.	 */	kbd_write_command_w(KBD_CCMD_SELF_TEST);	if (kbd_wait_for_input() != 0x55)		return "Keyboard failed self test";	/*	 * Perform a keyboard interface test.  This causes the controller	 * to test the keyboard clock and data lines.  The results of the	 * test are placed in the input buffer.	 */	kbd_write_command_w(KBD_CCMD_KBD_TEST);	if (kbd_wait_for_input() != 0x00)		return "Keyboard interface failed self test";	/*	 * Enable the keyboard by allowing the keyboard clock to run.	 */	kbd_write_command_w(KBD_CCMD_KBD_ENABLE);	/*	 * Reset keyboard. If the read times out	 * then the assumption is that no keyboard is	 * plugged into the machine.	 * This defaults the keyboard to scan-code set 2.	 *	 * 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 */	kbd_write_command_w(KBD_CCMD_READ_MODE);	if (!(kbd_wait_for_input() & 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();	}		kbd_write_output_w(KBD_CMD_ENABLE);	if (kbd_wait_for_input() != KBD_REPLY_ACK)		return "Enable keyboard: no ACK";	/*	 * Finally, set the typematic rate to maximum.	 */	kbd_write_output_w(KBD_CMD_SET_RATE);	if (kbd_wait_for_input() != KBD_REPLY_ACK)		return "Set rate: no ACK";	kbd_write_output_w(0x00);	if (kbd_wait_for_input() != KBD_REPLY_ACK)		return "Set rate: no ACK";	return NULL;}void __init pckbd_init_hw(void){	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	/* Ok, finally allocate the IRQ, and off we go.. */	kbd_request_irq(keyboard_interrupt);}#if defined CONFIG_PSMOUSE/* * 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 */	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){	if (!detect_auxiliary_port())		return -EIO;	misc_register(&psaux_mouse);	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);	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 */

⌨️ 快捷键说明

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