4 Input/Output Schemes (Interrupt, polling and DMA)
Now that you understand how to build and run a module, I will introduce
to you I/O schemes. There are three different I/O schemes used in
device driver programming. These are :
In this tutorial, we will use the Interrupt I/O scheme but I will
discuss briefly each of the three schemes.
4.1 Polling I/O
This is the easiest scheme, all you do is polled the data of the register. Here is an example of polling.
/* Poll the device until something happens */
Status = in(status_reg); /* read status register */
Ready = Status & 0x01 ; /* verify the status bit */
Timeout(); /* to get out of the while loop if Ready never switch to FALSE */
}while (Ready == TRUE);
As you see, polling is fairly straightforward. However, Polling wastes CPU time because of the while loop. Polling is commonly used in low-end microprocessor.
4.2 Interrupt I/O:
To get rid of the waiting loop, we can use interrupts. Interrupt is like a trap. It causes the CPU to temporarily halt its execution of the currently running program. The CPU allows the condition that caused the interrupt to be serviced by an interrupt handler. Once the condition has been serviced, the interrupt is cleared, and program execution proceeds from where it was halted prior to the interrupt being generated. An interrupt handler is a function that performs some appropriate action. Here is a schematic of interrupt connections:
These are the steps that occur in the event of an interrupt:
Instead of interrupting the CPU, we can use Direct Memory Access (DMA) to relieve the CPU from the burden of I/O. With DMA, you have direct access to memory. This means the data at the device can be transfer directly to memory with interrupting the CPU.
When you allocate a memory buffer for a DMA type driver, you have to make sure the memory is contiguous. This means when using kmalloc to allocate memory, make sure to specify GFP_DMA flags. A detailed explanation of DMA process is beyond the scope of this tutorial.