下面我们以8259A为例,看看系统是如何为其注册中断源的,即注册INTSRC(0)~INTSRC(15)。 描述8259A中断控制器的数据结构是struct atpic_intsrc,其第一个成员是一个中断源结构,这种类型定义方法是BSD中常用的方法,起到了面向对象编程中继承的作用。
由于两个级连的8259A中断控制器可以控制16个中断,因此系统注册16个struct atpic_intsrc。这些中断响应程序的的入口地址是IDTVEC(atpic_intr ## irq )。IDTVEC在.c文件中将扩展成Xatpic_intr0 至Xatpic_intr15,即为函数名的引用。而在.s文件中将扩展成
代码:
ALIGN_TEXT; .globl Xatpic_intr0; .type Xatpic_intr0,@function; Xatpic_intr0:
|
等等,即定义一个全局的函数,也就是说在.c文件中只是引用该函数,真正定义该函数的是
在sys/i386/isa/atpic_vector.s中,该函数实际上就是一个对atpic_handle_intr()
函数的包装,我们后面还将看到该函数。
代码:
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 ) }
|
系统启动时,调用8259A的初始化函数atpic_init(),为非SLAVE IRQ号注册中断源。并在i386初始化时调用atpic_startup()函数,注册中断向量IDTVEC(atpic_intr ## irq ),注意,这只是注册总的包装函数,具体IRQ号的中断处理函数将由设备驱动通过intr_add_handler()函数来注册。
代码:
SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, 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.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; 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)); } }
|
阅读(1129) | 评论(0) | 转发(0) |