日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

FreeBSD 5 內(nèi)核源代碼分析之中斷處理( 四 )


Xatpic_intr0 至Xatpic_intr15,即為函數(shù)名的引用 。而在.s文件中將擴(kuò)展成
代碼:
ALIGN_TEXT;
.globl Xatpic_intr0;
.type Xatpic_intr0,@function;
Xatpic_intr0:

等等,即定義一個(gè)全局的函數(shù),也就是說(shuō)在.c文件中只是引用該函數(shù),真正定義該函數(shù)的是
在sys/i386/isa/atpic_vector.s中,該函數(shù)實(shí)際上就是一個(gè)對(duì)atpic_handle_intr()
函數(shù)的包裝,我們后面還將看到該函數(shù) 。
代碼:
struct atpic_intsrc {
struct intsrc at_intsrc;
int at_irq; /* Relative to PIC base. */
inthand_t *at_intr;
u_long at_count;
u_long at_straycount;
};

static struct atpic_intsrc atintrs[] = {
INTSRC(0),
INTSRC(1),
INTSRC(2),
INTSRC(3),
INTSRC(4),
INTSRC(5),
INTSRC(6),
INTSRC(7),
INTSRC(8),
INTSRC(9),
INTSRC(10),
INTSRC(11),
INTSRC(12),
INTSRC(13),
INTSRC(14),
INTSRC(15),
};

#define INTSRC(irq)
{ { &atpics[(irq) / 8].at_pic }, (irq) % 8,
IDTVEC(atpic_intr ## irq ) }

系統(tǒng)啟動(dòng)時(shí),調(diào)用8259A的初始化函數(shù)atpic_init(),為非SLAVE IRQ號(hào)注冊(cè)中斷源 。
并在i386初始化時(shí)調(diào)用atpic_startup()函數(shù),注冊(cè)中斷向量
IDTVEC(atpic_intr ## irq ),注意,這只是注冊(cè)總的包裝函數(shù),
具體IRQ號(hào)的中斷處理函數(shù)將由設(shè)備驅(qū)動(dòng)通過(guò)intr_add_handler()函數(shù)來(lái)注冊(cè) 。
代碼:
SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND1, atpic_init, NULL)

static void
atpic_init(void *dummy __unused)
{
int i;

/* Loop through all interrupt sources and add them. */
for (i = 0; i < sizeof(atintrs) / sizeof(struct atpic_intsrc); i) {
if (i == ICU_SLAVEID)
continue;
intr_register_source(&atintrs[i].at_intsrc);
}
}

void
init386(first)
int first;
{
......

#ifdef DEV_ISA
atpic_startup();
#endif

......
}

void
atpic_startup(void)
{
struct atpic_intsrc *ai;
int i;

/* Start off with all interrupts disabled. */
imen = 0xffff;
i8259_init(&atpics[MASTER], 0);
i8259_init(&atpics[SLAVE], 1);
atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]);

/* Install low-level interrupt handlers for all of our IRQs. */
for (i = 0; i < sizeof(atintrs) / sizeof(struct atpic_intsrc); i) {
if (i == ICU_SLAVEID)
continue;
ai = &atintrs[i];
ai->at_intsrc.is_count = &ai->at_count;
ai->at_intsrc.is_straycount = &ai->at_straycount;
setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase
ai->at_irq, ai->at_intr, SDT_SYS386IGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
}
}


2,IRQ中斷的處理過(guò)程
代碼:
/*
* Macros for interrupt interrupt entry, call to handler, and exit.
*/
#define INTR(irq_num, vec_name)
.text ;
SUPERALIGN_TEXT ;
IDTVEC(vec_name) ;
pushl $0 ; /* dummy error code */
pushl $0 ; /* dummy trap type */
pushal ; /* 8 ints */
pushl %ds ; /* save data and extra segments ... */
pushl %es ;
pushl %fs ;
mov $KDSEL,%ax ; /* load kernel ds, es and fs */
mov %ax,%ds ;
mov %ax,%es ;
mov $KPSEL,%ax ;
mov %ax,%fs ;
;
FAKE_MCOUNT(13*4(%esp)) ; /* XXX late to avoid double count */
pushl $irq_num; /* pass the IRQ */
call atpic_handle_intr ;
addl $4, %esp ; /* discard the parameter */
;
MEXITCOUNT ;
jmp doreti

IRQ產(chǎn)生時(shí),系統(tǒng)根據(jù)產(chǎn)生中斷的IRQ號(hào)找到相應(yīng)的中斷向量入口,即此處的IDT_VEC(vec_name),
再這里,構(gòu)造好函數(shù)atpic_handle_intr()的調(diào)用棧后,將轉(zhuǎn)到atpic_handle_intr()進(jìn)行處理 。
同系統(tǒng)調(diào)用一樣,這里的調(diào)用棧struct intrframe既是atpic_handle_intr()的參數(shù),也是中斷
返回時(shí)用以恢復(fù)現(xiàn)場(chǎng)的寄存器狀態(tài) 。
代碼:
/* Interrupt stack frame */
struct intrframe {
int if_vec;
int if_fs;
int if_es;
int if_ds;
int if_edi;
int if_esi;
int if_ebp;
int :32;
int if_ebx;
int if_edx;

推薦閱讀