1. 响应鼠标中断需要先激活鼠标控制电路,鼠标控制电路包含在键盘控制电路中。
asmhead.nas中也有类似代码,等待键盘控制电路准备好。
waitkbdout:
IN AL,0x64
AND AL,0x02
JNZ waitkbdout
RET
#define PORT_KEYDAT 0x0060
#define PORT_KEYSTA 0x0064
#define PORT_KEYCMD 0x0064
#define KEYSTA_SEND_NOTREADY 0x02
#define KEYCMD_WRITE_MODE 0x60
#define KBC_MODE 0x47
void wait_KBC_sendready(void)
{
for (;;) {
if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
break;
}
}
return;
}
void init_keyboard(void)
{
wait_KBC_sendready();
io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
wait_KBC_sendready();
io_out8(PORT_KEYDAT, KBC_MODE);
return;
}
define KEYCMD_SENDTO_MOUSE 0xd4
#define MOUSECMD_ENABLE 0xf4
void enable_mouse(void)
{
wait_KBC_sendready();
io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
wait_KBC_sendready();
io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
return;
}
2. 中断处理程序要通知两块PIC,IRQ12已经完成,之后从寄存器取鼠标中断发来的数据。
struct FIFO8 mousefifo;
void inthandler2c(int *esp)
{
unsigned char data;
io_out8(PIC1_OCW2, 0x64);
io_out8(PIC0_OCW2, 0x62);
data = io_in8(PORT_KEYDAT);
fifo8_put(&mousefifo, data);
return;
}
3. 鼠标发送来的中断信息的第一个为0xfa,之后发送以3个字节为单位的信息。
struct MOUSE_DEC {
unsigned char buf[3], phase;
/*buf[0]与鼠标移动和按键滚轮都有关,buf[1]与鼠标左右移动有关,buf[2]与鼠标上下移动有关*/
int x, y, btn;
/*xy坐标和btn按键状态*/
};
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
{
if (mdec->phase == 0) {
if (dat == 0xfa) {/*第一个发来的标志信息*/
mdec->phase = 1;
}
return 0;
}
/*接着发正常的三个字节信息*/
if (mdec->phase == 1) {
if ((dat & 0xc8) == 0x08) {/*保证第一个对*/
mdec->buf[0] = dat;
mdec->phase = 2;
}
return 0;
}
if (mdec->phase == 2) {
mdec->buf[1] = dat;
mdec->phase = 3;
return 0;
}
if (mdec->phase == 3) {
mdec->buf[2] = dat;
mdec->phase = 1;
mdec->btn = mdec->buf[0] & 0x07;
mdec->x = mdec->buf[1];
mdec->y = mdec->buf[2];
if ((mdec->buf[0] & 0x10) != 0) {
mdec->x |= 0xffffff00;
}
if ((mdec->buf[0] & 0x20) != 0) {
mdec->y |= 0xffffff00;
}
mdec->y = - mdec->y;
return 1;
}
return -1;
}
/*MariMain 处理鼠标信息部分代码*/
void hariMain()
{
/*中略*/
struct MOUSE_DEC mdec;
/*中略*/
enable_mouse(&mdec);
for(;;)
{
io_cli();
if(fifo8_status(&keyfifo)+fifo8_status(&mousefifo)==0)
{
io_stihlt();
}
else
{
if(fifo8_status(&keyfifo)!=0)
{
}
else if(fifo8_status(&mousefifo)!=0)
{
i = fifo8_get(&mousefifo);
io_sti();
if (mouse_decode(&mdec, i) != 0) {
sprintf(s, "%02X %02X %02X",mdec.buf[0],mdec.buf[1],mdec.buf[2]); boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32+8*8-1,31);
putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
}
}
}
}
}
4. 移动鼠标
void HariMain(void)
{
struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
char s[40], mcursor[256],keybuf[32],mousebuf[128];
int mx, my,i;
struct MOUSE_DEC mdec;
init_gdtidt();/*初始化GDT,IDT*/
init_pic();/* 初始化PIC */
io_sti();
fifo8_init(&keyfifo,32,keybuf);//初始化队列
fifo8_init(&mousefifo,128,mousebuf);
io_out8(PIC0_IMR, 0xf9); /*开鼠标和键盘中断*/
io_out8(PIC1_IMR, 0xef);
init_keyboard();
init_palette(); /* 初始化调色板 */
init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);/* 初始化屏幕 */
mx = (binfo->scrnx - 16) / 2;
my = (binfo->scrny - 28 - 16) / 2;
init_mouse_cursor8(mcursor, COL8_008484);/* 显示鼠标指示符 */
putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);
sprintf(s, "(%d, %d)", mx, my);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s);
enable_mouse(&mdec);
for (;;) {
io_cli();
if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
io_stihlt();
} else {
if (fifo8_status(&keyfifo) != 0) {
i = fifo8_get(&keyfifo);
io_sti();
sprintf(s, "%02X", i);
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
} else if (fifo8_status(&mousefifo) != 0) {
i = fifo8_get(&mousefifo);
io_sti();
if (mouse_decode(&mdec, i) != 0) {
sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);
if ((mdec.btn & 0x01) != 0) {
s[1] = 'L';
}
if ((mdec.btn & 0x02) != 0) {
s[3] = 'R';
}
if ((mdec.btn & 0x04) != 0) {
s[2] = 'C';
}
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);
putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, mx, my, mx + 15, my + 15); /*隐藏鼠标*/
mx += mdec.x;
my += mdec.y;
if (mx < 0) {
mx = 0;
}
if (my < 0) {
my = 0;
}
if (mx > binfo->scrnx - 16) {
mx = binfo->scrnx - 16;
}
if (my > binfo->scrny - 16) {
my = binfo->scrny - 16;
}
sprintf(s, "(%3d, %3d)", mx, my);
boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 0, 79, 15);
putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s);
putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);/*显示鼠标*/ }
}
}
}
}