1.几个重要的数据结构:
///////////////////////////////////////////////
1.struct irq_desc; 表示一个中断号
31struct irq_desc;
32typedef void (*irq_flow_handler_t)(unsigned int irq,
33 struct irq_desc *desc);
175struct irq_desc {
176 unsigned int irq; //中断号
177 struct timer_rand_state *timer_rand_state;
178 unsigned int *kstat_irqs;
179#ifdef CONFIG_INTR_REMAP
180 struct irq_2_iommu *irq_2_iommu;
181#endif
182 irq_flow_handler_t handle_irq; //该中断号对应的公共处理程序
183 struct irq_chip *chip; //中断控制器
184 struct msi_desc *msi_desc;
185 void *handler_data; //handle_irq公共处理程序的参数
186 void *chip_data;
187 struct irqaction *action; //该中断线上已经注册的中断处理程序链表
188 unsigned int status; //中断线此时的状态
189
190 unsigned int depth;
191 unsigned int wake_depth;
192 unsigned int irq_count;
193 unsigned long last_unhandled;
194 unsigned int irqs_unhandled;
195 raw_spinlock_t lock;
196#ifdef CONFIG_SMP
197 cpumask_var_t affinity;
198 const struct cpumask *affinity_hint;
199 unsigned int node;
200#ifdef CONFIG_GENERIC_PENDING_IRQ
201 cpumask_var_t pending_mask;
202#endif
203#endif
204 atomic_t threads_active;
205 wait_queue_head_t wait_for_threads;
206#ifdef CONFIG_PROC_FS
207 struct proc_dir_entry *dir;
208#endif
209 const char *name; //中断线的名字
210}
<全部中断号组成一个中断号数组>
216#ifndef CONFIG_SPARSE_IRQ
217extern struct irq_desc irq_desc[NR_IRQS];
218#endif
///////////////////////////////////////////
2.struct irqaction; 表示一个中断处理程序
98typedef irqreturn_t (*irq_handler_t)(int, void *);
113struct irqaction {
114 irq_handler_t handler; //中断处理程序
115 unsigned long flags; //中断发生时的一些标志
116 const char *name; //中断程序名字
117 void *dev_id; //设备标志
118 struct irqaction *next; //该中断线上的下一个中断处理程序
119 int irq; //中断号
120 struct proc_dir_entry *dir;
121 irq_handler_t thread_fn;
122 struct task_struct *thread;
123 unsigned long thread_flags;
124};
///////////////////////////////////////
3.struct irq_chip; 表示一个中断控制器
111struct irq_chip {
112 const char *name; //中断控制器的名字
113 unsigned int (*startup)(unsigned int irq); //启动某条中断线
114 void (*shutdown)(unsigned int irq); //关闭某条中断线
115 void (*enable)(unsigned int irq); //允许某条中断线中断
116 void (*disable)(unsigned int irq); //禁止某条中断线中断
117
118 void (*ack)(unsigned int irq);
119 void (*mask)(unsigned int irq);
120 void (*mask_ack)(unsigned int irq);
121 void (*unmask)(unsigned int irq);
122 void (*eoi)(unsigned int irq);
123
124 void (*end)(unsigned int irq);
125 int (*set_affinity)(unsigned int irq,
126 const struct cpumask *dest);
127 int (*retrigger)(unsigned int irq);
128 int (*set_type)(unsigned int irq, unsigned int flow_type);
129 int (*set_wake)(unsigned int irq, unsigned int on);
130
131 void (*bus_lock)(unsigned int irq);
132 void (*bus_sync_unlock)(unsigned int irq);
133
134 /* Currently used only by UML, might disappear one day.*/
135#ifdef CONFIG_IRQ_RELEASE_METHOD
136 void (*release)(unsigned int irq, void *dev_id);
137#endif
138 /*
139 * For compatibility, ->typename is copied into ->name.
140 * Will disappear.
141 */
142 const char *typename;
143};
2.上述三个结构的关系:
3.中断发生时的执行过程:
1.键盘产生一个中断,通过中断线把信号(中断号)发给中断控制器
2.中断控制器把该中断号发给处理器,处理器停止当前工作
3.处理器调用common_interrup这个公共的中断处理程序,保存当前执行进程的环境,大概就是一些寄存器值,都保存到该进程的堆栈中
4.处理器调用do_IRQ()函数,该函数会调用struct irq_desc结构中的属于该中断线的公共处理程序,即 handle_irq字段指向的函数
5.handle_irq指向的函数最终会调用上述图片中所示的hand_IRQ_event函数,该函数会依次调用属于该中断线上的处理程序,即依次调用struct irq_desc结构中的action字段指向的属于该中断线上的中断处理程序链表上的处理程序
6.中断处理程序执行完后,调用上述图片中的ret_from_intr()函数,该函数返回到中断之前的现场环境