
void main(void)
{
ROOT_DEV = ORIG_ROOT_DEV;
drive_info = DRIVE_INFO;
memory_end = (1<<20) + (EXT_MEM_K<<10);
memory_end &= 0xfffff000;
if (memory_end > 16*1024*1024)
memory_end = 16*1024*1024;
if (memory_end > 12*1024*1024)
buffer_memory_end = 4*1024*1024;
else if (memory_end > 6*1024*1024)
buffer_memory_end = 2*1024*1024;
else
buffer_memory_end = 1*1024*1024;
main_memory_start = buffer_memory_end;
#ifdef RAMDISK
main_memory_start += rd_init(main_memory_start, RAMDISK*1024);
#endif
mem_init(main_memory_start,memory_end);
trap_init();
blk_dev_init();
chr_dev_init();
tty_init();
time_init();
sched_init();
buffer_init(buffer_memory_end);
hd_init();
floppy_init();
sti();
move_to_user_mode();
if (!fork()) {
init();
}
for(;;) pause();
}
1.内核先初始化根设备和硬盘,设置bootsect中读取的软盘为根设备(ROOT_DEV):
ROOT_DEV = ORIG_ROOT_DEV;
fs/super.c:
int ROOT_DEV = 0;
#define ORIG_ROOT_DEV (*(unsigned short *)0x901FC)
2.设置硬盘参数表(drive_info,16字节):
drive_info = DRIVE_INFO;
struct drive_info { char dummy[32]; } drive_info;
#define DRIVE_INFO (*(struct drive_info *)0x90080)
3.规划物理内存格局:
memory_end = (1<<20) + (EXT_MEM_K<<10); memory_end &= 0xfffff000; if (memory_end > 16*1024*1024) memory_end = 16*1024*1024; if (memory_end > 12*1024*1024) buffer_memory_end = 4*1024*1024; else if (memory_end > 6*1024*1024) buffer_memory_end = 2*1024*1024; else buffer_memory_end = 1*1024*1024; main_memory_start = buffer_memory_end;
static long memory_end = 0; static long buffer_memory_end = 0; static long main_memory_start = 0;
>16MB: 缓冲区4MB, 物理16MB
12~16MB: 缓冲区4MB
6~12MB: 缓冲区2MB
小于6MB: 缓冲区1MB
4.设置虚拟盘空间并初始化:
#ifdef RAMDISK main_memory_start += rd_init(main_memory_start, RAMDISK*1024); #endif
(Makefile)假如设定RAMDISK = 512(单位KB)
kernel/blk_drv/ramdisk.c:
#define MAJOR_NR 1
long rd_init(long mem_start, int length)
{
int i;
char *cp;
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
rd_start = (char *) mem_start;
rd_length = length;
cp = rd_start;
for (i=0; i < length; i++)
*cp++ = '';
return(length);
}
将blk_dev[1](即dev mem)的request_fn挂上do_rd_request函数(虚拟盘区请求项处理函数)
然后将虚拟盘所在的内存区全部初始化为0
最后返回虚拟盘区的长度值(单位B)
kernel/blk_drv/ll_rw_blk.c:
struct blk_dev_struct {
void (*request_fn)(void);
struct request * current_request;
};
struct blk_dev_struct blk_dev[NR_BLK_DEV] = {
{ NULL, NULL },
{ NULL, NULL },
{ NULL, NULL },
{ NULL, NULL },
{ NULL, NULL },
{ NULL, NULL },
{ NULL, NULL }
};
kernel/blk_drv/blk.h:
#define DEVICE_REQUEST do_rd_request
struct request {
int dev;
int cmd;
int errors;
unsigned long sector;
unsigned long nr_sectors;
char * buffer;
struct task_struct * waiting;
struct buffer_head * bh;
struct request * next;
};
kernel/blk_drv/ramdisk.c:
void do_rd_request(void)
{
int len;
char *addr;
INIT_REQUEST;
addr = rd_start + (CURRENT->sector << 9);
len = CURRENT->nr_sectors << 9;
if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) {
end_request(0);
goto repeat;
}
if (CURRENT-> cmd == WRITE) {
(void ) memcpy(addr,
CURRENT->buffer,
len);
} else if (CURRENT->cmd == READ) {
(void) memcpy(CURRENT->buffer,
addr,
len);
} else
panic("unknown ramdisk-command");
end_request(1);
goto repeat;
}
5.内存管理结构mem_map初始化:
kernel/mm/memory.c:
#define LOW_MEM 0x100000
#define PAGING_MEMORY (15*1024*1024)
#define PAGING_PAGES (PAGING_MEMORY>>12)
#define MAP_NR(addr) (((addr)-LOW_MEM)>>12)
#define USED 100
static long HIGH_MEMORY = 0;
static unsigned char mem_map [ PAGING_PAGES ] = {0,};
void mem_init(long start_mem, long end_mem)
{
int i;
HIGH_MEMORY = end_mem;
for (i=0 ; i>= 12;
while (end_mem-->0)
mem_map[i++]=0; //再将从start_mem到end_mem对应的mem_map置0
}
6.之后进行异常处理类中断服务程序的挂接:
kernel/blk_dev/traps.c:
void trap_init(void)
{
int i;
set_trap_gate(0,÷_error);
set_trap_gate(1,&debug);
set_trap_gate(2,&nmi);
set_system_gate(3,&int3);
set_system_gate(4,&overflow);
set_system_gate(5,&bounds);
set_trap_gate(6,&invalid_op);
set_trap_gate(7,&device_not_available);
set_trap_gate(8,&double_fault);
set_trap_gate(9,&coprocessor_segment_overrun);
set_trap_gate(10,&invalid_TSS);
set_trap_gate(11,&segment_not_present);
set_trap_gate(12,&stack_segment);
set_trap_gate(13,&general_protection);
set_trap_gate(14,&page_fault);
set_trap_gate(15,&reserved);
set_trap_gate(16,&coprocessor_error);
for (i=17;i<48;i++)
set_trap_gate(i,&reserved);
set_trap_gate(45,&irq13);// 设置协处理器的陷阱门。
outb_p(inb_p(0x21)&0xfb,0x21);// 允许主8259A 芯片的IRQ2 中断请求。
outb(inb_p(0xA1)&0xdf,0xA1);// 允许从8259A 芯片的IRQ13 中断请求。
set_trap_gate(39,¶llel_interrupt);// 设置并行口的陷阱门。
}
TODO: 未追踪IRQ2,3中断设置
include/asm/system.h:
#define _set_gate(gate_addr,type,dpl,addr)
__asm__ ("movw %%dx,%%axnt" //addr低位给eax低位
"movw %0,%%dxnt" //设置edx低位
"movl %%eax,%1nt"
"movl %%edx,%2"
:
: "i" ((short) (0x8000+(dpl<<13)+(type<<8))),
"o" (*((char *) (gate_addr))),
"o" (*(4+(char *) (gate_addr))),
"d" ((char *) (addr)),"a" (0x00080000))
#define set_intr_gate(n,addr)
_set_gate(&idt[n],14,0,addr)
#define set_trap_gate(n,addr)
_set_gate(&idt[n],15,0,addr)
#define set_system_gate(n,addr)
_set_gate(&idt[n],15,3,addr)
7.初始化块设备请求项结构:
kernel/blk_drv/ll_rw_blk.c:
void blk_dev_init(void)
{
int i;
for (i=0 ; i
kernel/blk_drv/blk.h:
#define NR_REQUEST 32
struct request {
int dev;
int cmd;
int errors;
unsigned long sector;
unsigned long nr_sectors;
char * buffer;
struct task_struct * waiting;
struct buffer_head * bh;
struct request * next;
};
8.初始化字符设备请求项结构:
kernel/chr_dev/tty_io.c:
void chr_dev_init(void)
{
}
空,实际上是通过tty_init来初始化的
kernel/chr_dev/tty_io.c:
void tty_init(void)
{
rs_init(); //对串行口进行设置
con_init(); //
}
kernel/chr_dev/serial.c:
void rs_init(void)
{
set_intr_gate(0x24,rs1_interrupt); //设置串行口1中断
set_intr_gate(0x23,rs2_interrupt); //设置串行口2中断
init(tty_table[1].read_q.data); //初始化串行口1
init(tty_table[2].read_q.data); //初始化串行口2
outb(inb_p(0x21)&0xE7,0x21); //允许IRQ3,IRQ4
}
static void init(int port)
{
outb_p(0x80,port+3);
outb_p(0x30,port);
outb_p(0x00,port+1);
outb_p(0x03,port+3);
outb_p(0x0b,port+4);
outb_p(0x0d,port+1);
(void)inb(port);
}
include/linux/tty.h:
struct tty_struct {
struct termios termios;
int pgrp;
int stopped;
void (*write)(struct tty_struct * tty);
struct tty_queue read_q;
struct tty_queue write_q;
struct tty_queue secondary;
};
extern struct tty_struct tty_table[];
kernel/chr_dev/tty_io.c:
struct tty_struct tty_table[] = {
{
{ICRNL,
OPOST|ONLCR,
0,
ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
0,
INIT_C_CC},
0,
0,
con_write,
{0,0,0,0,""},
{0,0,0,0,""},
{0,0,0,0,""}
},{
{0,
0,
B2400 | CS8,
0,
0,
INIT_C_CC},
0,
0,
rs_write,
{0x3f8,0,0,0,""},
{0x3f8,0,0,0,""},
{0,0,0,0,""}
},{
{0,
0,
B2400 | CS8,
0,
0,
INIT_C_CC},
0,
0,
rs_write,
{0x2f8,0,0,0,""},
{0x2f8,0,0,0,""},
{0,0,0,0,""}
}
};
struct tty_queue * table_list[]={
&tty_table[0].read_q, &tty_table[0].write_q,
&tty_table[1].read_q, &tty_table[1].write_q,
&tty_table[2].read_q, &tty_table[2].write_q
};
TODO:未细究
kernel//chr_drv/console.c:
void con_init(void)
{
register unsigned char a;
char *display_desc = "????";
char *display_ptr;
video_num_columns = ORIG_VIDEO_COLS;
video_size_row = video_num_columns * 2;
video_num_lines = ORIG_VIDEO_LINES;
video_page = ORIG_VIDEO_PAGE;
video_erase_char = 0x0720;
if (ORIG_VIDEO_MODE == 7)
{
video_mem_start = 0xb0000;
video_port_reg = 0x3b4;
video_port_val = 0x3b5;
if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
{
video_type = VIDEO_TYPE_EGAM;
video_mem_end = 0xb8000;
display_desc = "EGAm";
}
else
{
video_type = VIDEO_TYPE_MDA;
video_mem_end = 0xb2000;
display_desc = "*MDA";
}
}
else
{
video_mem_start = 0xb8000;
video_port_reg = 0x3d4;
video_port_val = 0x3d5;
if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
{
video_type = VIDEO_TYPE_EGAC;
video_mem_end = 0xbc000;
display_desc = "EGAc";
}
else
{
video_type = VIDEO_TYPE_CGA;
video_mem_end = 0xba000;
display_desc = "*CGA";
}
}
display_ptr = ((char *)video_mem_start) + video_size_row - 8;
while (*display_desc)
{
*display_ptr++ = *display_desc++;
display_ptr++;
}
origin = video_mem_start;
scr_end = video_mem_start + video_num_lines * video_size_row;
top = 0;
bottom = video_num_lines;
gotoxy(ORIG_X,ORIG_Y);
set_trap_gate(0x21,&keyboard_interrupt);
outb_p(inb_p(0x21)&0xfd,0x21);
a=inb_p(0x61);
outb_p(a|0x80,0x61);
outb(a,0x61);
}
TODO:未细究
9.开机启动时间设置:
main.c:
static void time_init(void)
{
struct tm time;
do {
time.tm_sec = CMOS_READ(0);
time.tm_min = CMOS_READ(2);
time.tm_hour = CMOS_READ(4);
time.tm_mday = CMOS_READ(7);
time.tm_mon = CMOS_READ(8);
time.tm_year = CMOS_READ(9);
} while (time.tm_sec != CMOS_READ(0));
BCD_TO_BIn(time.tm_sec);
BCD_TO_BIn(time.tm_min);
BCD_TO_BIn(time.tm_hour);
BCD_TO_BIn(time.tm_mday);
BCD_TO_BIn(time.tm_mon);
BCD_TO_BIn(time.tm_year);
time.tm_mon--;
startup_time = kernel_mktime(&time);
}
TODO:未细究
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)