5.2 driver development - memory mapped PCI
From: John Jarvis (jj_at_altsoftware.com)
Date: 12/29/03
- Next message: Benjamin Gawert: "Re: RS6000 /320 vs /390"
- Previous message: Gereon Wenzel: "Re: RS6000 /320 vs /390"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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
- Next message: Benjamin Gawert: "Re: RS6000 /320 vs /390"
- Previous message: Gereon Wenzel: "Re: RS6000 /320 vs /390"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|