定義於 include/linux/interrupt.h
int request_irq(
unsigned int irq,
irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
const char *devname,
void *dev_id
);
void free_irq(
unsigned int irq,
void *dev_id
);
struct irqaction {
irqreturn_t (*handler)(int, void *, struct pt_regs *);
unsigned long flags;
cpumask_t mask;
const char *name;
void *dev_id;
struct irqaction *next;
int irq;
struct proc_dir_entry *dir;
};
request_irq() 函式內部則是呼叫 setup_irq() 來進行 IRQ Line 的註冊
其動作是將要求中斷處理的資訊包裝成 struct irqaction 的結構,然後記錄於 irq_desc 陣列中的 IRQ Line 的位置
若有共用 IRQ Line 的中斷,則會以鏈結串列的方式掛在同一個陣列的位置上,如下圖所示
圖中的 hw_interrupt_type 是一個描述中斷控制器的資料結構,用來抽象化不同的中斷控制硬體
例如:舊式的 8259A,或新式的 APIC,也可能是無任何中斷控制器
定義於 include/linux/irq.h
/*
* Interrupt controller descriptor. This is all we need
* to describe about the low-level hardware.
*/
struct hw_interrupt_type {
const char * typename;
unsigned int (*startup)(unsigned int irq);
void (*shutdown)(unsigned int irq);
void (*enable)(unsigned int irq);
void (*disable)(unsigned int irq);
void (*ack)(unsigned int irq);
void (*end)(unsigned int irq);
void (*set_affinity)(unsigned int irq, cpumask_t dest);
};
typedef struct hw_interrupt_type hw_irq_controller;
定義於 arch/i386/kernel/i8259.c
static struct hw_interrupt_type i8259A_irq_type = {
"XT-PIC",
startup_8259A_irq,
shutdown_8259A_irq,
enable_8259A_irq,
disable_8259A_irq,
mask_and_ack_8259A,
end_8259A_irq,
NULL
};
定義於 arch/i386/kernel/io_apic.c
/*
* Level and edge triggered IO-APIC interrupts need different handling,
* so we use two separate IRQ descriptors. Edge triggered IRQs can be
* handled with the level-triggered descriptor, but that one has slightly
* more overhead. Level-triggered interrupts cannot be handled with the
* edge-triggered handler, without risking IRQ storms and other ugly
* races.
*/
static struct hw_interrupt_type ioapic_edge_type = {
.typename = "IO-APIC-edge",
.startup = startup_edge_ioapic,
.shutdown = shutdown_edge_ioapic,
.enable = enable_edge_ioapic,
.disable = disable_edge_ioapic,
.ack = ack_edge_ioapic,
.end = end_edge_ioapic,
.set_affinity = set_ioapic_affinity,
};
static struct hw_interrupt_type ioapic_level_type = {
.typename = "IO-APIC-level",
.startup = startup_level_ioapic,
.shutdown = shutdown_level_ioapic,
.enable = enable_level_ioapic,
.disable = disable_level_ioapic,
.ack = mask_and_ack_level_ioapic,
.end = end_level_ioapic,
.set_affinity = set_ioapic_affinity,
};
定義於 kernel/irq/handle.c
struct hw_interrupt_type no_irq_type = {
.typename = "none",
.startup = startup_none,
.shutdown = shutdown_none,
.enable = enable_none,
.disable = disable_none,
.ack = ack_none,
.end = end_none,
.set_affinity = NULL
};
沒有留言:
張貼留言