Questions on PCI DMA operations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I'm writing a device driver for a custom PCI device, a FPGA, and I need
to do DMA asynchronous transfers from/to the PCI device. By asynchronous
I mean that the DMA operations are triggered by an interrupt received
from the PCI device. I would appreciate some help on the questions I
have on the DMA operations.

Using the DMA streaming mapping as an example, my understanding of how
things happen is the following: I have an interrupt service routine
(ISR) servicing an interrupt that the PCI device activates every time a
DMA operation has to take place. Inside this ISR a simplified flow is,

a. Allocate a DMA buffer (could be pre-allocated), say buff.
b. Call bus_addr=pci_map_single(pci_dev, buff, size, direction)
c. Instruct the PCI device to do the transfer.
d. Call pci-unmap_single(pci_dev, bus_addr, size, direction)
e. kfree(buff) (if needed at this point).

In step b above, bus_address is the physical address the PCI device has
to use to copy from/to depending on the direction of the DMA transfer.

Now, say that the PCI device presents two memory mapped PCI regions,
BAR0 and BAR1, with physical addresses bar0_addr and bar1_addr
respectively. I ioremap these addresses to bar0_vaddr and bar1_vaddr
early in my kernel module.

My questions are:

1. How do I specify DMA target addresses in the PCI device? In my case I
need to do something like this: When copying *to* the PCI device I want
to specify the pair (source=bus_addr, destination=bar0_addr). When
copying *from* the PCI device I want to specify the pair
(source=bar1_addr, destination=bus-addr). I don't see how the DMA APIs
give me this possibility, so I don't know where data is coming from or
going to in the PCI device.

2. How do I actually implement step c above? If I simply use memcpy_toio
and memcpy_fromio, both involving bus_addr, would this magically
translate into a DMA transfer? Or is the operation device-specifc and I
have to explicitly tell the PCI device to do the DMA transfer? Or do I
have to talk directly to the DMA controller to instruct it to do the
transfer? Something else?

3. Step d above is supposed to happen within a different interrupt
service routine, not the same one that triggered the DMA operation in
the first place. Once a DMA operation has taken place, I'm supposed to
get an interrupt telling me that the transaction is done. However, the
pci_dev structure in the kernel only has one IRQ, the one I'm using to
start the whole process asynchronously. How then do I know which IRQ
number will be used to ACK the DMA operations? Is this supposed to be
the same IRQ that triggers the operation in the first place?

For what is worth, I'm using kernel 2.4.18 from Montavista on an IXDP425
(arm) Intel platform. Thank you in advance for your time,

-- 
Pedro


--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
FAQ:           http://kernelnewbies.org/faq/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux