粗略阅读haribote键盘管理程序 keyboard.c

[1] 粗略阅读haribote引导程序 ipl09.nas
[2] 粗略阅读haribote从实模式进入保护模式程序 asmhead.nas
[3] 粗略阅读haribote设置GDT和IDT的程序 dsctbl.c
[4] 粗略阅读haribote内存管理程序 memory.c
[5] 略阅读haribote可编程中断控制器(PIC)初始配置程序 int.c
[6] 粗略阅读haribote定时器管理程序 timer.c
[7] 粗略阅读haribote循环队列管理程序 fifo.c
[8] 粗略阅读haribote键盘管理程序
keyboard.c
/* keyboard.c, 键盘管理程序接口 */

#include "bootpack.h"

/* 键盘缓冲队列全局指针,键盘缓冲队列数据的基数/标识
 * (键盘数据加上 keydata0 后发往键盘缓冲队列中)。*/
struct FIFO32 *keyfifo;
int keydata0;

/* inthandler21,
 * 键盘中断C处理函数,读取键盘输入到键盘缓冲队列中。
 * 
 * 当有键盘输入而向PIC输出中断时,
 * CPU处理PIC申请的键盘中断时会执行IDT[21h]中的入口处
 * 理程序 _asm_inthandler21 (见int.c和dsctbl.c), 该处
 * 理函数会调用此处的C处理函数 inthandler21.*/
void inthandler21(int *esp)
{
    int data;

    /* 发送EOI命令结束键盘中断 */
    io_out8(PIC0_OCW2, 0x61);
    /* 读键盘输入扫描码 data,并将其加上键盘数
     * 据基数发送到键盘队列中, 供其他任务读取。*/
    data = io_in8(PORT_KEYDAT);
    fifo32_put(keyfifo, data + keydata0);
    return;
}

/* PORT_KEYSTA,键盘控制器8042状态寄存器端口;
 * KEYSTA_SEND_NOTREADY,8042状态控制器输入缓冲器满的标志;
 * KEYCMD_WRITE_MODE,写入键盘控制命令字节的命令,具体的命令字节随后从60h端口写入;
 *
 * KBC_MODE, KEYCMD_WRITE_MODE的参数即具体的命令字节: 
 * 键盘以PC兼容方式运作,使用鼠和标键盘以及鼠标和键盘中断,
 * 未完成当前键盘数据时不接收下一个键盘数据等 */
#define PORT_KEYSTA          0x0064
#define KEYSTA_SEND_NOTREADY 0x02
#define KEYCMD_WRITE_MODE    0x60
#define KBC_MODE             0x47


/* wait_KBC_sendready,
 * 等待键盘控制器8042输入缓冲器寄存器空。*/
void wait_KBC_sendready(void)
{
    /* 8042状态控制器bit[1]=0时表示其输入缓冲寄存器为空即已可接受输入 */
    for (;;) {
        if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
            break;
        }
    }
    return;
}

/* init_keyboard,
 * 初始化键盘控制器并设置键盘缓冲队列fifo及其数据标识data0。
 * 
 * 设置键盘控制器8042运作方式:键盘以PC兼容方式运作,在未完成
 * 当前键盘数据的接收时不接收下一个键盘输入。*/
void init_keyboard(struct FIFO32 *fifo, int data0)
{
    /* 设置键盘换成队列和键盘队列数据标识 */
    keyfifo = fifo;
    keydata0 = data0;

    /* 设置键盘运作模式,粗略含义见宏处注释 */
    wait_KBC_sendready();
    io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
    wait_KBC_sendready();
    io_out8(PORT_KEYDAT, KBC_MODE);
    return;
}
bootpack.h
/* ... */

/* keyboard.c */
void inthandler21(int *esp);
void wait_KBC_sendready(void);
void init_keyboard(struct FIFO32 *fifo, int data0);
/* 8042 端口地址,
 * in  al, 60h, 读8042输出缓冲寄存器内容到al;
 * in  al, 64h, 读8042状态寄存器内容到al;
 * out 60h, al, 写数据al到8042输入缓冲寄存器;
 * out 64h, al, 写命令al到8042输入缓冲寄存器. */
#define PORT_KEYDAT 0x0060
#define PORT_KEYCMD 0x0064

/* ... */
上一篇:自定义对话框上的自定义键盘(Android)


下一篇:处理SDL和C中的关键事件