PCI memory access on PPC

I have a PCI card installed in a PPC (sandpoint). I can’t seem
to access the memory correctly. The only bank of memory that has
the correct contents is bank 0. The card works fine with a PII
using the same resource manager.

Here is the mmap calls that I am using.

for( i = 0; i < PCI_ADDRESS_BLOCKS; i++ )
{
if( info->BaseAddressSize == 0 )
{
break;
}

attr.info.mem_io.id = i;
attr.info.mem_io.pci_base_address =
info->PciBaseAddress;
attr.info.mem_io.cpu_base_address =
info->CpuBaseAddress;
attr.info.mem_io.base_address_size =
info->BaseAddressSize;

if( PCI_IS_IO( info->PciBaseAddress ))
{
attr.type = DEVCCSP_TYPE_IO;
attr[i].info.mem_io.io_ptr =
mmap_device_io( attr[i].info.mem_io.base_address_size,
PCI_IO_ADDR(
attr[i].info.mem_io.cpu_base_address ) );
}
else if( PCI_IS_MEM( info->PciBaseAddress[i] ))
{
attr[i].type = DEVCCSP_TYPE_MEMORY;
attr[i].info.mem_io.mem_ptr =
mmap_device_memory( 0,
attr[i].info.mem_io.base_address_size,
PROT_READ | PROT_WRITE | PROT_NOCACHE,
0,
PCI_MEM_ADDR(
attr[i].info.mem_io.cpu_base_address ));

if( attr[i].info.mem_io.mem_ptr == MAP_FAILED )
{
VERBOSE2( “Failed to map Memory bank %d to address 0x%016llX.”,
i, attr[i].info.mem_io.cpu_base_address );
return( EXIT_FAILURE );
}
HOSTDEBUG_LTEXT2( 5, “Memory bank %d mapped to address %p.”,
i, attr[i].info.mem_io.mem_ptr );
}
}

I’ve read the postings on this news group regarding the
issue of using the ieieo() instruction following a
read/write to a h/w register. I’ve added the opcode
throughout my resource manager without any success.

To access i/o, I use the outx()/inx() macros. To access the memory I
use memcpy().

Any thoughts/ideas? Anyone?

John O’Grady.

John O’Grady <john@focus-systems.on.ca> wrote:

: I have a PCI card installed in a PPC (sandpoint). I can’t seem
: to access the memory correctly. The only bank of memory that has
: the correct contents is bank 0. The card works fine with a PII
: using the same resource manager.

Still haven’t seen a reply to my original posting.

Has anyone out there had difficulties/success reading from physical
memory on a PCI card, installed in a PPC?

I’ve written a resource manager. This resource manager performs a
pci_attach() request. Once the manager has found the PCI card
and retrieved the physical address for each PCI bank, it then
uses the mmap_device_memory() or mmap_device_io() functions to map
the physical address into the resource managers address space.
The problem is that when I read from the memory of the PCI card
the information that I expect is not there.

It’s as if the wrong address is being referenced.

What complicates the situation is that I can compile the resource
manager for the x86 platform. When run on the x86 platform I have
no difficulties reading/writing the PCI card.

The results are from working with the Neutrino 2.11 package.

I would appreciate any help or insight anyone could provide.

Thanks,
John O’Grady

Hi,

I am afraid I do not have an answer for you… only an observation on your
post(s)
This post, and the original post on the thread both popped up together this
p.m. (Mar 23)
I think the original post got “stuck” somewhere… hence the lack of a
timely answer…

I might be just shooting into the sky since I haven’t done that myself.
But if it works on x86 but not on PPC I’d suspect endianness. PCI is
inherently little-endian, while PPC is inherently big-endian (my MCP750
docs say). Thus, PCI addresses must be translated on PPC. From what I
understand this should be done by PCI chipset (Raven or Hawk for
example) but there might be more to it. And I don’t know what chipset is
used on Sandpoint and if it does that …

  • igor

John O’Grady wrote:

John O’Grady <> john@focus-systems.on.ca> > wrote:

: I have a PCI card installed in a PPC (sandpoint). I can’t seem
: to access the memory correctly. The only bank of memory that has
: the correct contents is bank 0. The card works fine with a PII
: using the same resource manager.

