scobb,
Good question. In general, I don't have an answer for you other than to pick either your ISR, or your IST and modify the bits in only one place. Is there a specific reason you need to modify a bit in the ISR? Most of the time, you should only use the ISR to check if an interrupt really did occur, and then handle everything up in the IST.
Also, think about it this way. When the ISR finishes running, that particular interrupt is going to be disabled. It will not be re-enabled until you do so up in the driver-level IST. Therefore, there is (or should be) a one-to-one correspondence between ISR runs and IST runs. So, your ISR shouldn't change anything in the middle of your IST and vice-versa.
It looks like this:
Interrupt fires.
ISR runs, decides an interrupt occurred, returns a SysIntr.
Kernel gets SysIntr, IST gets scheduled to run.
IST can do whatever it wants to as the interrupt is disabled.
When IST returns, interrupt is re-enabled.
This doesn't help with the case of multiple drivers running and accessing the same port though. In that case, you need to be able to share critical sections between the ISTs of the two drivers.
The most common occurance of this is GPIO pins used as interrupts. The easiest way to handle it is to make one driver to handle all of the GPIO interrupts. Then, have other drivers for each individual interrupt wait on it.
For instance, the A400 allows each pin in GPIO port-F to serve as an external interrupt. If I had to manage multiple drivers responding to these pins I would do the following.
Write a driver that responds to any and all port-F interrupts.
Have this driver maintain an internal list of events corresponding to each interrupt.
Write other drivers for each seperate interrupt that register with the first driver.
So, we have gpio.dll which is the driver to handle all GPIO interrupts. Then, lets take drivers foo.dll and bar.dll. Foo.dll is interested in pin-0 and Bar.dll is interested in pin-1.
Gpio.dll installs an ISR for IRQs; 0,5,6,7, 23-26. These are the bits within the Interrupt Controller Register that correspond to GPIO interrupts.
Gpio.dll spins an IST which will wait on a SysIntr value it gets from the OAL.
The installed ISRs all return the SysIntr above.
Gpio.dll exports the standard stream interface.
Foo.dll creates an event. It then calls gpio.dll's IOCTL function to say something like, "When bit zero fires, pulse my event."
Foo.dll then goes to sleep, waiting on its event.
Bar.dll does the same thing foo.dll just did.
Interrupt fires.
The chain of installed ISR's get called. One of our installed GPIO interrupts is going to run, returning the SysIntr that will wake up gpio.dll's IST.
Inside gpio.dll's IST, it looks at the interrupt controller registers to determine which GPIO pin(s) fired. Then, it looks through its internal data structure to see if any drivers have "registered" for that particular pin.
If it finds one, it pulses the event the registered driver indicated.
The registered driver wakes up and does its thing.
The main things you have to deal with are whether or not gpio.dll will re-enable the interrupts, or whether each registered driver will re-enable its own interrupts.
As you can see, it isn't a really tough problem to solve, it's just tough to solve the general case. That is why we at Logic don't have some sort of generic GPIO driver. But, it shouldn't be too hard for you to whip something together that suits your particular needs.
Regards,
--mikee