亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? i8042.c

?? QQ2440板子
?? C
?? 第 1 頁 / 共 2 頁
字號:
/* *  i8042 keyboard and mouse controller driver for Linux * *  Copyright (c) 1999-2004 Vojtech Pavlik *//* * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. */#include <linux/delay.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/config.h>#include <linux/init.h>#include <linux/serio.h>#include <linux/err.h>#include <linux/rcupdate.h>#include <asm/io.h>MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");MODULE_DESCRIPTION("i8042 keyboard and mouse controller driver");MODULE_LICENSE("GPL");static unsigned int i8042_noaux;module_param_named(noaux, i8042_noaux, bool, 0);MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port.");static unsigned int i8042_nomux;module_param_named(nomux, i8042_nomux, bool, 0);MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present.");static unsigned int i8042_unlock;module_param_named(unlock, i8042_unlock, bool, 0);MODULE_PARM_DESC(unlock, "Ignore keyboard lock.");static unsigned int i8042_reset;module_param_named(reset, i8042_reset, bool, 0);MODULE_PARM_DESC(reset, "Reset controller during init and cleanup.");static unsigned int i8042_direct;module_param_named(direct, i8042_direct, bool, 0);MODULE_PARM_DESC(direct, "Put keyboard port into non-translated mode.");static unsigned int i8042_dumbkbd;module_param_named(dumbkbd, i8042_dumbkbd, bool, 0);MODULE_PARM_DESC(dumbkbd, "Pretend that controller can only read data from keyboard");static unsigned int i8042_noloop;module_param_named(noloop, i8042_noloop, bool, 0);MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port");static unsigned int i8042_blink_frequency = 500;module_param_named(panicblink, i8042_blink_frequency, uint, 0600);MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics");#ifdef CONFIG_PNPstatic int i8042_nopnp;module_param_named(nopnp, i8042_nopnp, bool, 0);MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");#endif#define DEBUG#ifdef DEBUGstatic int i8042_debug;module_param_named(debug, i8042_debug, bool, 0600);MODULE_PARM_DESC(debug, "Turn i8042 debugging mode on and off");#endif__obsolete_setup("i8042_noaux");__obsolete_setup("i8042_nomux");__obsolete_setup("i8042_unlock");__obsolete_setup("i8042_reset");__obsolete_setup("i8042_direct");__obsolete_setup("i8042_dumbkbd");#include "i8042.h"static DEFINE_SPINLOCK(i8042_lock);struct i8042_port {	struct serio *serio;	int irq;	unsigned char disable;	unsigned char irqen;	unsigned char exists;	signed char mux;	char name[8];};#define I8042_KBD_PORT_NO	0#define I8042_AUX_PORT_NO	1#define I8042_MUX_PORT_NO	2#define I8042_NUM_PORTS		(I8042_NUM_MUX_PORTS + 2)static struct i8042_port i8042_ports[I8042_NUM_PORTS] = {	{		.disable	= I8042_CTR_KBDDIS,		.irqen		= I8042_CTR_KBDINT,		.mux		= -1,		.name		= "KBD",	},	{		.disable	= I8042_CTR_AUXDIS,		.irqen		= I8042_CTR_AUXINT,		.mux		= -1,		.name		= "AUX",	}};static unsigned char i8042_initial_ctr;static unsigned char i8042_ctr;static unsigned char i8042_mux_open;static unsigned char i8042_mux_present;static struct timer_list i8042_timer;static struct platform_device *i8042_platform_device;/* * Shared IRQ's require a device pointer, but this driver doesn't support * multiple devices */#define i8042_request_irq_cookie (&i8042_timer)static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs);/* * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to * be ready for reading values from it / writing values to it. * Called always with i8042_lock held. */static int i8042_wait_read(void){	int i = 0;	while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) {		udelay(50);		i++;	}	return -(i == I8042_CTL_TIMEOUT);}static int i8042_wait_write(void){	int i = 0;	while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) {		udelay(50);		i++;	}	return -(i == I8042_CTL_TIMEOUT);}/* * i8042_flush() flushes all data that may be in the keyboard and mouse buffers * of the i8042 down the toilet. */static int i8042_flush(void){	unsigned long flags;	unsigned char data, str;	int i = 0;	spin_lock_irqsave(&i8042_lock, flags);	while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {		udelay(50);		data = i8042_read_data();		i++;		dbg("%02x <- i8042 (flush, %s)", data,			str & I8042_STR_AUXDATA ? "aux" : "kbd");	}	spin_unlock_irqrestore(&i8042_lock, flags);	return i;}/* * i8042_command() executes a command on the i8042. It also sends the input * parameter(s) of the commands to it, and receives the output value(s). The * parameters are to be stored in the param array, and the output is placed * into the same array. The number of the parameters and output values is * encoded in bits 8-11 of the command number. */static int i8042_command(unsigned char *param, int command){	unsigned long flags;	int i, retval, auxerr = 0;	if (i8042_noloop && command == I8042_CMD_AUX_LOOP)		return -1;	spin_lock_irqsave(&i8042_lock, flags);	if ((retval = i8042_wait_write()))		goto out;	dbg("%02x -> i8042 (command)", command & 0xff);	i8042_write_command(command & 0xff);	for (i = 0; i < ((command >> 12) & 0xf); i++) {		if ((retval = i8042_wait_write()))			goto out;		dbg("%02x -> i8042 (parameter)", param[i]);		i8042_write_data(param[i]);	}	for (i = 0; i < ((command >> 8) & 0xf); i++) {		if ((retval = i8042_wait_read()))			goto out;		if (command == I8042_CMD_AUX_LOOP &&		    !(i8042_read_status() & I8042_STR_AUXDATA)) {			retval = auxerr = -1;			goto out;		}		param[i] = i8042_read_data();		dbg("%02x <- i8042 (return)", param[i]);	}	if (retval)		dbg("     -- i8042 (%s)", auxerr ? "auxerr" : "timeout"); out:	spin_unlock_irqrestore(&i8042_lock, flags);	return retval;}/* * i8042_kbd_write() sends a byte out through the keyboard interface. */static int i8042_kbd_write(struct serio *port, unsigned char c){	unsigned long flags;	int retval = 0;	spin_lock_irqsave(&i8042_lock, flags);	if(!(retval = i8042_wait_write())) {		dbg("%02x -> i8042 (kbd-data)", c);		i8042_write_data(c);	}	spin_unlock_irqrestore(&i8042_lock, flags);	return retval;}/* * i8042_aux_write() sends a byte out through the aux interface. */static int i8042_aux_write(struct serio *serio, unsigned char c){	struct i8042_port *port = serio->port_data;	int retval;/* * Send the byte out. */	if (port->mux == -1)		retval = i8042_command(&c, I8042_CMD_AUX_SEND);	else		retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux);/* * Make sure the interrupt happens and the character is received even * in the case the IRQ isn't wired, so that we can receive further * characters later. */	i8042_interrupt(0, NULL, NULL);	return retval;}/* * i8042_activate_port() enables port on a chip. */static int i8042_activate_port(struct i8042_port *port){	if (!port->serio)		return -1;	i8042_flush();	/*	 * Enable port again here because it is disabled if we are	 * resuming (normally it is enabled already).	 */	i8042_ctr &= ~port->disable;	i8042_ctr |= port->irqen;	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {		i8042_ctr &= ~port->irqen;		return -1;	}	return 0;}/* * i8042_open() is called when a port is open by the higher layer. * It allocates the interrupt and calls i8042_enable_port. */static int i8042_open(struct serio *serio){	struct i8042_port *port = serio->port_data;	if (port->mux != -1)		if (i8042_mux_open++)			return 0;	if (request_irq(port->irq, i8042_interrupt,			SA_SHIRQ, "i8042", i8042_request_irq_cookie)) {		printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", port->irq, port->name);		goto irq_fail;	}	if (i8042_activate_port(port)) {		printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", port->name);		goto activate_fail;	}	i8042_interrupt(0, NULL, NULL);	return 0;activate_fail:	free_irq(port->irq, i8042_request_irq_cookie);irq_fail:	serio_unregister_port_delayed(serio);	return -1;}/* * i8042_close() frees the interrupt, so that it can possibly be used * by another driver. We never know - if the user doesn't have a mouse, * the BIOS could have used the AUX interrupt for PCI. */static void i8042_close(struct serio *serio){	struct i8042_port *port = serio->port_data;	if (port->mux != -1)		if (--i8042_mux_open)			return;	i8042_ctr &= ~port->irqen;	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {		printk(KERN_WARNING "i8042.c: Can't write CTR while closing %s.\n", port->name);/* * We still want to continue and free IRQ so if more data keeps coming in * kernel will just ignore the irq. */	}	free_irq(port->irq, i8042_request_irq_cookie);	i8042_flush();}/* * i8042_start() is called by serio core when port is about to finish * registering. It will mark port as existing so i8042_interrupt can * start sending data through it. */static int i8042_start(struct serio *serio){	struct i8042_port *port = serio->port_data;	port->exists = 1;	mb();	return 0;}/* * i8042_stop() marks serio port as non-existing so i8042_interrupt * will not try to send data to the port that is about to go away. * The function is called by serio core as part of unregister procedure. */static void i8042_stop(struct serio *serio){	struct i8042_port *port = serio->port_data;	port->exists = 0;	synchronize_sched();	port->serio = NULL;}/* * i8042_interrupt() is the most important function in this driver - * it handles the interrupts from the i8042, and sends incoming bytes * to the upper layers. */static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct i8042_port *port;	unsigned long flags;	unsigned char str, data;	unsigned int dfl;	unsigned int port_no;	int ret;	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);	spin_lock_irqsave(&i8042_lock, flags);	str = i8042_read_status();	if (unlikely(~str & I8042_STR_OBF)) {		spin_unlock_irqrestore(&i8042_lock, flags);		if (irq) dbg("Interrupt %d, without any data", irq);		ret = 0;		goto out;	}	data = i8042_read_data();	spin_unlock_irqrestore(&i8042_lock, flags);	if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {		static unsigned long last_transmit;		static unsigned char last_str;		dfl = 0;		if (str & I8042_STR_MUXERR) {			dbg("MUX error, status is %02x, data is %02x", str, data);			switch (data) {				default:/* * When MUXERR condition is signalled the data register can only contain * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately * it is not always the case. Some KBC just get confused which port the * data came from and signal error leaving the data intact. They _do not_ * revert to legacy mode (actually I've never seen KBC reverting to legacy * mode yet, when we see one we'll add proper handling). * Anyway, we will assume that the data came from the same serio last byte * was transmitted (if transmission happened not too long ago). */					if (time_before(jiffies, last_transmit + HZ/10)) {						str = last_str;						break;					}					/* fall through - report timeout */				case 0xfd:				case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break;				case 0xff: dfl = SERIO_PARITY;  data = 0xfe; break;			}		}		port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3);		last_str = str;		last_transmit = jiffies;	} else {		dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |		      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);		port_no = (str & I8042_STR_AUXDATA) ?				I8042_AUX_PORT_NO : I8042_KBD_PORT_NO;	}	port = &i8042_ports[port_no];	dbg("%02x <- i8042 (interrupt, %s, %d%s%s)",	    data, port->name, irq,	    dfl & SERIO_PARITY ? ", bad parity" : "",	    dfl & SERIO_TIMEOUT ? ", timeout" : "");	if (likely(port->exists))		serio_interrupt(port->serio, data, dfl, regs);	ret = 1;out:	return IRQ_RETVAL(ret);}/* * i8042_set_mux_mode checks whether the controller has an active * multiplexor and puts the chip into Multiplexed (1) or Legacy (0) mode. */static int i8042_set_mux_mode(unsigned int mode, unsigned char *mux_version){	unsigned char param;/* * Get rid of bytes in the queue. */	i8042_flush();/* * Internal loopback test - send three bytes, they should come back from the * mouse interface, the last should be version. Note that we negate mouseport * command responses for the i8042_check_aux() routine. */	param = 0xf0;	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != 0xf0)		return -1;	param = mode ? 0x56 : 0xf6;	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param != (mode ? 0x56 : 0xf6))		return -1;	param = mode ? 0xa4 : 0xa5;	if (i8042_command(&param, I8042_CMD_AUX_LOOP) || param == (mode ? 0xa4 : 0xa5))		return -1;	if (mux_version)		*mux_version = param;	return 0;}/* * i8042_enable_mux_ports enables 4 individual AUX ports after * the controller has been switched into Multiplexed mode */static int i8042_enable_mux_ports(void){	unsigned char param;	int i;/* * Disable all muxed ports by disabling AUX. */	i8042_ctr |= I8042_CTR_AUXDIS;	i8042_ctr &= ~I8042_CTR_AUXINT;	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {		printk(KERN_ERR "i8042.c: Failed to disable AUX port, can't use MUX.\n");		return -1;	}/* * Enable all muxed ports. */	for (i = 0; i < 4; i++) {		i8042_command(&param, I8042_CMD_MUX_PFX + i);		i8042_command(&param, I8042_CMD_AUX_ENABLE);	}	return 0;}/*

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
欧美激情一区三区| 欧美精品一二三区| 亚洲人一二三区| 91免费在线看| 亚洲永久精品大片| 777欧美精品| 久久精品理论片| 中文字幕精品一区二区精品绿巨人 | 国产一区二区不卡老阿姨| 欧美精品一区二区在线观看| 国产成人免费视频网站 | eeuss影院一区二区三区| 亚洲视频综合在线| 欧美自拍偷拍一区| 麻豆精品一二三| 国产精品久久久久久久久晋中 | 日本一区二区成人在线| 欧美性色黄大片| 日韩精品乱码免费| 国产拍揄自揄精品视频麻豆| 色婷婷亚洲一区二区三区| 婷婷开心激情综合| 久久久精品黄色| 欧美日韩高清影院| 国产精品一区二区三区乱码| 一区二区三区四区亚洲| 日韩欧美一区在线观看| 成人一区二区三区视频在线观看 | 欧美日韩亚洲综合在线| 国内精品伊人久久久久av影院| 中国色在线观看另类| 欧美猛男超大videosgay| 国产毛片精品视频| 亚洲午夜免费电影| 国产亚洲1区2区3区| 欧美精品少妇一区二区三区| 风间由美一区二区三区在线观看| 亚洲444eee在线观看| 欧美国产视频在线| 日韩一区二区免费电影| 91久久精品午夜一区二区| 久久se这里有精品| 亚洲成av人片在线观看| 国产精品不卡一区二区三区| 欧美大片拔萝卜| 欧美日韩精品一区二区天天拍小说| 国产一区二区日韩精品| 日本伊人午夜精品| 亚洲国产日韩a在线播放| 欧美日韩国产在线观看| 亚洲天堂网中文字| 国产欧美日韩在线| 精品奇米国产一区二区三区| 欧美日韩美少妇| 色一情一伦一子一伦一区| 成人永久免费视频| 国产高清在线精品| 老司机一区二区| 日韩av中文字幕一区二区| 一区二区免费在线| 日韩码欧中文字| 国产精品久久久久久久久久久免费看 | 成人av资源站| 国产伦精一区二区三区| 另类小说综合欧美亚洲| 青青国产91久久久久久| 日本女优在线视频一区二区 | 欧美激情一区二区三区全黄| 2024国产精品视频| 精品国产一区二区三区不卡| 欧美成人video| 精品女同一区二区| xvideos.蜜桃一区二区| 2023国产精品视频| 久久午夜羞羞影院免费观看| 精品精品国产高清a毛片牛牛| 日韩一级大片在线观看| 日韩欧美在线综合网| 精品国产免费人成电影在线观看四季 | 日韩理论片一区二区| 国产精品久久久久婷婷| 亚洲欧洲日本在线| 亚洲精品成人少妇| 亚洲一区精品在线| 日韩中文字幕1| 久久国内精品视频| 国产综合色在线视频区| 国产福利精品导航| 色综合天天综合色综合av| 在线观看亚洲a| 91精品国产手机| 久久久久久黄色| 亚洲天堂免费在线观看视频| 亚洲国产美国国产综合一区二区| 亚洲成年人影院| 精彩视频一区二区三区| 丁香婷婷深情五月亚洲| 一本一道波多野结衣一区二区| 欧美在线视频全部完| 日韩欧美在线观看一区二区三区| 国产清纯美女被跳蛋高潮一区二区久久w | 精品久久久久久最新网址| 欧美精品一区二区三区四区| 中文字幕免费不卡在线| 亚洲成人av一区二区三区| 久久99国产精品麻豆| 99久久婷婷国产综合精品| 欧美日韩和欧美的一区二区| 2020国产精品自拍| 亚洲欧洲综合另类在线| 琪琪久久久久日韩精品| 成人动漫一区二区三区| 欧美日韩国产精品成人| 国产日韩欧美在线一区| 一区二区三区在线视频播放| 麻豆精品一区二区av白丝在线| av亚洲精华国产精华精| 欧美一区二区在线观看| 亚洲国产岛国毛片在线| 日韩和的一区二区| 成人av网址在线| 日韩亚洲欧美在线| 亚洲男人的天堂在线观看| 久久激五月天综合精品| 日本精品视频一区二区| 国产亚洲精品免费| 日日夜夜免费精品视频| 不卡在线视频中文字幕| 日韩亚洲欧美中文三级| 一区二区三区成人在线视频| 国产成人精品亚洲777人妖 | 久久av中文字幕片| 欧洲亚洲精品在线| 国产精品看片你懂得| 久久国产欧美日韩精品| 欧美日韩在线一区二区| 欧美极品aⅴ影院| 久久99久久久欧美国产| 欧美在线free| 亚洲免费观看高清完整版在线| 国精产品一区一区三区mba桃花| 欧美日韩中文字幕精品| 亚洲色图欧美激情| 成人激情免费网站| 国产日产欧美一区二区三区| 免费成人美女在线观看.| 欧美日精品一区视频| 亚洲三级在线免费观看| 成人激情免费视频| 久久久亚洲午夜电影| 激情国产一区二区 | 欧美色图一区二区三区| 亚洲私人影院在线观看| 成人国产一区二区三区精品| 久久综合久久综合亚洲| 久久99国产精品成人| 日韩亚洲欧美在线观看| 蜜臀a∨国产成人精品| 51精品国自产在线| 午夜精品一区二区三区三上悠亚| 色噜噜狠狠成人中文综合| 亚洲视频香蕉人妖| 94-欧美-setu| 亚洲免费资源在线播放| 色综合久久综合网97色综合| 亚洲免费视频中文字幕| 色婷婷久久99综合精品jk白丝| 亚洲人成网站色在线观看| 91农村精品一区二区在线| 亚洲欧美日本在线| 欧美在线你懂的| 日韩专区欧美专区| 精品久久久久久综合日本欧美 | 五月婷婷久久丁香| 777午夜精品视频在线播放| 日本视频中文字幕一区二区三区| 91精品国产aⅴ一区二区| 久久精品国产**网站演员| 久久久美女毛片| caoporn国产一区二区| 日韩美女精品在线| 欧美丝袜丝交足nylons图片| 午夜视频在线观看一区二区| 欧美一区二区三区四区在线观看| 蜜臀av性久久久久蜜臀av麻豆| 久久亚洲捆绑美女| 91蝌蚪porny九色| 天天操天天干天天综合网| 日韩欧美中文字幕公布| 国产电影精品久久禁18| 亚洲视频一二三| 欧美一级在线免费| 国产v综合v亚洲欧| 亚洲一级二级在线| 精品成人在线观看| 在线免费一区三区| 国产一区二区三区四区五区美女| 中文字幕制服丝袜成人av| 欧美美女黄视频| 国产精品影视在线观看|