【 *** 作系统】30天自制 *** 作系统--

【 *** 作系统】30天自制 *** 作系统--,第1张

        上一章的最后,实现了键盘的中断反馈,但是鼠标依然没有反应,所以承上启下,本章要做这么几个事情,(1)将中断接收到的数据,拿到中断外面来处理,以减少中断中的 *** 作,加快程序运行(这边很好理解,不再赘述);(2)建立FIFO缓冲区,以便快速稳定地读写键盘/鼠标的活动数据;(3)键盘控制电路的初始化,并激活鼠标,应用建立的FIFO缓冲区读写鼠标的活动数据;

一 建立FIFO缓冲区

        缓冲区是一个队列结构,先进先出,队列长度可以在初始化中自行定义。


这边主要构建了以下几个 *** 作函数:

【1】FIFO缓冲区初始化----fifo8_init:

        这个函数用于初始化一个缓冲区结构体,缓冲区的读写采用双指针的控制方法,所以这边用p、q两个指针来指代缓冲区数组下标


长度可以根据情况自行定义(键盘 *** 作少一点,定义的长度为32,鼠标的 *** 作多一点,定义的长度为128):

void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
/* FIFO缓冲区初始化 */
{
	fifo->buf   = buf;  //缓冲数据区
    fifo->p     = 0;    //缓冲区写指针
    fifo->q     = 0;    //缓冲区读指针
    fifo->size  = size; //缓冲区总长度
    fifo->free  = size; //缓冲区剩余长度
    fifo->flags = 0;    //缓冲区溢出标志位
    
	return;
}

【2】FIFO缓冲区写数据----fifo8_put:

int fifo8_put(struct FIFO8 *fifo, unsigned char data)
/* 向FIFO传送数据并保存 */
{
    if(fifo->free == 0)
    {
        /* 如果缓冲区满,则溢出标志位置1,写不进新的数据 */
        fifo->flags |= FLAGS_OVERRUN;
        return -1;
    }
	fifo->buf[fifo->p] = data;
    fifo->p ++;
    fifo->free --;
    if(fifo->p == fifo->size)
    {
        fifo->p = 0;
    }
	return 0;
}

【3】FIFO缓冲区读数据----fifo8_get:

int fifo8_get(struct FIFO8 *fifo)
/* 从FIFO取一个数据 */
{
    int data;
    if(fifo->free == fifo->size)
    {
        /* 如果缓冲区为空,则直接返回,读不到数据 */
        return -1;
    }
	data = fifo->buf[fifo->q];
    fifo->q ++;
    fifo->free ++;
    if(fifo->q == fifo->size)
    {
        fifo->q = 0;
    }
    
	return data;
}

【4】FIFO缓冲区状态查询----fifo8_status:

int fifo8_status(struct FIFO8 *fifo)
/* 查询使用了多少数据 */
{
	return fifo->size - fifo->free;
}

        有了上面的几个FIFO *** 作函数,就可以在主函数以及中断处分别添加读、写 *** 作:

        中断处写FIFO:

void inthandler21(int *esp)
{
	unsigned char data;
	io_out8(PIC0_OCW2, 0x61);	/* 通知PIC,IRQ1受理完成 */
	data = io_in8(PORT_KEYDAT);
	fifo8_put(&keyfifo, data);  /* 将接收到的键盘 *** 作符,写缓冲区 */
	return;
}

        主函数处读FIFO:

void HariMain(void)
{
    //display...
	fifo8_init(&keyfifo, 32, keybuf);

	for (;;) {
		io_cli();
		if (fifo8_status(&keyfifo) == 0) {
            //缓冲区为空则等待
			io_stihlt();
		} else {
            //读缓冲区一个字节
			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);
		}
	}
}

二 鼠标控制

        上一章的最后,实现了键盘的中断反馈,但是鼠标依然没有反应,原因在于,主板上虽然做了鼠标用的电路,但只要不执行激活鼠标的指令,就不产生鼠标的中断信号。


        鼠标的使用包含两个部分,一个是控制电路的激活,第二个是鼠标 *** 作符的接收。


        【1】鼠标的控制电路包含在键盘的控制电路中,鼠标的激活需要键盘控制电路的初始化

#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; /* 顺利的话,键盘控制其会返回ACK(0xfa) */
}

        【2】鼠标 *** 作符的接收

        与键盘 *** 作相比,鼠标这部分区别不大。


区别在于中断中的处理(这边为了方便对比,把键盘的处理也一并贴出来):

        键盘的处理如下:

struct FIFO8 keyfifo;

void inthandler21(int *esp)
{
    /* 来自PS/2键盘的中断 */
	unsigned char data;
	io_out8(PIC0_OCW2, 0x61);	/* 通知PIC0 IRQ-01的受理已经完成 */
	data = io_in8(PORT_KEYDAT);
	fifo8_put(&keyfifo, data);
	return;
}

        鼠标的处理如下:

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;
}

        由上面可以看出,键盘因为是IRQ1中断,只需要通知一次PIC0即可。


然而鼠标是IRQ12中断,IRQ12是由PIC1控制,而PIC1是由PIC0上的IRQ2控制,所以这边需要分别通知:

         主函数中的处理与键盘没有区别,所以这边不再赘述(设定的键盘缓冲区是32,鼠标缓冲区是128)。


        至此,鼠标和键盘的初始化、激活以及 *** 作符的反馈已经完成。


        但是目前鼠标的 *** 作符返回的东西看不懂,还不能实际使用,对其的解读下一章会介绍。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/634453.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-16
下一篇 2022-04-16

发表评论

登录后才能评论

评论列表(0条)

保存