Still haven’t seen a reply to my original posting.

Has anyone out there had difficulties/success reading from physical
memory on a PCI card, installed in a PPC?

I’ve written a resource manager. This resource manager performs a
pci_attach() request. Once the manager has found the PCI card
and retrieved the physical address for each PCI bank, it then
uses the mmap_device_memory() or mmap_device_io() functions to map
the physical address into the resource managers address space.
The problem is that when I read from the memory of the PCI card
the information that I expect is not there.

It’s as if the wrong address is being referenced.

What complicates the situation is that I can compile the resource
manager for the x86 platform. When run on the x86 platform I have
no difficulties reading/writing the PCI card.

The results are from working with the Neutrino 2.11 package.

I would appreciate any help or insight anyone could provide.

Thanks,
John O’Grady

Thanks, I just found out that the mail server that I use, has been
experiencing a problem posting to this news group. The article actually
appeared in my news
reader but had not been sent. Sorry for the mistake.

“Steve Munnings, Corman Technologies” <steve@cormantech.com> wrote in
message news:99fok0$4aj$1@inn.qnx.com

Hi,

I am afraid I do not have an answer for you… only an observation on your
post(s)
This post, and the original post on the thread both popped up together
this
p.m. (Mar 23)
I think the original post got “stuck” somewhere… hence the lack of a
timely answer…

Previously, Igor Kovalenko wrote in qdn.public.qnxrtp.os:

I might be just shooting into the sky since I haven’t done that myself.
But if it works on x86 but not on PPC I’d suspect endianness. PCI is
inherently little-endian, while PPC is inherently big-endian (my MCP750
docs say). Thus, PCI addresses must be translated on PPC. From what I
understand this should be done by PCI chipset (Raven or Hawk for
example) but there might be more to it. And I don’t know what chipset is
used on Sandpoint and if it does that …

IMHO transparent hardware endian swapping is generally a Bad Thing[tm]
which should be avoided at all costs.

This is especially true on the PPC, which has some very nice endian-swapping
load and store operands.

Ideally there should be a set of read*() and write*() calls that automagically
read and write big-endian, little-endian, and raw-endian values to and from
PCI memory space (as with in*() and out*() for IO space), with appropriate
barrier instructions before and/or after, but it doesn’t appear that there are
any (according to the documentation) in NTO.


Cheers - Tony ‘Nicoya’ Mantler :slight_smile:


Tony Mantler | Proud ---- Days since the last
QNX Consulting | of our | 27 |
tony@astra.mb.ca | Record ---- “Gerbil Incident”

John O’Grady <john@focus-systems.on.ca> wrote:

: Has anyone out there had difficulties/success reading from physical
: memory on a PCI card, installed in a PPC?
:
: I’ve written a resource manager. This resource manager performs a
: pci_attach() request. Once the manager has found the PCI card
: and retrieved the physical address for each PCI bank, it then
: uses the mmap_device_memory() or mmap_device_io() functions to map
: the physical address into the resource managers address space.
: The problem is that when I read from the memory of the PCI card
: the information that I expect is not there.
:
: It’s as if the wrong address is being referenced.
:
: What complicates the situation is that I can compile the resource
: manager for the x86 platform. When run on the x86 platform I have
: no difficulties reading/writing the PCI card.

I have tried to link the problem to endian conversion. I will admit
I cannot be entirely certain that this is not the problem. I am
new to working with PCI cards on a PPC platform.

Still the information filled into the pci_dev_info structure does not
appear to be suffering from signs of endianness :slight_smile:. For instance the
memory size elements are 100% accurate for all 6 PCI banks. Also I can
mmap_device_memory() bank 0 and read/write the entire 128 bytes. The contents
match the correct configuration for the pci chip (PLX9052).

I have discussed the matter with the designer of the PCI card. From his
investigation he feels that I have access to the correct address for
banks 0, 1, 4 and 5. (Difficult to verify without enabling read/write of
banks 4 and 5 which must be done from bank 2.) It is his feeling that
the resource manager when reading address 0x0 of bank two is really
accessing the contents of address 0x80 of bank two.

