5.2 driver development - memory mapped PCI

From: John Jarvis (jj_at_altsoftware.com)
Date: 12/29/03


Date: 29 Dec 2003 08:49:43 -0800

Hi,

I'm developing an AIX 5.2 driver for a PCI card and I'm having trouble
accessing/mapping memory mapped PCI space on the card. Here is what
I'm doing, including a few code snipets. The system is big endian,
the card is PCI-X. 'PCI_Dev.dds' is the DDS structure. PCI_Dev is a
structure of type my_pci_dev.

There are two memory spaces on the card I need access to. The first
is referenced by BAR0, the second by BAR1. I'm reading BAR0/1 with
the following piece of code.

   MACH_DD_IO md;

   . . .

/* read BAR0 */
    md.md_size = 2; // BAR value is two words under PCI-X
    md.md_incr = MV_WORD;
    md.md_data = (char *)&md_word;
    md.md_addr = 0x10;
    if (retval = pci_cfgrw(BID_VAL(IO_PCI,PCI_IOMEM,PCI_Dev.dds.busid),&md,READ))
    {
      return (retval);
    }
    PCI_Dev.dds.bar0 = SWAP_LONG(md_word);

This is done for both BAR0 and BAR1, giving me the following values:
    BAR0 - 0xC1010000
    BAR1 - 0xC0000000

On a side note, I've verified the device's Vendor ID and Device ID by
reading the PCI configuration space as well, and I am on the propper
device.

Both spaces are to be memory mapped. I initialize the memory mapping
for each with the following snippet.

    /* prepare Registers for mapping (BAR0) */
    PCI_Dev.regsMap.bid = BID_ALTREG(PCI_Dev.dds.busid, PCI_BUSMEM);
    PCI_Dev.regsMap.key = IO_MEM_MAP;
    PCI_Dev.regsMap.flags = IOM_RDONLY & 0;
    PCI_Dev.regsMap.busaddr = PCI_Dev.dds.bar0;
    PCI_Dev.regsMap.size = REGS_SIZE;

    PCI_Dev.regsHandle = io_map_init(&PCI_Dev.regsMap, 0, NULL);

I understand that I am able to tie the two memory spaces together by
specifying the returned handle of the first in the third parameter of
the second call to io_map_init(), but currently I am not doing this.
They are both initialized identically with the above piece of code.
And I have tried this with both flags = 0 and flags = IOM_RDONLY, both
produce equal read results. When the driver is being shut down, a
call as follows is made to clear the mapping.
    io_map_clear(PCI_Dev.regsHandle);

Next I want to read a register from the above space. The function
that does so boils down to this:

extern K_Uint32 read_card_register( struct my_pci_dev* i_pstDev,
                                      K_Int32 i_iRegisterOffset )
{
    volatile char* start_addr = 0;
    long long value;

    /* BAR0 mapping */
    start_addr = (volatile char*)io_map(i_pstDev->regsHandle);
    i_pstDev->m_pvRegsAddress = (void*)(start_addr +
(uintptr_t)(i_pstDev->regsMap.busaddr & OFFSET_MASK));
    if (i_pstDev->m_pvRegsAddress == NULL)
    { return ENOMEM;
    }

    // read the register
    regval = *((K_Uint32*)((K_Uint64)i_pstDev->m_pvRegsAddress +
i_iRegisterOffset));

    // unmap register space
    io_unmap(i_pstDev->m_pvRegsAddress);

    // return
    return regval;
}

I think the only other pieces of info you need about this function is
that m_pvRegsAddress is a void*, which on this architecture is 64-bits
wide, and OFFSET_MASK is 0x0FFF. I am told this is required because
of how memory mapping is handled on a 64-bit kernel.

The problem is that the data I am receiving from a read is garbage.
All I see in this mapping is 0xFFFFFFFF. As well, the value that
io_map is returning to start_addr is 0xFFFFFFFF 00000000, which seems
odd to say the least. And lastly, if I write (a function identical to
the above read, with the exception of regval being on the other side
of the =) it either locks the system, or locks the next time I do a
read (I've seen both).

If anyone has any experience with this and could share some insight I
would really appreciate it. Any information, regardless of whether
it's PCI or PCI-X related is welcome. I've gone through and made sure
no pointer types end up being case through 32-bit values, and that all
seems good. But I'm a little at a loss as to why this is not working,
though none of the above mapping functions are returning a failure.

Thanks in advance,
John



Relevant Pages

  • Re: p5e3 deluxe motherboard and 1333 2GB memory modules.. best bet?
    ... I cant find the module i was going to buy in their memory specs/ ... The 5400 has enough bandwidth to run four video card slots at ... I purchased a PCI video card the ...
    (alt.comp.periphs.mainboard.asus)
  • [PATCH] Cardbus card memory assignment on x86_64 (if base==maxbase)
    ... I've sent the patch below to Ivan Kokshaysky ... I've debugged a memory assignment problem which happens even with 2.6.8.1 ... on Amilo Laptops from Siemens Fujitsu with a RT2500 CardBus card. ... The problem was that the PCI scan didn't report a memory range for the ...
    (Linux-Kernel)
  • Re: "PCI: Cannot Allocate resource ... " when adding graphic card
    ... |>Reuben D. Budiardja wrote: ... I tried changing to PCI as the primary display, ... Have you tried the PCI card without the AGP ... usually memory. ...
    (Fedora)
  • Re: driver: rmalloc, rmallocmap
    ... See the section called 8 Memory Management Via Regions ... Subject: Memory mapping to VMEbus ... Keywords: vme SunOS ... I am modifying a VME device driver for a SPARC 1E card running SunOS 4.1e ...
    (comp.unix.solaris)
  • Re: 5.2 driver development - memory mapped PCI
    ... BUT that segment does NOT begin at the ... > accessing/mapping memory mapped PCI space on the card. ... > There are two memory spaces on the card I need access to. ... > call as follows is made to clear the mapping. ...
    (comp.unix.aix)