操作系统学习初步-解读鼠标
-- 以下是控制器的一些定义
-- programmable Interrupt Controller port
PIC0_ICW1 :constant:=16#0020#;
PIC0_OCW2 :constant:=16#0020#;
PIC0_IMR :constant:=16#0021#;
PIC0_ICW2 :constant:=16#0021#;
PIC0_ICW3 :constant:=16#0021#;
PIC0_ICW4 :constant:=16#0021#;
PIC1_ICW1 :constant:=16#00a0#;
PIC1_OCW2 :constant:=16#00a0#;
PIC1_IMR :constant:=16#00a1#;
PIC1_ICW2 :constant:=16#00a1#;
PIC1_ICW3 :constant:=16#00a1#;
PIC1_ICW4 :constant:=16#00a1#;
-- 8259A chip interrupt request
-- chip master
irq_clock1 :constant:=0;
irq_keyboard:constant:=1;
irq_link :constant:=2;
irq_ata2 :constant:=3;
irq_ata1 :constant:=4;
irq_ide2 :constant:=5;
irq_floppy :constant:=6;
irq_ide1 :constant:=7;
-- chip slave
irq_clock2 :constant:=8;
irq_mouse :constant:=12;
irq_harddisk :constant:=14;
irq_hd :constant:=14;
-- 以下是8259可编程控制器的初始化代码:
procedure init_pic is
begin
asm("cli",volatile=>true);
outb(PIC0_IMR,16#ff#);
outb(PIC1_IMR,16#ff#);
outb(PIC0_ICW1,16#11#);
outb(PIC0_ICW2,16#20#);
outb(PIC0_ICW3,4);
outb(PIC0_ICW4,01);
outb(PIC1_ICW1,16#11#);
outb(PIC1_ICW2,16#28#);
outb(PIC1_ICW3,2);
outb(PIC1_ICW4,1);
outb(PIC0_IMR,16#ff#);
outb(PIC1_IMR,16#ff#);
asm("sti",volatile=>true);
end init_pic;
-- 以下是开启8237通道的代码(如果是从片的则打开主片的第2号通道):
procedure enable_irq(irq_no:dword) is
mask:byte;
begin
if irq_no<8 then
mask:=inb(16#21#) and (16#ff# xor (shift_left(1,natural(irq_no))));
outb(16#21#,dword(mask));
elsif irq_no>7 and irq_no<16 then
mask:=inb(16#21#) and (16#ff# xor (shift_left(1,natural(irq_link))));
outb(16#21#,dword(mask));
mask:=inb(16#a1#) and (16#ff# xor (shift_left(1,natural(irq_no-8))));
outb(16#a1#,dword(mask));
end if;
end enable_irq;
-- 以下是开启鼠标控制电路:
procedure wait_kbdController_ready is
begin
loop
exit when (inb(16#64#) and 2)=0;
end loop;
end wait_kbdController_ready;
procedure enable_mouse is
begin
wait_kbdController_ready;
outb(16#64#,16#60#);
wait_kbdController_ready;
outb(16#60#,16#47#);
wait_kbdController_ready;
outb(16#64#,16#d4#);
wait_kbdController_ready;
outb(16#60#,16#f4#);
wait_kbdController_ready;
end enable_mouse;
-- 定义鼠标解码结构:
type MouseDecode is record
phase :byte;
button:byte;
xmove :char;
ymove :char;
x :integer; -- current screen x
y :integer;
ICON :byte_array(0..11):=(16#80#,16#c0#,16#e0#,16#f0#,16#f8#,16#fc#,16#fe#,16#ff#,16#f8#,16#f8#,16#cc#,16#8c#);
end record;
for mouseDecode'alignment use 1;
type lpMouseDecode is access all MouseDecode;
-- Button为按键状态,xmove,ymove为鼠标移动量信息,请注意是有符号的。X,y记录鼠标原始位置。ICON中定义了12个字节(8个点每字节)的点阵鼠标图标。
-- 以下do_mouse为鼠标中断函数。
procedure draw_mouse(md:lpmousedecode) is
bt:byte:=2#1000_0000#;
icon:byte_array(0..11):=(16#80#,16#c0#,16#e0#,16#f0#,16#f8#,16#fc#,16#fe#,16#ff#,16#f8#,16#f8#,16#cc#,16#8c#);
begin
icon(0):=16#80#;
fill_rectangle24(1024,768,dword(md.x),dword(md.y),dword(md.x)+dword(8),dword(md.y)+dword(12),16#48d1cc#);
for j in 0..11 loop
for i in 0..7 loop
if (icon(j) and bt)/=0 then
draw_pixel24(1024,768,dword(md.x+int(md.xmove)+i),dword(md.y+int(md.ymove)+j),16#00ff0000#);
end if;
bt:=shift_right(bt,1);
end loop;
bt:=2#10000000#;
end loop;
md.x:=(if (md.x+int(md.xmove))<1 then 1 elsif (md.x+int(md.xmove))>1024 then 1024 else md.x+int(md.xmove));
md.y:=(if (md.y+int(md.ymove))<1 then 1 elsif (md.y+int(md.ymove))>768 then 768 else md.y+int(md.ymove));
end draw_mouse;
procedure do_mouse is
B1:byte:=0;
md:lpMouseDecode;
pragma import(c,md,"keyboards__pmousedec");
begin
asm("cli",volatile=>true);
outb(PIC1_OCW2,16#64#);
outb(PIC0_OCW2,16#62#);
B1:=inb(16#60#);
if b1/=16#fa# then
md.button:=b1;
B1:=inb(16#60#);
md.xmove:=char(B1);
b1:=inb(16#60#);
md.ymove:=-char(B1);
draw_mouse(md);
end if;
asm("sti",volatile=>true);
asm("leave"&nl&"iretl",volatile=>true);
end do_mouse;