Yes, I am confused too.

My next step is to attempt to use a different PMC card with an entirely different
pci bridge chip (let’s hope I can get the boot image to work).

Here is some output from the resource manager. Included is a listing of the
contents of the pci_dev_info structure:

Looking for PCI card: Vendor 0x10B5, device 0x9050.
devc-csp.c:Memory bank 0 mapped to address 0x80100000. // Result of mmap_device_memory()
devc-csp.c:Memory bank 2 mapped to address 0x80102080.
devc-csp.c:Memory bank 3 mapped to address 0x80104080.
devc-csp.c:Memory bank 4 mapped to address 0x80205000.
devc-csp.c:Memory bank 5 mapped to address 0x90205000.
Found 6 address blocks.
============= pci_dev_info ============= /* start. /
DeviceId: 0x9050
VendorId: 0x10B5
SubsystemId: 0x0000
SubsystemVendorId: 0x0000
BusNumber: 0
DevFunc: 40 /
Different than the x86. /
Revision: 2
Class: 0x118000
Irq: 255
CpuIoTranslation: 0x0000000000000000
CpuMemTranslation: 0x0000000000000000
CpuISaTranslation: 0x00000000FE000000 /
Also not present on x86. /
CpuBmstrTranslation: 0x0000000000000000
PciBaseAddress 0: 0x00000000F0000000
CpuBaseAddress 0: 0x00000000F0000000
BaseAddressSize 0: 128
PciBaseAddress 1: 0x0000000000BFFE01
CpuBaseAddress 1: 0x00000000FEBFFE01
BaseAddressSize 1: 128
PciBaseAddress 2: 0x00000000F0000080 /
80? /
CpuBaseAddress 2: 0x00000000F0000080
BaseAddressSize 2: 4096
PciBaseAddress 3: 0x00000000F0001080
CpuBaseAddress 3: 0x00000000F0001080
BaseAddressSize 3: 1048576
PciBaseAddress 4: 0x00000000E0000000
CpuBaseAddress 4: 0x00000000E0000000
BaseAddressSize 4: 268435456
PciBaseAddress 5: 0xFFFFFFFFF9E00000 /
Seems erroneous but contents are correct.
CpuBaseAddress 5: 0x00000000F7E00000
BaseAddressSize 5: 1048576
PciRom: 0x0000000000000000
CpuRom: 0x0000000000000000
RomSize: 0
============= pci_dev_info ============= /* end. */
Attaching mount point /dev/csp/memory/0
Attaching mount point /dev/csp/io/1
Attaching mount point /dev/csp/memory/2
Attaching mount point /dev/csp/memory/3
Attaching mount point /dev/csp/memory/4
Attaching mount point /dev/csp/memory/5

Thanks,
John O’Grady

Anyone experiencing problems with “pci-sandpoint”?

Re-cap of the problem:

I have a resource manager that was written to interface to a PCI card. The
resource manager works fine on an x86 plattform but when it is started on
a PPC (sandpoint) the resource manager fails to map the PCI physical
memory properly. (actually the resource manager code is fine)

New Discovery:

The problem seems to be a conflict in the programming of the address decode
registers that reside in the PCI configuration header. According to the PCI
System Architecture guide that I have, all Base Address values must
“… occupy mutually-exclusive address ranges”. Using the function
“pci_read_config()” I have confirmed that these registers have not been
programmed correctly by the O.S.

How are these registers programmed? Is it the responsibility of
“pci-sandpoint”?

While “pci-sandpoint” loads, it reports “Range check failed…” for each
memory/IO block of every PCI card installed in the system. Is this normal?
The only other installed PCI device, a network card, seems to work fine.

The decode registers Base Address 0, 2 and 3 are not mutually-exclusive on
the PPC. Thus the failure to map/access the PCI memory correctly.

PPC
0xF0000000 0x00BFFE01 0xF0000000 0xF0000000
^Base 0 ^Base 2 ^Base 3

vs. x86
0xF4800000 0x0000B401 0xF4000000 0xF3800000
^Base 0 ^Base 2 ^Base 3

No one else is having this problem??? … help.

Thanks,

John.


John O’Grady
Focus Automation Systems Inc.