Re: Abstracting the interrupt interface
Posted: Sat Mar 17, 2012 12:23 pm
I keep mine pretty simple, most of the code for the determining what resources a device uses is done outside of the device itself and simply passed to the driver when it's initialized. The driver will request to install a handler for that event and the OS will install one, for user space drivers this will run the proper task through a callback as Combuster described, and await a response back saying either 'I generated this interrupt and have handled it', at which point the kernel will take care of the EOI and go on about it's merry way.
For kernel space drivers it's much the same, without the task switching and with more direct call backs. Some devices also handle interrupt events through other methods because they're required to. For example ACPI compatible embedded controllers must signal their interrupts through an SCI and ACPI's GPE interface (this is not the case in 5.0 on a 'hardware reduced' platform). So drivers attach instead to a GPE event interface, which ACPICA implements wonderfully.
In general I'd agree with the idea of just abstracting it into some catch all 'interrupt event' and letting the kernel, HAL or whatever other drivers take care of the implementation specific details. It makes it much easier to signal and deal with those situations where you have a bus, behind a bus, behind a bus as well. Another example from the world of ACPI, you could have an Smbus controller requiring attention which is behind an EC controller. Generally this will be signaled by a single SCI being generated, which could be shared by a huge number of devices. The ACPI driver figures out that it's a GPE generated from the embedded controller, which is then forced to issue a query command and report back. The query command will tell it that the SMBus controll is what actually generated the interrupt. From there the SMBus driver will actually have to check the SMBus controller and figure out what device behind the SMBus was asserting it's alarm signal. Let's say in the end it's a smart battery device, so that in the end is the one device that ended up asserting an SCI, but to figure it out you had to jump through all those hoops.
Obviously such a scenario doesn't fit in too cleanly with the idea of a numbered interrupt line on the processor or it's bus. You just have a hardware event that signaled a very large 'catch all' interrupt along the line. You pretty much have to abstract it into some event caused with a virtual id number, or an event controlled by the SMBus controller itself. Events let you cleanly abstract away the mess of how a particular device or driver actually recieved the event, and focus simply on handling it.
For kernel space drivers it's much the same, without the task switching and with more direct call backs. Some devices also handle interrupt events through other methods because they're required to. For example ACPI compatible embedded controllers must signal their interrupts through an SCI and ACPI's GPE interface (this is not the case in 5.0 on a 'hardware reduced' platform). So drivers attach instead to a GPE event interface, which ACPICA implements wonderfully.
In general I'd agree with the idea of just abstracting it into some catch all 'interrupt event' and letting the kernel, HAL or whatever other drivers take care of the implementation specific details. It makes it much easier to signal and deal with those situations where you have a bus, behind a bus, behind a bus as well. Another example from the world of ACPI, you could have an Smbus controller requiring attention which is behind an EC controller. Generally this will be signaled by a single SCI being generated, which could be shared by a huge number of devices. The ACPI driver figures out that it's a GPE generated from the embedded controller, which is then forced to issue a query command and report back. The query command will tell it that the SMBus controll is what actually generated the interrupt. From there the SMBus driver will actually have to check the SMBus controller and figure out what device behind the SMBus was asserting it's alarm signal. Let's say in the end it's a smart battery device, so that in the end is the one device that ended up asserting an SCI, but to figure it out you had to jump through all those hoops.
Obviously such a scenario doesn't fit in too cleanly with the idea of a numbered interrupt line on the processor or it's bus. You just have a hardware event that signaled a very large 'catch all' interrupt along the line. You pretty much have to abstract it into some event caused with a virtual id number, or an event controlled by the SMBus controller itself. Events let you cleanly abstract away the mess of how a particular device or driver actually recieved the event, and focus simply on handling it.