13.实现鼠标中断处理

本文档介绍了如何实现鼠标中断处理并优化中断缓存机制。首先,通过对8259A中断控制器的配置启用鼠标中断信号线。接着,详细描述了检测鼠标电路状态的过程以及在kernel.s和os.c中的修改。此外,为了提高代码可维护性,将os.c的部分内容分离到os.h。最后,讲解了中断处理后的End of Interrupt机制,并展示了运行效果。
摘要由CSDN通过智能技术生成

简介

上节实现了对键盘中断服务子程序的处理和修改优化了中断程序,但只是简单的在中断服务子程序中记录断码或通码,缓冲区使用效率不高。

目标

实现鼠标中断处理、优化中断缓存。pc中8259A中断控制器连接模型如下:
在这里插入图片描述

1.鼠标发送中断信号的数据线在从8259A芯片的IRQ4信号线,为了接收鼠标中断信号,我们在初始化中断控制芯片时,必须启用该信号线,同时,从8259A芯片是通过主8259A的IRQ2信号线连接在一起的,所以,也必须同时启动主8259A芯片的IRQ2信号线。故init8259A:初始化中断控制器中如下代码修改如下:

mov  al, 11111001b	;CPU只接收主8259A, IRQ1管线发送的信号,其他管线发送信号一概忽略
out  0x21, al		;IRQ1对应的是键盘产生的中断
call io_delay

mov  al, 11101111b	;IRQ4 允许鼠标中断
out  0xa1, al		;鼠标是通过从8259A的IRQ4管线向CPU发送信号
call io_delay

2.鼠标电路对应的一个端口是 0x64, 通过读取这个端口的数据来检测鼠标电路的状态,内核会从这个端口读入一个字节的数据,如果该字节的第二个比特位为0,那表明鼠标电路可以接受来自内核的命令,因此,在给鼠标电路发送数据前,内核需要反复从0x64端口读取数据,并检测读到数据的第二个比特位,直到该比特位为0时,才发送控制信息。

