7 从鼠标接受数据(harib04g)

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

int.c节选

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

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

■■■■■

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

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

bootpack.c节选

  1. fifo8_init(&mousefifo, 128, mousebuf);
  2. for (;;) {
  3. io_cli();
  4. if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {
  5. io_stihlt();
  6. } else {
  7. if (fifo8_status(&keyfifo) != 0) {
  8. i = fifo8_get(&keyfifo);
  9. io_sti();
  10. sprintf(s, "%02X", i);
  11. boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
  12. putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
  13. } else if (fifo8_status(&mousefifo) != 0) {
  14. i = fifo8_get(&mousefifo);
  15. io_sti();
  16. sprintf(s, "%02X", i);
  17. boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 47, 31);
  18. putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);
  19. }
  20. }
  21. }

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

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

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

7 从鼠标接受数据(harib04g) - 图1

启动刚完成时

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

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

7 从鼠标接受数据(harib04g) - 图2

滚动鼠标

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

7 从鼠标接受数据(harib04g) - 图3

按下键盘之后

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

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