?? memory.c
字號:
/*
memory.c
memory-related library functions.
Note on "physical" versions of functions...
Non-"physical" versions can be used by machines that return
pointer values that match actual addresses, such as
I960 and Motorola. Other systems (i.e. PC) must use
"physical" versions. Actually, any system may use
the "physical" version since it uses function calls for
doing read/write.
*/
#include <stdtypes.h>
#include <string.h>
#include <stdio.h>
/* non-standard includes... */
#include <clib1.h>
#include <lib.h>
extern CHAR errstring[], text[];
/* **************************************************** */
/* local function protos... */
/* **************************************************** */
static int adderr( UINT32 sb, UINT32 ws );
int address_test( UINT32 address, UINT32 size_bytes )
/*
Test addressing of memory.
Entry: address - PCI memory address to use as start ( must be 4-byte aligned )
"address" must be a multiple of "size_bytes", unless size_bytes is not a
power-of-two (in which case "address" must be a multiple of the next
power-of-two larger than "size_bytes").
size_bytes - size in bytes to test
Return: TRUE if OK, else FALSE and error string added.
*/
{
UINT32 size, i, data, tsize = size_bytes;
/* get size as a power-of-two based on highest bit set... */
for( size = 0; tsize; tsize = tsize >> 1 )
{
if ( size == 0L ) size = 1;
else size = size << 1;
}
if ( size != size_bytes )
size = size << 1; /* go to next higher power-of-two */
/* see if address is multiple of size... */
if ( (address % size) != 0L)
{
strcat( errstring, "Error calling address_test.\n" );
sprintf( text, "Address %8.8lx is not multiple of size %8.8lx.\n", \
address, size );
strcat( errstring, text );
sprintf( text, "Requested test size is %8.8lx.\n", size_bytes );
strcat( errstring, text );
return( FALSE );
}
size /= 2; /* size halfway thru is the last location written */
/* write unique data to each unique address... */
*(UINT32 *)address = 0; /* write unique data location 0 */
for( i = 4; i <= size; i = i << 1 )
*(UINT32 *)(address + i) = i; /* write unique data */
/* read back and compare unique data... */
data = *(UINT32 *)address;
if ( data != 0L )
return( adderr( 0L, data ) );
for( i = 4; i <= size; i = i << 1 )
{
data = *(UINT32 *)(address + i);
if ( data != i )
return( adderr( i, data ) );
}
return( TRUE );
}
int physical_address_test( UINT32 address, UINT32 size_bytes )
/*
Same as address_test, but must be used by PCs.
*/
{
UINT32 size, i, data, tsize = size_bytes;
/* get size as a power-of-two based on highest bit set... */
for( size = 0; tsize; tsize = tsize >> 1 )
{
if ( size == 0L ) size = 1;
else size = size << 1;
}
if ( size != size_bytes )
size = size << 1; /* go to next higher power-of-two */
/* see if address is multiple of size... */
if ( (address % size) != 0L)
{
strcat( errstring, "Error calling address_test.\n" );
sprintf( text, "Address %8.8lx is not multiple of size %8.8lx.\n", \
address, size );
strcat( errstring, text );
sprintf( text, "Requested test size is %8.8lx.\n", size_bytes );
strcat( errstring, text );
return( FALSE );
}
size /= 2; /* size halfway thru is the last location written */
/* write unique data to each unique address... */
xpoke32( address, 0L ); /* write unique data location 0 */
for( i = 4; i <= size; i = i << 1 )
xpoke32( address + i, i ); /* write unique data */
/* read back and compare unique data... */
data = xpeek32( address );
if ( data != 0L )
return( adderr( 0L, data ) );
for( i = 4; i <= size; i = i << 1 )
{
data = xpeek32(address + i);
if ( data != i )
return( adderr( i, data ) );
}
return( TRUE );
}
static int adderr( UINT32 sb, UINT32 ws )
/* Stuff error text.
Entry: sb - both the offset into the memory and the data expected
ws - what was actually read
*/
{
strcat( errstring, "Address test error.\n" );
return( sb_ws32( sb, sb, ws ) );
}
int data_test( UINT32 address, UINT32 size_bytes, UINT32 *data, int num_data )
/*
Test complete block of data in memory using passed values.
Tests using using long-word accesses.
Limited to 24-bit addresses.
Entry: address - PCI memory address to use as start ( must be 4-byte aligned )
size_bytes - size in bytes
data - array of data values to use
data is { value, incrementor } for each entry
num_data - how many elements in array "data"
Return: TRUE if OK, else FALSE and error string added.
*/
{
UINT32 sbdata, wsdata;
UINT32 *p32 = (UINT32 *)(voidaddr(address));
UINT16 i, j;
for( j = 0; j < num_data*2; j+=2 )
{
// write all data...
sbdata = data[j];
for( i = 0; i < (UINT16)(size_bytes/4); i ++ )
{
p32[i] = sbdata;
sbdata += data[j+1];
}
// read back and compare...
sbdata = data[j];
for( i = 0; i < (UINT16)(size_bytes/4); i++ )
{
wsdata = p32[i];
if ( sbdata != wsdata )
return( data_err32( "data_test() error.\n", i*4L, sbdata, wsdata ) );
sbdata += data[j+1];
}
}
return( TRUE );
}
int physical_data_test( UINT32 address, UINT32 size_bytes, UINT32 *data, int num_data )
/*
Same as data_test, but uses full 32-bit addresses.
*/
{
UINT32 i, sbdata, wsdata;
int j;
for( j = 0; j < num_data; j++ )
{
// write...
sbdata = data[j];
for( i = 0; i < size_bytes; i += 4 )
{
xpoke32( address + i, sbdata );
sbdata += data[j+1];
}
// read back and compare...
sbdata = data[j];
for( i = 0; i < size_bytes; i += 4 )
{
wsdata = xpeek32( address + i );
if ( sbdata != wsdata )
return( data_err32( "data_test() error.\n", i*4L, sbdata, wsdata ) );
sbdata += data[j+1];
}
}
return( TRUE );
}
int bus_sizing( UINT32 address )
/*
Test byte/word/long accesses at all offset 0-3.
Note:
Since this type of access is dependent on the CPU subsystem, and not
the PCI subsystem, the unaligned offsets are not tested.
Uses two longword locations at "address".
Entry: address - PCI memory address to use as start ( must be 4-byte aligned )
Return: TRUE if OK, else FALSE and error string added.
*/
{
UINT32 data, tdata;
/* **************************** */
/* test simple byte accesses... */
/* **************************** */
*(UINT32 *)address = 0x11223344L;
*(UINT32 *)(address + 4) = 0L; /* used to check for overwrite */
*(UINT8 *)address = 0xFF;
tdata = 0x112233FFL;
data = *(UINT32 *)address;
if ( data != tdata )
return( simbyte( 0, tdata, data ) );
*(UINT8 *)(address + 1) = 0xFE;
tdata = 0x1122FEFFL;
data = *(UINT32 *)address;
if ( data != tdata )
return( simbyte( 1, tdata, data ) );
*(UINT8 *)(address + 2) = 0xFD;
tdata = 0x11FDFEFFL;
data = *(UINT32 *)address;
if ( data != tdata )
return( simbyte( 2, tdata, data ) );
*(UINT8 *)(address + 3) = 0xFC;
tdata = 0xFCFDFEFFL;
data = *(UINT32 *)address;
if ( data != tdata )
return( simbyte( 3, tdata, data ) );
/* **************************** */
/* test simple word accesses... */
/* **************************** */
*(UINT32 *)address = 0x11223344L;
*(UINT16 *)address = 0xFFFE;
tdata = 0x1122FFFEL;
data = *(UINT32 *)address;
if ( data != tdata )
return( simword( 0, tdata, data ) );
*(UINT16 *)(address + 2) = 0xFDFC;
tdata = 0xFDFCFFFEL;
data = *(UINT32 *)address;
if ( data != tdata )
return( simword( 2, tdata, data ) );
/* check for overwrite past the long... */
data = *(UINT32 *)(address + 4);
if ( data != 0L )
{
strcat( errstring, "Offset 4 overwritten during simple byte/word test.\n" );
return( dynfail() );
}
return(TRUE);
}
int physical_bus_sizing( UINT32 address )
/*
Sma eas bus_sizing but uses physical address so can do 32-bit addressing.
Test byte/word/long accesses at all offset 0-3.
Note:
Since this type of access is dependent on the CPU subsystem, and not
the PCI subsystem, the unaligned offsets are not tested.
Uses two longword locations at "address".
Entry: address - PCI memory address to use as start ( must be 4-byte aligned )
Return: TRUE if OK, else FALSE and error string added.
*/
{
UINT32 data, tdata;
/* **************************** */
/* test simple byte accesses... */
/* **************************** */
xpoke32( address, 0x11223344L );
xpoke32( address + 4, 0L ); /* used to check for overwrite */
xpoke8( address, 0xFF );
tdata = 0x112233FFL;
data = xpeek32( address );
if ( data != tdata )
return( simbyte( 0, tdata, data ) );
xpoke8( address + 1, 0xFE );
tdata = 0x1122FEFFL;
data = xpeek32( address );
if ( data != tdata )
return( simbyte( 1, tdata, data ) );
xpoke8( address + 2, 0xFD );
tdata = 0x11FDFEFFL;
data = xpeek32( address );
if ( data != tdata )
return( simbyte( 2, tdata, data ) );
xpoke8( address + 3, 0xFC );
tdata = 0xFCFDFEFFL;
data = xpeek32( address );
if ( data != tdata )
return( simbyte( 3, tdata, data ) );
/* **************************** */
/* test simple word accesses... */
/* **************************** */
xpoke32( address, 0x11223344L );
xpoke16( address, 0xFFFE );
tdata = 0x1122FFFEL;
data = xpeek32( address );
if ( data != tdata )
return( simword( 0, tdata, data ) );
xpoke16( address + 2, 0xFDFC );
tdata = 0xFDFCFFFEL;
data = xpeek32( address );
if ( data != tdata )
return( simword( 2, tdata, data ) );
/* check for overwrite past the long... */
data = xpeek32( address + 4);
if ( data != 0L )
{
strcat( errstring, "Offset 4 overwritten during simple byte/word test.\n" );
return( dynfail() );
}
return(TRUE);
}
int simbyte( int offset, UINT32 sb, UINT32 ws )
/*
Entry: offset - byte offset that failed 0-3
sb - "should be" data
ws - "was" data
Return: thru dynafail
*/
{
data_err32( "Failed simple byte access.\n", (UINT32)offset, sb, ws );
return( dynfail() );
}
int simword( int offset, UINT32 sb, UINT32 ws )
/*
Entry: offset - offset that failed 0-3
sb - "should be" data
ws - "was" data
Return: thru dynafail
*/
{
data_err32( "Failed simple word access.\n", (UINT32)offset, sb, ws );
return( dynfail() );
}
int dynfail( VOID )
{
strcat( errstring, "Dynamic Bus Sizing Test failed.\n" );
return( FALSE );
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -