Re: how the interrupt handler(ISR) knows the source of interrupt ?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Mar 29, 2007 at 03:04:53PM +0530, Mansha Linux wrote:
> On 3/29/07, Rajat Jain <rajat.noida.india@xxxxxxxxx> wrote:
> >
> >Here is how it works:
> >
> >1) The driver registers ISR for each device it services, also telling
> >the kernel the corresponding device ID. This is done by calling
> >request_irq().
> >
> >2) When the IRQ occurs, the kernel invokes EACH and every ISR hooked
> >onto that IRQ (Not just the ISR that actually services the device).
> >
> >3) Each ISR receives its original device ID as parameter, it
> >determines whether the corresponding device is the one that generated
> >the IRQ.
> >
> 
> ok. but when the ISR receives the device id and who will pass this device id
> to the ISR ??
> 

Hi Mansha,

It seems you don't have a big picture of how interrupts are handled, I've just
finished understanding interrupts code ;), so Here's a little explanatoin:

* From the device driver side (Also check LDD3, chapter 10):

1) A device driver notifies the system that it want to be signalled when a
   specific IRQ line is triggered. It does so by calling request_irq(). 

   int request_irq(unsigned int irq, irq_handler_t handler,
		   unsigned long irqflags, const char *devname, void *dev_id)

2) As you notice, request_irq() gathers all the needed info from parameters
   and forms with it an `irqaction' structure (the ISR). This irqaction is
   added to a doubly linked list of other ISRs sharing the same IRQ using
   the setup_irq() method.

   int setup_irq(unsigned int irq, struct irqaction *new)


* From hardware and other kernel layers side (code is best source ;)):

1) The hardware has something called IDT (Interrupt Descriptor Table). When a
hardware device issues an interrupt, it finds the address of its handler. usually
this address is initialized to the appropriate entry in interrupt[] array, aka
interrupt[IRQ].

Check:		arch/i386/kernel/i8259.c::native_init_IRQ()

2) every handler in interrupt[] just pushes ~IRQ value in stack, saves other
registers then calls do_IRQ(). After some sanity checks do_IRQ() calls the
specific handler.

     		desc->handle_irq(irq, desc);

3) Above handler is one of handle_simple_irq(), handle_level_irq(),
handle_fasteoi_irq(), ... . The thing common in all those different specialized
type of handlers is that they call the handle_IRQ_event() function. 

    irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)

4) As you can deduce from parameters, it takes the first irqaction in the ISR
list. it follows the list to execute all of ISRs till the list ends.

      	irqreturn_t retval = IRQ_NONE;
	[...]
	do {
		ret = action->handler(irq, action->dev_id);
		if (ret == IRQ_HANDLED)
			status |= action->flags;
		retval |= ret;		action = action->next;
	} while (action);
	[...]
	return retval;


* Now back to your original question, note the first line:

		ret = action->handler(irq, action->dev_id);

Remember, The handler called above was set using using request_irq() and it's
called _now_. If the handler deduced that passed dev_id is not its own, it just
returns IRQ_NONE. 

	#define IRQ_NONE	(0)
	#define IRQ_HANDLED	(1)

Now an interrupt will be considered serviced by the system if retval != 0. That's
the reason why it's ORed with every handler irqreturn_t value.


mm, this could be transofmed to a little article. I Hope it has helped you :).

Regards,

-- 
Ahmed S. Darwish
http://darwish.07.googlepages.com


--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux