[ 1] haribote ipl09.nas 引导程序阅读注释。
[ 2] haribote asmhead.nas 从实模式进入保护模式程序阅读注释。
[ 3] haribote dsctbl.c 设置GDT和IDT程序阅读注释。
[ 4] haribote memory.c 内存管理程序阅读注释。
篇幅较长,可通过浏览器的搜索功能(Ctrl + f)搜索函数名了解相应函数的实现机制,如 init_pic。
[5] haribote int.c 可编程中断控制器(PIC)初始配置程序阅读注释
int.c
/* int.c, 可编程中断控制器(PIC)8259A初始化程序接口 */
#include "bootpack.h"
#include <stdio.h>
/* 两片8259A中断控制器级联时,
* 8259A-2(从片)连在8259A-1(主片)的IR2引脚上,
* 8259A-1与8259A-2共用IR0-IR15分别接收与其相
* 连设备的中断输入。
* IRQ0 - 日时钟(8254)
* IRQ1 - 键盘(8042)
* IRQ2 - 连接8258A-2
* IRQ3 - 串口2(8250 etc.)
* IRQ4 - 串口1
* IRQ5 - 并口2
* IRQ6 - 软盘
* IRQ7 - 并口1
*
* IRQ8 - 实时钟(CMOS RAM)
* IRQ9 - 顶替IRQ2
* IRQ12 - PS2鼠标
* IRQ13 - 协处理器
* IRQ14 - 硬盘
* IRQ10,11,15 - 暂保留未用
*
* 经init_pic配置后,
* [IR0, IRQ15]中断向量号[0x20, 0x2f]对应。
* 即在开启8259A中断和设置IDT后,在允许CPU处理当
* 前任务中断前提下,与IR0-IRQ15相连设备分别向引
* 脚IR0-IR15发出中断时,配置在IDT[20h..2fh]中的
* 程序将会被CPU执行。*/
/* init_pic,
* 初始化配置可编程中断控制器(PIC),
* 为PIC分配中断向量[0x20, 0x2f],暂屏蔽所有中断。*/
void init_pic(void)
{
/* 往8259A-1和8259A-2写OCW1,先让8259A屏蔽所有中断输入。
* 同 asmhead.nas 中语句,由于目前还未对8259A下发过ICW
* 命令组,此语句应该无效。*/
io_out8(PIC0_IMR, 0xff );
io_out8(PIC1_IMR, 0xff );
/* 向8259A-1下发
* ICW1,边缘触发中断,多片级联,会下发ICW4;
* ICW2,8259A-1中断号为[0x20,0x27];
* ICW3,IR2连接从片;
* ICW4,16位微机处理方式。*/
io_out8(PIC0_ICW1, 0x11 );
io_out8(PIC0_ICW2, 0x20 );
io_out8(PIC0_ICW3, 1 << 2);
io_out8(PIC0_ICW4, 0x01 );
/* 向8259A-2下发
* ICW1,边缘触发中断,多片级联,会下发ICW4;
* ICW2,8259A-1中断号为[0x28,0x2f];
* ICW3,从片中断级为2;
* ICW4,16位微机处理方式。*/
io_out8(PIC1_ICW1, 0x11 );
io_out8(PIC1_ICW2, 0x28 );
io_out8(PIC1_ICW3, 2 );
io_out8(PIC1_ICW4, 0x01 );
/* 向8258A-1写OCW1=0xfb允许IRQ2中断即接收从片中断,
* 向8259A-2写OCW1=0xff即屏蔽从片所有中断。*/
io_out8(PIC0_IMR, 0xfb );
io_out8(PIC1_IMR, 0xff );
return;
}
bootpack.h
/* ... */
/* int.c */
void init_pic(void);
/* 8259A-1提供20h和21h两个端口地址供编程配置,
* 8259A-2提供a0h和a1两个端口地址供编程配置。
*
* 需先通过8259A端口地址下发ICW初始化命令字组,
* 然后才能通过8259A端口地址下发OCW操作命令字组,
* 同一个端口地址在不同阶段配置不同的功能。*/
/* 在8259A正确的配置顺序下,
* 以下端口地址的在不同阶段的作用分别是, */
#define PIC0_ICW1 0x0020 /* 写8259A-1 ICW1的端口地址 */
#define PIC0_OCW2 0x0020 /* 写8259A-1 OCW2的端口地址 */
#define PIC0_IMR 0x0021 /* 写8259A-1 OCW1的端口地址 */
#define PIC0_ICW2 0x0021 /* 写8259A-1 ICW2的端口地址 */
#define PIC0_ICW3 0x0021 /* 写8259A-1 ICW3的端口地址 */
#define PIC0_ICW4 0x0021 /* 写8259A-1 ICW4的端口地址 */
#define PIC1_ICW1 0x00a0 /* 写8259A-2 ICW1的端口地址 */
#define PIC1_OCW2 0x00a0 /* 写8259A-2 OCW2的端口地址 */
#define PIC1_IMR 0x00a1 /* 写8259A-2 OCW1的端口地址 */
#define PIC1_ICW2 0x00a1 /* 写8259A-2 ICW2的端口地址 */
#define PIC1_ICW3 0x00a1 /* 写8259A-2 ICW3的端口地址 */
#define PIC1_ICW4 0x00a1 /* 写8259A-2 ICW4的端口地址 */
/* ... */