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

📄 pc_keyb.c,v

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C,V
📖 第 1 页 / 共 2 页
字号:
		acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */		resend = 0;		reply_expected = 1;		kbd_write(KBD_DATA_REG, data);		for (;;) {			if (acknowledge)				return 1;			if (resend)				break;			mdelay(1);			if (!--timeout) {#ifdef KBD_REPORT_TIMEOUTS				printk(KERN_WARNING "Keyboard timeout[2]\n");#endif				return 0;			}		}	} 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 (!send_data(KBD_CMD_SET_LEDS) || !send_data(leds))	    send_data(KBD_CMD_ENABLE);	/* re-enable kbd if any errors */}/* * 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 */void __init kbd_reset_setup(char *str, int *ints){	kbd_startup_reset = 1;}#define KBD_NO_DATA	(-1)	/* No data */#define KBD_BAD_DATA	(-2)	/* Parity or other error */static int __init kbd_read_input(void){	int retval = KBD_NO_DATA;	unsigned char status;	status = inb(KBD_STATUS_REG);	if (status & KBD_STAT_OBF) {		unsigned char data = inb(KBD_DATA_REG);		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_input() == KBD_NO_DATA)			break;	} while (--maxread);}static int __init kbd_wait_for_input(void){	long timeout = KBD_INIT_TIMEOUT;	do {		int retval = kbd_read_input();		if (retval >= 0)			return retval;		mdelay(1);	} while (--timeout);	return -1;}static void kbd_write(int address, int data){	unsigned long flags;	spin_lock_irqsave(&kbd_controller_lock, flags);	kb_wait();	outb(data, address);	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();	outb(KBD_CCMD_WRITE_MODE, KBD_CNTL_REG);	kb_wait();	outb(cmd, KBD_DATA_REG);	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(KBD_CNTL_REG, 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(KBD_CNTL_REG, 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(KBD_CNTL_REG, 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(KBD_DATA_REG, 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(KBD_DATA_REG, 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(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);	kbd_write(KBD_DATA_REG, 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(KBD_CNTL_REG, 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(KBD_DATA_REG, 0xF0);		kbd_wait_for_input();		kbd_write(KBD_DATA_REG, 0x01);		kbd_wait_for_input();	}		kbd_write(KBD_DATA_REG, 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(KBD_DATA_REG, KBD_CMD_SET_RATE);	if (kbd_wait_for_input() != KBD_REPLY_ACK)		return "Set rate: no ACK";	kbd_write(KBD_DATA_REG, 0x00);	if (kbd_wait_for_input() != KBD_REPLY_ACK)		return "Set rate: no ACK";	return NULL;}void __init pckbd_init_hw(void){	/* Get the keyboard controller registers (incomplete decode) */	request_region(0x60, 16, "keyboard");	/* 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.. */	request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);}#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;	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();	outb(KBD_CCMD_WRITE_AUX_OBUF, KBD_CNTL_REG);	kb_wait();	outb(0x5a, KBD_DATA_REG); /* 0x5a is a random dummy value. */	do {		unsigned char status = inb(KBD_STATUS_REG);		if (status & KBD_STAT_OBF) {			(void) inb(KBD_DATA_REG);			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();	outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG);	kb_wait();	outb(val, KBD_DATA_REG);	spin_unlock_irqrestore(&kbd_controller_lock, flags);}/* * Send a byte to the mouse & handle returned ack */static void aux_write_ack(int val){	unsigned long flags;	spin_lock_irqsave(&kbd_controller_lock, flags);	kb_wait();	outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG);	kb_wait();	outb(val, KBD_DATA_REG);	/* we expect an ACK in response. */	mouse_reply_expected++;	kb_wait();	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){	fasync_aux(-1, file, 0);	if (--aux_count)		return 0;	kbd_write_cmd(AUX_INTS_OFF);			    /* Disable controller ints */	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE);	free_irq(AUX_IRQ, AUX_DEV);	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 (request_irq(AUX_IRQ, keyboard_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)) {		aux_count--;		return -EBUSY;	}	kbd_write(KBD_CNTL_REG, 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 */	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){	struct wait_queue wait = { current, NULL };	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:		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;}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 = {	NULL,		/* seek */	read_aux,	write_aux,	NULL, 		/* readdir */	aux_poll,	NULL, 		/* ioctl */	NULL,		/* mmap */	open_aux,	NULL,		/* flush */	release_aux,	NULL,	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;	queue->proc_list = NULL;#ifdef INITIALIZE_MOUSE	kbd_write(KBD_CNTL_REG, 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(KBD_CNTL_REG, 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 + -