在linu-kernel/drivers/input/mouse/psmouse-base.c是ps2鼠标驱动的主体,如psmouse_reset、psmouse_connect等函数具体实现在此文件之中。
简单地,拿psmouse_reset为例,调用ps2_command()->ps2_sendbyte()->serio_write()来完成对硬件的操作。而serio_write()在已经指定。
static int __devinit i8042_create_aux_port(void)
{
struct serio *serio;
struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio)
return -ENOMEM;
serio->id.type = SERIO_8042;
serio->write = i8042_aux_write;
serio->open = i8042_open;
serio->close = i8042_close;
serio->start = i8042_start;
serio->stop = i8042_stop;
serio->port_data = port;
serio->dev.parent = &i8042_platform_device->dev;
strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
port->serio = serio;
return i8042_port_register(port);
i8042_aux_write()会调用i8042_command()来完成对60/64口的操作。
(注意,操作端口前必须disable_keyboard,完成后enable_keyboard)
截取了鼠标初始化的log如下:
60 -> i8042 (command)
47 -> i8042 (parameter) //配置8042控制器
d4 -> i8042 (command) //针对鼠标操作
f2 -> i8042 (parameter) //getid命令
interrupt: read status (0x3d)
interrupt: read data (0xfa) //ACK应答,如果是FE的话,说明返回错误。
但是在LINUX中若使用PS2鼠标驱动,屏蔽掉USB鼠标驱动的话,在某些平台上会出现返回FE的错误,以至于鼠标驱动加载失败,通过DOS下的ctmouse驱动可以看到,psmouse驱动使用int15/c2xx来完成初始化。所以在linux启动的实模式期间,调用int15来实现鼠标驱动初始化工作。
在/arch/i386/boot/setup.S中添加如下代码:
start_of_setup:
+# Fix ULOS mouse BUG
+ pushw %ax
+ pushw %bx
+ pushw %es
+
+ xorw %bx, %bx
+ movw %cs, %ax
+ movw %ax, %es
+ movw $0x0c207, %ax
+ int $0x15
+
+ movw $0x0c200, %ax
+ movw $0x0100, %bx
+ int $0x15
+
+ movb $0xa7, %al
+ outb %al, $0x64 # disable mouse
+ call delay
+
+ popw %es
+ popw %bx
+ popw %ax
# Bootlin depends on this being done early
movw $0x01500, %ax
movb $0x81, %dl