Can't seem to Memory Map devices on the ISA bus


I’m trying to write a driver that will talk over the ISA bus to a device (an IP carrier and some IPs). Right now I have a very simple program that tries to read identifying information from one of the IP modules, just to check if it works. So far, I can’t seem to get any data back. I’m using QNX 6.1.0 and an x86 Single Board Computer.

Some relevant code snippets:

#define ADDRESS 0x1C0000
// Address > 1 megabyte
#define TOT_BYTES 0x3FFF
#define INTR 9

volatile char * base_addr;

ThreadCtl(_NTO_TCTL_IO, 0);

if(base_addr == MAP_FAILED) {
printf(“Couldn’t map ISA carrier board\n”);
return -1;

// Identifying information resides at base address+0x80 to 0x90
for(i = 0x80; i < 0x90; i+=1) {
Total = (char *)((long int)i+(long int)base_addr);
ID_info = *(Total); // in8(MSB_ret);
printf(“ID_info: 0x%x, Total: 0x%x, %d\n”, ID_info, Total, i );

// end code snippets

I don’t get a MAP_FAILED error, but as far as I can tell, nothing is getting sent over the ISA bus successfully. (at worst, an LED should be blinking during transmission even if nothing else is)

I’m fairly new to writing driver code, so any help/advice/debug strategies people could tell me about would be most appreciated!

I assume you are running this as root? You should always check the return code from ThreadCtl(). How big is the boot image you are using? Since you are forcing BELOW16M, it is possible that the first 16M of phyiscal memory are taken and so your request cannot be serviced.

That’s a weird address for an ISA based card. On standard PC this is usually taken up by RAM

A few pointers here (although probably not related). Don’t do math with pointer it’s very error prone. Because of commented in8, I’m assuming Total is a pointer to char, you could rewrite the loop like this

 for( i = 0x80; i< 0x90; i++ ) {
      ID_info = base_addr[i];
      printf("ID_info: 0x%x, Total: 0x%x,  %d\n", ID_info, &base_addr[i], i );

Mucho easier on the eyes IMHO;-). You declared base_addr volatile, that"s good, but all the math you did on base_addr made it useless. It only makes sense if you use base_addr as a pointer to access the memory location directly. Hopefully Total was declared volatile as well.

MAP_BELOW16 is useless here because you are mapping an existing memory location. That flags makes sense if you are asking mmap for a block of memory (just like a malloc) but need the block to be physicaly located below 16M to allow it to be DMAable by ISA devices. You are specifying the address yourself, so no need for that.

Any chance the board is PnP and needs to be “enabled” before it is really visible to the system?

Thanks for all your help, I’ll try to respond to all your questions:

cdm -
I am running as root, and now checking the ThreadCtl return value - no problem there. The boot image (.ifs file?) is 600k. I don’t think the BELOW16M flag is a problem - I took it out in any case.

The address is set by jumpers on the ISA card - it can be any value from 0 to 2^24 (16M). Maybe I’m confusing this address with the physical address that the CPU sees it at? You mention this space is usually used by RAM - do you know where the ISA bus usually resides?

Thanks for the pointers on pointers - I’m still learning this stuff, so some of the more obvious things slip past me. Total was also declared as volatile.

The board is definitely not PnP (I wish…:slight_smile:)

Thanks again!

The issue is not the bus per se, but rather you are trying to place system ram and your board’s shared memory at the same address. You will probably end up using a range in the 0xd000 or 0xdc00 ranges (I think - it has been a long time since I tried to manually place shared ram in low memory).

Not necessarily since QNX is not a PnP OS. You would have to manually manage it (the source for the isapnp util works). Not as nice as you could want, but do-able.


The ISA bus doesn’t sit an any perticular address, it’s actually more of an extention of the CPU address range. ISA adresse bus is 24 bit wide, which when invented seems plenty, hence some device like yours (i’m guesing it’s old) provide the ability to map anywere. When most PC only had 640k of ram that was great (doesn’t 640K ring a bell :wink: ). PC designers put non ram stuff (like video ram and such) just above 640k. Then when more ram was added later it was added at 1Meg. That left a “hole” between 640k (A0000) and 1M (100000) were memory based device and BIOS extension could live. A0000-BFFFF is usually taken by video ram. That leaves C0000 - FFFFF free (given there is no other device taking that space).

I have never heard of a card allowing any adress range (0-FFFFFF) I only make sense on very old PC with less the 1M of ram or on some very funky custom designed PC.

The address that you set the card at is the address as seen by the CPU.

The ISA bus is mapped to the first 16MB of address space but I suspect that only the first 1 MB is partitioned exclusively for ISA functions. And the first 640 KB of that was RAM.

I’d think that where ever you locate your card in the lower 16 MB of space it will appear there superceeding the main memory. As long as your software is using the same addresses then it should work.

One concern is telling the OS not to use that space as main memory, the BIOS can often be configured to reserve a block of address space. Whether QNX listens to that or not I have no idea.

Your current location of 1.75 MB seems ok but since it’s only a 16 KB device you might want to try in the 0x0d0000 - 0x0dffff range first just to be on the safe side. This area is often unused unless you have a bunch of bios/boot ROMs.

Note: All addresses mentioned above are physical.

No it will create a conflict.

Not really , BIOS will reserve the address space of plug and play devices (that’s special BIOSes). Most BIOS will allow you to turn caching off for area between (C0000-FFFFFF)

No it’s not 1.7m is 0x1A0000, that is were RAM is. I wouldn’t be surprise if modern chip set won’t allow this address range on the ISA bus as they know there is physical ram living at that same address.

I just used the 0x0D0000 memory address and it works! The hardware I’m using is fairly old - I think the IP carrier card is from 1993, so perhaps their instructions for selecting the address are out of date…

Thanks for all your help!