Specifications
This is the Title of the Book, eMatter Edition
Copyright © 2005 O’Reilly & Associates, Inc. All rights reserved.
458
|
Chapter 15: Memory Mapping and DMA
In addition to these functions, there are a number of housekeeping facilities that
must be used when dealing with DMA devices:
void disable_dma(unsigned int channel);
A DMA channel can be disabled within the controller. The channel should be
disabled before the controller is configured to prevent improper operation. (Oth-
erwise, corruption can occur because the controller is programmed via 8-bit data
transfers and, therefore, none of the previous functions is executed atomically).
void enable_dma(unsigned int channel);
This function tells the controller that the DMA channel contains valid data.
int get_dma_residue(unsigned int channel);
The driver sometimes needs to know whether a DMA transfer has been com-
pleted. This function returns the number of bytes that are still to be transferred.
The return value is
0 after a successful transfer and is unpredictable (but not 0)
while the controller is working. The unpredictability springs from the need to
obtain the 16-bit residue through two 8-bit input operations.
void clear_dma_ff(unsigned int channel)
This function clears the DMA flip-flop. The flip-flop is used to control access to
16-bit registers. The registers are accessed by two consecutive 8-bit operations,
and the flip-flop is used to select the least significant byte (when it is clear) or the
most significant byte (when it is set). The flip-flop automatically toggles when
eight bits have been transferred; the programmer must clear the flip-flop (to set
it to a known state) before accessing the DMA registers.
Using these functions, a driver can implement a function like the following to pre-
pare for a DMA transfer:
int dad_dma_prepare(int channel, int mode, unsigned int buf,
unsigned int count)
{
unsigned long flags;
flags = claim_dma_lock( );
disable_dma(channel);
clear_dma_ff(channel);
set_dma_mode(channel, mode);
set_dma_addr(channel, virt_to_bus(buf));
set_dma_count(channel, count);
enable_dma(channel);
release_dma_lock(flags);
return 0;
}
Then, a function like the next one is used to check for successful completion of
DMA:
int dad_dma_isdone(int channel)
{
,ch15.13676 Page 458 Friday, January 21, 2005 11:04 AM