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 */
do
{
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:
4.3 DMA
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.