Alan Cox (alan@lxorguk.ukuu.org.uk)
Fri, 16 Oct 1998 17:08:06 +0100 (BST)
> Can anyone point me to a Linux driver that illustrates the use of DMA?
There are quite a few candidates - the floppy driver is rather convoluted as
an example but some of the net cards are easier to follow.
The interfaces you need
kmalloc(size, GFP_KERNEL|GFP_DMA);
to get ISA DMA'able memory or NULL if it fails.
request_dma(n, "name");
Grab a DMA channel. Makes you appear in /proc/dma as owner too
free_dma(n)
Give it back
disable_dma(n)
Turns a DMA channel off
enable_dma(n)
Turns a DMA channel on
set_dma_mode(channel, DMA_MODE_READ or DMA_MODE_WRITE)
(+0x10 if you need AUTOINIT)
This sets the direction of transfer
clear_dma_ff(chan)
Clears the channel flip flop (do this before setting the addr/size)
set_dma_addr(chan, virt_to_bus(addr));
The virt_to_bus isnt needed in 2.0.x intel but is needed in 2.1 for all
architectures and 2.0 for some others. It translates the kernel CPU address
space to what is seen on the address bus.
set_dma_count(dma, count)
Sets the number of bytes to transfer
And get_dma_residue(chan) tells you what got left over
It tends to look something like
if(request_dma(my_dma, "MyDriver"))
{
printk("Someone has my DMA channel\n");
return -EBUSY;
}
set_dma_mode(my_dma, DMA_MODE_WRITE);
Then
save_flags(flags);
cli();
disable_dma(my_dma);
clear_dma_ff(my_dma);
set_dma_addr(my_dma, virt_to_phys(buffer));
set_dma_count(my_dma, buffer_len);
enable_dma(my_dma);
restore_flags(flags);
and in the IRQ
disable_dma(my_dma);
n=get_dma_residue(my_dma);
enable_dma(my_dma);
if(n>0)
printk("Card left %d bytes!\n", n);
Alan
-- To unsubscribe, send mail to: linux-parport-request@torque.net --
-- with the single word "unsubscribe" in the body of the message. --
This archive was generated by hypermail 2.0b3 on Wed 30 Dec 1998 - 10:18:36 EST