Just as a clarification for the two options I mentioned:
Option 1 would be the same as the kernel believing there truly was only 1.6GiB of RAM in the system. In other words, if the kernel received a request for an address beyond that range, it might error out saying "No such address"
Option 2 is different. The kernel
knows 2GiB exists, but that the kernel is allowed to use only 1.6GiB. In this case, if the kernel sees an address beyond 1.6GiB, it may not report an error (because it knows the address
will decode to physical RAM).
To your question... My experience is limited. I did some embedded development/testing at my last job. We had a system-on-chip design with multiple programmable sub-devices on the chip. Our on-chip memory map was static. So any cycles we initiated within the chip itself were deterministic.
For our system-level tests, we had PCI expansion boards with our prototype chip built on. We had the host computer run some rudimentary firmware to program up the device through PCI registers. Then, we could initiate reads and writes from within the host, out through the PCI expansion bus, and finally inside the chip.
So first, I don't know how you're planning to connect this device to the machine. I assume PCI since that's what you mentioned earlier. If that is the case, then yeah, you'll need to read and write the device's PCI registers to find out where the computer memory-mapped the device. As I recall, the PCI standard specifies a minimum register set that all PCI-compatible devices must follow. Any given device may have more programmable registers than the minimum, but if you don't have any documentation, then those extra registers don't do you a bit of good (even if the device implements them, because you don't know where they are or what they do).
So, first, get the PCI spec that matches the hardware you have. You can download the spec. from:
http://www.pcisig.com/specifications/conventional
Older specs look to be available for free, but the current ones have to be purchased. Then, with the spec. in hand, query the PCI devices attached to the system (perhaps with lspci). Then perform some reads and writes to the configuration registers detailed in the PCI spec.
That should give you the memory range the device is mapped to. From that point, you can start reading writing all you want.
Though, I've never read/written to /dev/mem directly. I stay within user space. To perform reads and writes to memory-mapped devices, use mmap() along with /dev/mem. For instance, something like this maybe:
Code:
volatile void *device_base_address;
int fd;
int status_register;
...
fd = open( "/dev/mem", O_RDWR );
device_base_address = mmap( 0,
DEVICE_WINDOW_SIZE,
PROT_READ | PROT_WRITE,
MAP_PRIVATE,
fd,
DEVICE_MAPPED_ADDRESS );
status_register = *(int *)(device_base_register + status_register_offset );
...
*(int *)(device_base_regiser + status_register_offset) = 0x001F0300;
The text in blue would need to be replaced with the memory window (in bytes) and the memory-mapped address you read from the PCI registers.
The last bit of code just shows a read and a write to a fictitious status register. At least, that's how we did things.
Here's a page that may be of some interest:
http://www.linuxjournal.com/node/5442/print
At the very least, it might help you find other interesting approaches.