30天自制操作系统
上QQ阅读APP看书,第一时间看更新

7 从鼠标接受数据(harib04g)

既然中断已经来了,现在就让我们取出中断数据吧。前面已经说过,鼠标和键盘的原理几乎相同,所以程序也就非常相似。

int.c节选

struct FIFO8 mousefifo;
void inthandler2c(int *esp)
/* 来自PS/2鼠标的中断 */
{
    unsigned char data;
    io_out8(PIC1_OCW2, 0x64);   /* 通知PIC1 IRQ-12的受理已经完成 */
    io_out8(PIC0_OCW2, 0x62);   /* 通知PIC0 IRQ-02的受理已经完成 */
    data = io_in8(PORT_KEYDAT);
    fifo8_put(&mousefifo, data);
    return;
}

不同之处只有送给PIC的中断受理通知。IRQ-12是从PIC的第4号(从PIC相当于IRQ-08~IRQ-15),首先要通知IRQ-12受理已完成,然后再通知主PIC。这是因为主/从PIC的协调不能够自动完成,如果程序不教给主PIC该怎么做,它就会忽视从PIC的下一个中断请求。从PIC连接到主PIC的第2号上,这么做OK。

■■■■■

下面的鼠标数据取得方法,居然与键盘完全相同。这不是笔者的失误,而是事实。也许是因为键盘控制电路中含有鼠标控制电路,才造成了这种结果。至于传到这个设备的数据,究竟是来自键盘还是鼠标,要靠中断号码来区分。

取得数据的程序如下所示:

bootpack.c节选

fifo8_init(&mousefifo, 128, mousebuf);
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();
            sprintf(s, "%02X", i);
            boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 47, 31);
            putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
        }
    }
}

因为鼠标往往会比键盘更快地送出大量数据,所以我们将它的FIFO缓冲区增加到了128字节。这样,就算是一下子来了很多数据,也不会溢出。

取得数据的程序中,如果键盘和鼠标的FIFO缓冲区都为空了,就执行HLT。如果不是两者都空,就先检查keyinfo,如果有数据,就取出一个显示出来。如果keyinfo是空,就再去检查mouseinfo,如果有数据,就取出一个显示出来。很简单吧。

到底能不能执行呢?好紧张呀。我们来测试一下。运行“make run”。

就像上面那样,最初只显示鼠标发送过来的数据,且内容的确是FA。

随便滚动鼠标一下,就会像下面这样显示出各种各样的数据来。

如果按下键盘,当然会像以前一样,正常响应。

看,运行得很正常很不错呀。

好了,今天我们做的事已经不少了,就先到这吧。明天我们来解读鼠标数据,让鼠标指针在屏幕上动起来。真期待呀。啊,今天就不要再往下读了哦。先睡觉,明天再继续,好吧?