[comp.sys.ibm.pc] Need Help with ROM/empty address distinction

jal@ee.rochester.edu (John Lefor) (01/16/90)

I am trying to write a program which can tell me what is going at
at various memory locations.  I am trying to distinguish between 
RAM,  ROM and nothing at all addresses.  Now I have no problem
distinguishing between RAM and ROM,  but how do I distinguish between
ROM and nothing.  In my experiments nothing sometimes is read as the
same hex data and other times the data changes between reads.

ANy suggestions would be much appreciated.

Thanks.



- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

I program ... therefore I am.

John Lefor    	University of Rochester		Dept of E. Engineering
716-275-8265	jal@ee.rochester.edu		uunet!ur-valhalla!jal

emmo@moncam.co.uk (Dave Emmerson) (01/16/90)

In article <1990Jan15.162053.14109@ee.rochester.edu>, jal@ee.rochester.edu (John Lefor) writes:
> [deleted] but how do I distinguish between
> ROM and nothing.  In my experiments nothing sometimes is read as the
> same hex data and other times the data changes between reads.

The problem is that empty memory is just that, you could literally read
*any* valid bit pattern from *any* empty adrress *any* number of times
on many systems.
What you need is a method to force empty locations to a known state. The
simplest, cheapest and safest method (which *should* be standard practice
on any well-designed system) is to put a 10K ohm pull-up resistor on each
data bus line. If your motherboard has an empty ROM socket (2 if it's an AT)
it's an ideal place to fit them. All unused locations then show up as hex
'FF'.
I won't go into detail, I suspect you want your software to work on any
machine without modification. To do that, write known pseudo-random data
to a small-ish area (16-256 bytes), read back and compare the results,
and *store them too*. If it doesn't match, either it's not RAM, or something
is overwriting it (an interrupt routine etc..), or it's empty. Now read it
back again (a few times if necessary), this time comparing with the first
readback. If it fails to re-match it's most likely empty, otherwise, unless
it's all HEX FF's it's almost certainly ROM (probably, but not necessarily,
a valid BIOS ROM).
On other machines, I have found it worthwhile using different opcodes
for the second and third passes, it seems like the data bus had enough
capacitance to retain the last valid data for several uSec, so it
always seemed to read the exact same data ( the last byte/word of the
read instruction ). If you're using a high level language, this might
be difficult. I haven't gotten my hands that dirty with a PC yet, so
I can't offer any further suggestions.

Hope that helps,

Dave E.

pipkins@qmsseq.imagen.com (Jeff Pipkins) (01/17/90)

In article <1990Jan15.162053.14109@ee.rochester.edu> jal@ee.rochester.edu writes:
>I am trying to write a program which can tell me what is going at
>at various memory locations.  I am trying to distinguish between 
>RAM,  ROM and nothing at all addresses.  Now I have no problem
>distinguishing between RAM and ROM,  but how do I distinguish between
>ROM and nothing.  In my experiments nothing sometimes is read as the
>same hex data and other times the data changes between reads.

The following code is an excerpt from a program similar to the one you
describe.  It works because of a convention set forth in the IBM AT Tech
Ref. Manual that says what add-on rom modules must look like in order
to be recognized by the BIOS.  Because add-on rom is only allowed from
C800:0000 to E000:0000, the following statement is used to call the
check_rom() function:

   puts("\nChecking for added ROM from C8000 to E0000...");
   check_rom((addr) 0xC0008000, (addr) 0xE0000000);

Here is the code for check_rom(), along with a function that it needs:

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                                                                           *
 *   This routine checks for optional ROM code from "address" to "limit"     *
 *                                                                           *
 *   Each 2K block from "address" up to "limit" has the potential to contain *
 *   ROM.  If ROM is present, the first word will be AA55 and the next byte  *
 *   will contain the number of 512 byte blocks.                             *
 *                                                                           *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

void check_rom(address, limit)
   unsigned int huge *address;
   unsigned int huge *limit;

{
   unsigned int blocks;

   while (address < limit) {
      if (*address == 0xAA55) {
         blocks = *(address+1) & 0x00FF;
         printf("   %lX: %uK bytes.\n", adr8086(address), blocks>>1);
         address += (blocks * 512)/2;
      }else {
         address += 2048/2;
      }
   }
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                                                                           *
 *   This function takes as input a 32-bit long and returns another 32-bit   *
 *   long that is the screwed-up 8086 address version.  In other words,      *
 *   the high word is shifted left 4 bits and then added to the low word     *
 *   to produce a 20-bit address.                                            *
 *                                                                           *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

unsigned long adr8086( adr)
   unsigned long adr;

{
   return( ((adr>>12)&0x000FFFF0L) + (adr&0x0000FFFFL) );
}

Any opinions expressed here (including the expression "screwed-up") are
my own, and not necessarily shared by my employer.  So there.

johne@hpvcfs1.HP.COM (John Eaton) (01/18/90)

<<<
>  but how do I distinguish between
>ROM and nothing.  In my experiments nothing sometimes is read as the
>same hex data and other times the data changes between reads.
----------
Bus capacitance can be a big problem when trying to identify non-existant
memory since you normally will read the last valid data on the buss. I 
once did a PC-compatible design using an 8086 that had several problems
with this. It would randomly fail its POST by jumping into nonexistant
ROM space. I traced it and found that it was reading a rom location to
see if it was AA55. The code was such that when executed on a 8086 that the
cycle before the read was a prefetch of the AA55 that the read was to be
compared with. It passed! It then did a checksum on the "Rom" by adding
all of its bytes to see if they sum to 00. This was done in a loop so that
the value read was always the same value that was in the loop before the 
read. Since rom sizes were always a multiple of 256 bytes the sum always
came out to 00.

Many applications that search for memory rely on the program cycle accesses
to trash the buss between the time they write something and read it back.
We had seperated the 8 bit buss from the 16 bit cpu buss so that you could
write a byte to the 8 bit buss and it would still be there the next time
you did a 8 bit read. A lot of applications would think they found memory
or I/O cards until we added circuitry to trash the buss between accesses.
There are quite a few applications that search for the presence of a plug
in card on the PC buss that really don't work in theory but work enough
of the time that nobody notices.


John Eaton
!hpvcfs1!johne