Help - Search - Members - Calendar
Full Version: Help with IOMemoryMap
InsanelyMac Forum > Apple World > Mac Programming and Development
PoisonDrop
Here is what I would like to do:

CODE
struct PCIRegisterType {
     UInt32 Reg1;
     UInt32 Reg2;
     ...
}

int main ()
{
     IOMemoryMap *PCIMemoryMap;
     PCIRegisterType *PCIRegisters;

     ...

     PCIMemoryMap = Device->getDeviceMapWithRegister(kIOPCIConfigBaseAddress0);
     PCIRegisters = (PCIRegisterType *)PCIMemoryMap->getVirtualAddress();

     printf("Result 1: 0x%02x", Device->ioRead8(0x00, PCIMemoryMap)); /* Result 1: 0xfe */
     printf("Result 2: 0x%02x", PCIRegisters->Reg1); /* Result 2: 0x00 */

     ...
}


This compiles and runs fine. Everything except the printf lines were taken from Apple's documentation on the IOMemoryMap class. When I use the memory map to ioRead32(0x00, PCIMemoryMap) I get the correct value from the register. But when I try to read the register using PCIRegisters->Reg1 (or Reg2, etc...) all I get is a value of 0x00. The output of both printf lines should be the same because, according to what I would LIKE to happen, both statements should be reading the same address in memory. This, though, does not seem to be true. The memory mapping seems fine, but I can't use a struct pointer to access the mapped memory? Apple's documentation seems to let on that this is possible, but maybe I am just not getting it.

Any help would greatly be appreciated, as I've been working on this for days...
dong
Instead of using:
CODE
     printf("Result 2: 0x%02x", PCIRegisters->Reg1); /* Result 2: 0x00 */
}
what you want to do is actually:
CODE
     printf("Result 2: 0x%02x", *(volatile UInt8 *) (PCIRegisters + Reg1));
}

You may need to make sure you are familiar with c/c++ pointer before this. I don't see how the PCIRegisterType struct will work as you expect.
PoisonDrop
Actually I am very familiar with pointers. PCIRegisters is a pointer to an address in memory. This address in memory should be the PCI card's memory mapped registers. At the address the pointer PCIRegisters references is data that has a structure of type PCIRegisterType. Therefore I should be able to access it like any other structure pointer:

CODE
StructureName->Variable // to access the value of Variable


Your code refers to Reg1 as if it is a seperate variable whose value is an offset of PCIRegisters. In my program, Reg1 is a member variable of the PCIRegisterType structure. Maybe it is structures that I need to better understand?

Well either way, I tried your code anyway and got

CODE
error: Reg1 not declared in this scope


which was as expected. But thanks anyway!

So can anyone else share what needs to be done? To reiterate, I need to access a block of mapped memory. I would like to do so using a structure, or a class would be ok (in my opinion a class would be overkill, no functions).

CODE
PCIRegisters->Reg1 = 0x00;


This is how I would like to access this block of memory. I know at this point it soulds like a dumb question, but I'm really stuck here. My pointer method (above) does not work for some reason.
dong
QUOTE (PoisonDrop @ Aug 2 2009, 11:00 AM) *
Ok, I now get what you mean. Yes, I did not read clearly. So even IORead32(0x00, memMap) do not give the same value as PCIRegisters->Reg1? Will that be something related to system endianess?
PoisonDrop
IORead32 gives 0x000000fe (the correct value). I just don't want to do all those read writes or have to have all those extra variables to operate on. Apple makes it sound like the OS takes care of endianess, either way, if that was the issue, it would at least read SOMETHING other than 0x00000000.

Apple makes it sound so simple. It should be like mapping 2 pointers to the same address. PCIRegisters will point to the same address space as the PCI IO address space. At least that's what I thought an IOMemoryMap was for. Any suggestions?
mercurysquad2
Check the return type of ->getVirtualAddress(). It doesn't return a pointer, it returns the address as a value. You have to force-cast it as a pointer.

Try replacing that line with this:

CODE
PCIRegisters = reinterpret_cast<PCIRegisterType*> (PCIMemoryMap->getVirtualAddress());


And it should work then.
PoisonDrop
OMG thank you! I actually get a value other than 0x00 with that code! That's amazing (sorry, I've been so frustrated that I'm amused by the simplest things). OK, so your code reads my test register as 0x73. But ioRead reads the same register as 0xef. Would THAT be an endianess problem? If so at least I get something. And endianess is an easy fix. Thanks again!
mercurysquad2
QUOTE (PoisonDrop @ Aug 4 2009, 06:26 PM) *
OMG thank you! I actually get a value other than 0x00 with that code! That's amazing (sorry, I've been so frustrated that I'm amused by the simplest things). OK, so your code reads my test register as 0x73. But ioRead reads the same register as 0xef. Would THAT be an endianess problem? If so at least I get something. And endianess is an easy fix. Thanks again!


There are some things with which you have to be very careful when you are doing I/O using structures. For example, in your ioRead, you call ioRead8 to read only one byte, but your struct has Reg1 mapped to a uint32 = 4 bytes. Secondly, make sure you add __attribute__((__packed__)); at the end of your struct so that the individual fields do not get padded or aligned. In general you must now make sure your register struct layout is exactly the same as the underlying hardware. Just play around with that and after a while it will begin to give expected results. (calculating the struct's field layout based on register addresses is kinda tricky!)
PoisonDrop
Yeah, my structure in my code above was from Apple's example. I used it just for speed, because my structure is VERY long...it would have polluted my message. The actual data I'm trying to read is 1 byte long, as my structure defines.

Actually, I have figured out my problem. I will clarify in case anyone else runs into this issue.

My original code was actually correct, and was actually working. The problem was the device I was trying to work with doesn't support memory mapped i/o (read the data sheet and figured that out). I tried this operation (using the code from my first post) on a different device that I know supported memory mapped i/o and it worked.

So the Apple example of IOMemoryMap was correct, and this was all for nothing. Although I'm extremely disappointed, at least now I know.

Thank you again to all for your help!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.