hd_init一共有四句;
第一句:
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
主要获取块设备操作函数地址,DEVICE_REQUEST其实是个调用宏,获取他的地址有什么用呢?获取了快设备操作函数地址,当要访问硬盘是,就可以直接使用该地址来访问块设备。
第二句:set_intr_gate(0x2E,&hd_interrupt);
这是一个中断初始化函数,用于指定中断服务例程。宏#define set_intr_gate(n,addr) _set_gate(&idt[n],14,0,addr)
函数实体:
#define _set_gate(gate_addr,type,dpl,addr) \
__asm__ ("movw %%dx,%%ax\n\t" \
"movw %0,%%dx\n\t" \
"movl %%eax,%1\n\t" \
"movl %%edx,%2" \
: \
: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
"o" (*((char *) (gate_addr))), \
"o" (*(4+(char *) (gate_addr))), \
"d" ((char *) (addr)),"a" (0x00080000))
是一段内联汇编,主要是设置段描述符,其实就是中断门描述符。对着图看。如图:
而中断服务程序是(hd_interrupt):
hd_interrupt:
pushl %eax
pushl %ecx
pushl %edx
push %ds
push %es
push %fs
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
movl $0x17,%eax
mov %ax,%fs
movb $0x20,%al
outb %al,$0xA0 # EOI to interrupt controller #1
jmp 1f # give port chance to breathe
1: jmp 1f
1: xorl %edx,%edx
xchgl do_hd,%edx
testl %edx,%edx
jne 1f
movl $unexpected_hd_interrupt,%edx
1: outb %al,$0x20
call *%edx # "interesting" way of handling intr.
pop %fs
pop %es
pop %ds
popl %edx
popl %ecx
popl %eax
iret
是一段汇编,用于真正访问硬盘。
第三和第四句:
outb_p(inb_p(0x21)&0xfb,0x21);
outb(inb_p(0xA1)&0xbf,0xA1);
是8259A中断设置,设置的是磁盘中断。
总结一下,首先设置并获取块设备函数地址,用以后要通过块设备访问磁盘时的入口地址。接着设置中断门描述符,包括中断服务列程,
最后设置磁盘中断,就是开启相应中断位。当要访问磁盘时,调用块设备函数,系统接到访问请求,发生一个中断,
执行中断服务程序hd_interrupt,访问磁盘,对磁盘进行操作.
2
floppy_init和前面基本一致,只是访问的是软驱。
3
sti()的实体很简单,如下,就是开启中断,开始运行进程进程:
#define sti() __asm__ ("sti"::)
sti是开中断,允许硬件中断
4
move_to_user_mode的实体也是一段内联汇编
#define move_to_user_mode() \
__asm__ ("movl %%esp,%%eax\n\t" \
"pushl $0x17\n\t" \
"pushl %%eax\n\t" \
"pushfl\n\t" \
"pushl $0x0f\n\t" \
"pushl $1f\n\t" \
"iret\n" \
"1:\tmovl $0x17,%%eax\n\t" \
"movw %%ax,%%ds\n\t" \
"movw %%ax,%%es\n\t" \
"movw %%ax,%%fs\n\t" \
"movw %%ax,%%gs" \
:::"ax")
主要是将进程0从内核态移动到移应用中,就是特权级0到3的过程
阅读(2609) | 评论(0) | 转发(0) |