MILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">外部中斷可變部分描述:
以irq_desc[]數組描述
Irq_desc_t:
typedef struct {
unsigned int status; /* IRQ status */
hw_irq_controller *handler;
struct irqaction *action; /* IRQ action list */
unsigned int depth; /* nested irq disables */
spinlock_t lock;
} ____cacheline_aligned irq_desc_t;
Irq狀態是由以下各標志組合的:
unsigned int status; /* IRQ status */:
#define IRQ_INPROGRESS 1 /* IRQ handler active - do not enter! */
#define IRQ_DISABLED 2 /* IRQ disabled - do not enter! */
#define IRQ_PENDING 4 /* IRQ pending - replay on enable */
#define IRQ_REPLAY 8 /* IRQ has been replayed but not acked yet */
#define IRQ_AUTODETECT 16 /* IRQ is being autodetected */
#define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */
#define IRQ_LEVEL 64 /* IRQ level triggered */
#define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */
#define IRQ_PER_CPU 256 /* IRQ is per CPU */
struct irqaction *action; /* IRQ action list */:
描述外部中斷的可變部分,對一個外部中斷的所有處理將以irqaction結構掛在action隊列上
Interrupt.hàirqaction:
struct irqaction {
void (*handler)(int, void *, struct pt_regs *);
unsigned long flags;
unsigned long mask;
const char *name;
void *dev_id;
struct irqaction *next;
};
Handler中斷處理函數,dev_id設備標識,用於標記多個設備共享同一個irq
時間中斷處理程序為timer_interrupt
外部設備的驅動程序在初始化時都要創建自己的irqaction結構
Irq.càrequest_irq:
int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
unsigned long irq_flags, const char * devname, void *dev_id)
{
unsigned long retval;
struct irqaction *action;
if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler ||
(irq_flags & SA_SHIRQ && !dev_id))
return -EINVAL;
action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
if (!action)
return -ENOMEM;
action->handler = handler;
action->flags = irq_flags;
action->mask = 0;
action->name = devname;
action->next = NULL;
action->dev_id = dev_id;
retval = setup_arm_irq(irq, action);
if (retval)
kfree(action);
return retval;
}
調用setup_arm_irq向內存申請一塊內存填寫irqaction結構,返回irq號
該函數完成以下工作:
(1) 在數組irq_desc[]中找到程序申請的irq號對應的action隊列
(2) 如果該隊列不為空,說明該irq號被多個設備共享,檢查這種共享是否允許(由老的irqaction結構的flags標識),如果合法,則將新的irqaction結構插到對應的action隊列的末尾
(3) 如果隊列為空,則將irqaction結構插在對應action隊列的頭部,填寫irq_desc[irq]的其他域
至此外部設備驅動向系統注冊中斷完成
中斷釋放:
void free_irq(unsigned int irq, void *dev_id)
完成以下工作:
(1) 檢查irq的合法性
(2) 在action隊列irq_desc[irq].action上,查找action->dev_id == dev_id的irqaction結構
(3) 如果找到這樣的結構,則將其從隊列上摘下,同時釋放其原本占用的內存空間
(4) 如果釋放後,irq_desc[irq]上已經沒有其他的irqaction結構,則釋放irq_desc[irq]上的相應域,關掉中斷