2

I'm implementing RTEMS driver for Ethernet card by porting it from Linux. Much of the work is done, processor IO mode is working ok, as well as interrupt handling. Now I'm having problems implementing DMA.

Specifically, in Linux driver I use as a base, function dma_alloc_coherent() is used. This function will return two different addresses: one is address that driver code (host CPU) will see, and other one is the address that card will use to access same memory region via PCI during DMA.

I'm having problems finding appropriate replacement function. First I thought of using malloc() and then pci_pci2cpu to translate this address to the one one card can access, however, pci_pci2cpu returns 0xFFFFFFFF for IO and 0x0 for remaining two modes.

Second approach I considered is using dual ported memory manager, but I'm not finding useful examples of it's usage. For example, rtems_port_create() function requires pointers *internal_start and *external_start to be provided, but I'm not sure where are this pointers comming from?

I use Gaisler RTEMS version 4.11 and Sparc architecture (LEON3 cpu).

Best, Ivan

Ivan
  • 81
  • 4

2 Answers2

3

Ok basically I got this figured out.

First, RTEMS has flat memory model, so address that malloc() returns is actual physical address in memory. That means I don't need dma_alloc_coherent() as malloc() is already doing same thing. For aligned memory, I used posix_memalign() which is also supported.

Second, I needed to see is there any address translation between the card and memory. This is not related to RTEMS, but rather to the system architecture, so after looking into GRLIB user manual and looking at RTEMS initialization code for grpci2 core, I found that there is no memory translation (it's set 1:1).

Bottom line is that if I allocate buffer with simple malloc and give that address to PCI card, it will be able to access (read/write) this buffer.

These were all assumptions that I started with, but in the end my problems were in faulty DMA chip. :)

Ivan
  • 81
  • 4
0

I'm not sure I got the question right but anyway:

RTEMS does not implements an handler for the LEON family DMA. To use the DMA you need to exploit the LEON structure you can find in leon.h header file. That structure is linked to the memory addresses of the LEON3 processor. Alternatively you can address the registers directly.

After that you need to go to http://www.gaisler.com/index.php/products/components/ut699 and download the functional manual of the UT699 (or search for the SoC you are using :) )

There you will find how to write the registries in the correct order to initiate a DMA transfer from/to PCI target.

Cheers

Kons
  • 94
  • 7
  • Hi, thank you for response. I'm not sure if I understood your answer. Basically, PCI ethernet card has it's own DMA controller(s), and I initiate transfer by writing to it's memory mapped registers. For (simplified) example, I give it pointer to the buffer that needs to be sent, buffer length and some more control parameters and it should initiate and handle DMA. Question is, does PCI card sees entire RAM and is the address of the buffer that I give to the card same address that I got from malloc(), or does this address need to be translated somehow so the card can see it? – Ivan Feb 29 '16 at 07:41
  • how is it the ethernet card connected to the LEON 3? (I got the question wrong btw :) ) – Kons Mar 01 '16 at 21:22
  • Card is connected via PCI Express bus and it's mapped to memory so I can read it's registers. I think only question I have is whether there is any address translation between PCI bus and LEON3, or, how can I determine it. I use RTEMS OS, which has flat memory model (ie, no virtual addresses), but I'm still not clear if card can access the memory address that I got via malloc(), or do I have to translate this somehow so cards DMA controller can access it? – Ivan Mar 03 '16 at 11:34