mmap_device_memory - what am I doing wrong

I have a question related to the mmap_device_memory() call.

We have QNX 6.3 installed on a std32 bus backplane architecture where I am attempting to port over some old legacy code from 10+ years ago into modern QNX.

I have the code ported and running and am now attempting to talk to the hardware plugged into the backplane and I’m having some problems.

The config files for DOS were writing to address’s 0x200 for one of the cards. So I attempted to use mmap_device_memory and plug in address 0x200 for my address. The call mapped without errors but reads/writes to the card don’t seem to be doing anything at all.

So I got out the old manuals on the Ziatech CPU card (the actual processor card QNX is running on) that sits on the backplane. There is an LED on this card than can be turned on and off by software according to the manual by turningon bit 2 at address 0x79. The original DOS code does indeed turn this LED on to indicate the system is running and it works.

So I wrote the following test program in QNX to turn on the LED.

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <fcntl.h>
#include <errno.h>
#include <sys/io.h>
#include <sys/mman.h>

using namespace std;

void testLed()
{
    uint64_t addr64 = 0x79;   // LED address
    char *ptr;
    char ledVal;

    ptr = (char*)mmap_device_memory((void*)0, 1, PROT_NOCACHE | PROT_READ | PROT_WRITE, MAP_TYPE, addr64);

    if (ptr == MAP_FAILED)
    {
        printf("Failed to map device memory thanks to error %s\n", strerror(errno);
        return;
    }
	
    printf("Memory mapped address 0x79 of size 1 to address of %p.\n", ptr);

    ledVal = (char)*ptr;
    printf("Read in led value of <%d>!\n", (int)ledVal);

    ledVal = ledVal | 0x04;   // Bit to turn on LED

    *ptr = (char)ledVal;
    printf("In theory we turned on the LED with value <%d>!\n", (int)ledVal);
}

int main()
{
    testLed();
	
    return 0;
}

I compiled and ran this and it runs to completion but never turns on the LED.

What is prints out is that is maps address 0x79 to some large number in my process space.

Then it reads the led value as being -17 (which makes no sense because this would mean bit 2 was already on meaning the LED would be on and it’s not)

Then writes out the change to the led value and still reports a value of -17 and exits.

So my question is what am I doing wrong? I’ve used mmap_device_memory before successfully but never with std32 bus architecture or a ziatech CPU card.

I’m sure I must have some kind of weird pointer problem in my example that I’m overlooking someplace because writing to address 0x79 on the actual processor card should be a snap. Once I get this working then I’ll go back to trying to map in actual hardware cards on the backplane.

TIA,

Tim

Hello Tim,

the program looks OK to me.
I guess that the 0x200 for the hardware card and 0x79 for the LED are IO space, meaning you have to use mmap_device_io() to map it in and then out8() to write to it, in8() to read from it.

I would probably map 16 bytes starting at address 0x70 to avoid any alignment problem, but in theory you should be able to map 1 byte IO space at an odd location.

Best regards,
Albrecht

Albrecht,

You are correct.

I was exploring mmap_device_io since I posted this and it does indeed do what I want in terms of turning on the LED and writing to the cards on the std32 bus. The only gotcha was figuring out I needed to do a ThreadCtl(_NTO_TCTL_IO, 0) call before it would work.

I am still not sure why mmap_device_memory doesn’t since in theory the 2 calls do roughly the same thing.

Tim

On x86, mmap_device_io() (and the use of inX()/outX()) is totally different with mmap_device_memory() (and directly operate the memroy).