Jump to content

Help with IOMemoryMap


  • Please log in to reply
8 replies to this topic

#1
PoisonDrop

PoisonDrop

    InsanelyMac Protégé

  • Members
  • Pip
  • 8 posts
Here is what I would like to do:

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...

#2
dong

dong

    InsanelyMac Sage

  • Retired Developers
  • 366 posts
  • Gender:Male
Instead of using:
printf("Result 2: 0x%02x", PCIRegisters->Reg1); /* Result 2: 0x00 */
}
what you want to do is actually:
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.

#3
PoisonDrop

PoisonDrop

    InsanelyMac Protégé

  • Members
  • Pip
  • 8 posts
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:

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

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).

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.

#4
dong

dong

    InsanelyMac Sage

  • Retired Developers
  • 366 posts
  • Gender:Male

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?

#5
PoisonDrop

PoisonDrop

    InsanelyMac Protégé

  • Members
  • Pip
  • 8 posts
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?

#6
mercurysquad2

mercurysquad2

    InsanelyMac Protégé

  • Members
  • Pip
  • 20 posts
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:

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

And it should work then.

#7
PoisonDrop

PoisonDrop

    InsanelyMac Protégé

  • Members
  • Pip
  • 8 posts
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!

#8
mercurysquad2

mercurysquad2

    InsanelyMac Protégé

  • Members
  • Pip
  • 20 posts

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!)

#9
PoisonDrop

PoisonDrop

    InsanelyMac Protégé

  • Members
  • Pip
  • 8 posts
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!





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

© 2014 InsanelyMac  |   News  |   Forum  |   Downloads  |   OSx86 Wiki  |   Mac Netbook  |   PHP hosting by CatN  |   Designed by Ed Gain  |   Logo by irfan  |   Privacy Policy