3.修改kernel.s 如下:

   	;全局描述符结构 8字节
    ; byte7 byte6 byte5 byte4 byte3 byte2 byte1 byte0
    ; byte6低四位和 byte1 byte0 表示段偏移上限
    ; byte7 byte4 byte3 byte2 表示段基址
    
    ;定义全局描述符数据结构
    ;3 表示有3个参数分别用 %1、%2、%3引用参数
    ;%1:段基址     %2:段偏移上限  %3:段属性
    %macro GDescriptor  3
        dw %2 & 0xffff
        dw %1 & 0xffff
        db (%1>>16) & 0xff 
        dw ((%2>>8) & 0x0f00) | (%3 & 0xf0ff)
        db (%1>>24) & 0xff 
    %endmacro
    DA_32       EQU 4000h   ; 32 位段
    DA_C        EQU 98h ; 存在的只执行代码段属性值
    DA_DRW      EQU 92h ; 存在的可读写数据段属性值
    DA_DRWA     EQU 93h ; 存在的已访问可读写数据段类型值


	;中断描述符表
	;Gate selecotor, offset, DCount, Attr
	%macro Gate 4
		dw  (%2 & 0xffff)
		dw  %1
		dw  (%3 & 0x1f) | ((%4 << 8) & 0xff00)
		dw  ((%2>>16) & 0xffff)
	%endmacro
	DA_386IGate EQU 8Eh ; 中断调用门

   
    org 0x9000 
    jmp entry
    
    [SECTION .gdt]
    ;定义全局描述符                                段基址           段偏移上限       段属性
    LABEL_GDT:              GDescriptor         0,              0,             0
    LABEL_DESC_CODE:        GDescriptor         0,              SegCodeLen-1,  DA_C+DA_32 
    LABEL_DESC_VIDEO:       GDescriptor         0xb8000,        0xffff,        DA_DRW
    LABEL_DESC_STACK:       GDescriptor         0,              STACK_TOP-1,   DA_DRWA+DA_32
    LABEL_DESC_VRAM:        GDescriptor         0,              0xffffffff,    DA_DRW

    ;gdt 表大小
    GdtLen  equ     $-LABEL_GDT

    ;gdt表偏移上限和基地址
    GdtPtr  dw      GdtLen-1
            dd      0


    ;cpu开机进入实模式时使用的段寄存器 cs,ds,es,ss 和偏移地址组成内存地址,内存地址=段寄存器 * 16 + 偏移地址 
    ;保护模式中段寄存器保存的是gdt 描述表中各个描述符的偏移,也叫选择子
    

    SelectorCode32      EQU     LABEL_DESC_CODE-LABEL_GDT
    SelectorVideo       EQU     LABEL_DESC_VIDEO-LABEL_GDT
    SelectorStack       EQU     LABEL_DESC_STACK-LABEL_GDT
    SelectorVRAM        EQU     LABEL_DESC_VRAM-LABEL_GDT


	;中断描述符表
	LABEL_IDT:
	%rep  0x21
		Gate  SelectorCode32, SpuriousHandler,0, DA_386IGate
	%endrep
	
	;键盘中断向量(8259A 键盘中断向量0x20,IRQ1 是键盘中断请求,0x20 + IRQ[n] = 0x21
	.0x21:
		Gate  SelectorCode32, KeyboardHandler,0, DA_386IGate
	
	%rep  10
		Gate  SelectorCode32, SpuriousHandler,0, DA_386IGate
	%endrep
	
	;从中断控制器8259A 中断向量0x28,IRQ4 是鼠标中断请求,0x28 + IRQ[n] = 0x2c
	.0x2c:
		Gate  SelectorCode32, MouseHandler,0, DA_386IGate


	IdtLen  equ $ - LABEL_IDT
	IdtPtr  dw  IdtLen - 1
		    dd  0

    [SECTION .s16]
    [BITS 16]
entry:
    mov ax,cs 
    mov ds,ax
    mov es,ax
    mov ss,ax
    mov sp,0x100 

    ;设置屏幕色彩模式
    mov al,0x13
    mov ah,0
    int 0x10

    ;设置LABEL_DESC_CODE描述符段基址
    mov eax,0 
    mov ax,cs 
    shl eax,4
    add eax,SEG_CODE32
    mov word [LABEL_DESC_CODE+2],ax
    shr eax,16
    mov [LABEL_DESC_CODE+4],al
    mov [LABEL_DESC_CODE+7],ah


    ;设置栈空间
    xor eax,eax
    mov ax,cs 
    shl eax,4
    add eax,LABEL_STACK
    mov word [LABEL_DESC_STACK+2],ax
    shr eax,16
    mov byte [LABEL_DESC_STACK+4],al
    mov byte [LABEL_DESC_STACK+7],ah


    mov eax,0
    mov ax,ds
    shl eax,4 
    add eax,LABEL_GDT
    mov dword [GdtPtr+2],eax

    ;设置GDTR 寄存器
    lgdt [GdtPtr]


    cli     ;关闭可可屏蔽中断,如键盘中断

    in al,0x92 
    or al,0x02
    out 0x92,al 

    mov eax,cr0
    or eax,1 
    mov cr0,eax


	
	call init8259A

	;加载中断描述符
	xor   eax, eax
	mov   ax,  ds
	shl   eax, 4
	add   eax, LABEL_IDT
	mov   dword [IdtPtr + 2], eax
	lidt  [IdtPtr]

	
	sti		;恢复中断
    jmp dword SelectorCode32:0



;初始化8259A中断控制器
init8259A:
	mov  al, 0x11		;向主8259A发送ICW1
	out  0x20, al
	call io_delay

	out 0xa0, al		;向从8259A发送ICW1
	call io_delay


	;20h 分解成ICW2 是, ICW2[0,1,2] = 0, 这是强制要求的,
	;也就是ICW2的值不能是0x21,0x22之类,只要前三位是0就行
	;整个ICW2 = 0x20,这样的话,当主8259A对应的IRQ0管线向CPU发送信号时,
	;CPU根据0x20这个值去查找要执行的代码,IRQ1管线向CPU发送信号时,
	;CPU根据0x21这个值去查找要执行的代码,依次类推

	mov al, 0x20		;向主8259A发送ICW2
	out 0x21, al		;
						;
	call io_delay

	mov  al, 0x28		;向从8259A发送ICW2
	out  0xa1, al
	call io_delay

	;04h 分解成ICW3 相当于ICW[2] = 1, 
	;这表示从8259A通过主IRQ2管线连接到主8259A控制器
	mov  al, 0x04		; 向主8259A发送ICW3 
	out  0x21, al
	call io_delay

	mov  al, 0x02		;向从8259A 发送 ICW3 
	out  0xa1, al
	call io_delay

	mov  al, 0x02
	out  0x21, al
	call io_delay

	out  0xa1, al
	call io_delay


	;还需要再向两个芯片分别发送一个字节,叫OCW(operation control word), 
	;一个OCW是一字节数据,	也就是8bit,每一bit设
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值