ndev_memtest.c 7.25 KB
#include <sys/types.h>
#ifdef __sgi__
#include <sys/sbd.h>
#endif
#include <sys/stat.h>
#include <sys/mman.h>
#ifdef __sgi__
#include <sys/sema.h>
#endif

#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <getopt.h>

#ifdef __sgi_
#include <sys/u64driver.h>
#else
#include <PR/R4300.h>
#endif
#include <sys/u64gio.h>

/*
 * From $ROOT/usr/include/ide, which is installed from $ROOT/PR/diags/include
 */
#include "diag.h"

/*
 * Local definitions
 */
#define GIOBUS_BASE	0x1f400000
#define GIOBUS_SIZE	0x200000	/* 2 MB */

#define U64_MEMTEST_BASE	10

static int gio_memtest(TEST_REF *test_ref);

static int address_long(unsigned int addrmask, unsigned char *mapbase,
		        unsigned char *name);

static int checkerboard_long(unsigned int data, unsigned char *mapbase,
		             unsigned char *name);

static struct u64_board *pBoard;

/*
 * Create an array of tests, each of which corresponds to a separate menu
 * item callable from the master ide menu.
 */
static TEST_REF TestRefs[] = {
    {"GIO memory test", 	U64_MEMTEST_BASE+0, gio_memtest},
    {"",0,0}
};

static char *TestName, *addr, *mask, *count;
static int NumFailures = 0;
static int ShortMsg = 0;
static int DebugLevel = 0;

static int ndev_memtestInit();
static int ndev_memtestDo(TEST_REF *test_ref);

/*
 * diagnostic entry point
 */
int ndev_memtestEntry()
{
    TestName = pGlobalComm->argv[0];

    diaginit(TestRefs, ndev_memtestInit, ndev_memtestDo);

    if (NumFailures) {
        errlog(INFO_END, "... test %s FAILED, %d failures.",
            TestName, NumFailures);
    } else {
	errlog(INFO, "... test %s PASSED", TestName);
    }
}

static int ndev_memtestInit()
{
    char *env;

    errlog(INFO_START, "Starting test %s ... ", TestName);
    NumFailures = 0;

    /*
     * We could do the memory mapping here, but we don't have a convenient way
     * of maintaining the pointer to the memory, other than as a static global.
     *
     * Thus, it's just as easy (and arguably better coding style) to do the 
     * test setup in the body of the test itself.
     */
    return(0);
}

static int ndev_memtestDo(TEST_REF *test_ref)
{
    int rc;

    errlog(DEBUG,
      "%s: starting subtest %s (%d) ...",
      TestName, test_ref->name, test_ref->num);

    /*
     * Invoke the actual test from the "TEST_REF" array statically declared
     * as a global within this test module.
     */
    if (rc = test_ref->fnc(test_ref)) NumFailures++;

    if (rc == 0) {
	errlog(DEBUG, "... PASSED");
    } else {
	errlog(INFO_END, "... FAILED");
    }
    return(NumFailures);
}

/*
 * Return value: number of errors encountered.  "Zero" indicates success.
 */
int
gio_memtest(TEST_REF *test_ref)
{
    int mmemFd;
    unsigned char *mapbase;
    int pageIndex, memIndex;
    int errorCount;
    unsigned int readLong, readLongAddr;
    unsigned short readShort, readShortAddr;

    if ((mmemFd = open("/dev/mmem", 2)) < 0) {
	perror("open of /dev/mmem failed");
	return(1);
    }

    if ((mapbase = (unsigned char *)mmap(0, GIOBUS_SIZE, PROT_READ|PROT_WRITE,
      (MAP_PRIVATE), mmemFd,
      PHYS_TO_K1(GIOBUS_BASE))) == (unsigned char *)-1) {
	errlog(ERR_SEVERE,
	  "%s: cannot map 0x%x (errno = %d)\n", 
	  test_ref->name, GIOBUS_BASE, errno);
	perror("mmap");
	return(1);
    }

    pBoard = (struct u64_board *)(mapbase);

    if ( (pBoard->product_id_reg & _U64_PRODUCT_ID_MASK) != 
      _U64_PRODUCT_ID_VALUE ) {
	errlog(ERR_SEVERE,
	  "unable to read product id.\n");
	errlog(ERR_SEVERE, 
	  "\tread 0x%x, exp 0x%x\n", *mapbase, _U64_PRODUCT_ID_VALUE);
	return(1);
    } else {
	errlog(DEBUG, 
	  "product id reg = 0x%x.\n", pBoard->product_id_reg);
    }
    fflush(stderr);

    errorCount =  checkerboard_long(0xaaaa5555, mapbase, "checkerboard test") ;
    errorCount += checkerboard_long(0x5555aaaa, mapbase,
				    "checkerboard bar test") ;
    errorCount += address_long(0, mapbase, "addr to addr test") ;
    errorCount += address_long(-1, mapbase, "inverse addr to addr test") ;
    return(errorCount);
}

int address_long(unsigned int addrmask, unsigned char *mapbase,
		 unsigned char *name)
{
    int pageIndex, memIndex;
    int errorCount;
    unsigned int readLong, readLongAddr, realAddr;

    /*
     * Loop through each 1MB page of memory and do a simple address to 
     * address test.  Use 32 bit addressing.
     */
    realAddr = 0;
    for (pageIndex = 0, errorCount = 0; pageIndex < 16; pageIndex++) {
       /*
        * Setup the page pointer in the page control register.
        */
       pBoard->dram_page_cntrl = (pageIndex << 20);
       for (memIndex = 0, readLongAddr = (((int)mapbase) + U64_MEM_SIZE); 
	  memIndex < (U64_MEM_SIZE >> 2);
	  memIndex++, readLongAddr += 4, realAddr += 4) {
	    *((unsigned int *)readLongAddr) = realAddr ^ addrmask;
       }
    }
    for (pageIndex = 0, realAddr = 0; pageIndex < 16; pageIndex++) {
       /*
        * Setup the page pointer in the page control register.
        */
       pBoard->dram_page_cntrl = (pageIndex << 20);
       errlog(DEBUG, "testing page %d, %s.\n", pageIndex, name);
       for (memIndex = 0, readLongAddr = (((int)mapbase) + U64_MEM_SIZE); 
	    memIndex < (U64_MEM_SIZE >> 2);
	    memIndex++, readLongAddr += 4, realAddr += 4) {
	  readLong = *((unsigned int *)(readLongAddr));
	  if (readLong != (realAddr ^ addrmask)) {
	     errlog(ERR_SIMPLE, "0x%x, read 0x%x, exp 0x%x, rd^exp = 0x%x\n", 
		    readLongAddr, readLong, realAddr ^ addrmask, 
		    (readLong ^ realAddr ^ addrmask));
	     ++errorCount;
	  }
       }
    }

    if (errorCount > 0) {
	errlog(ERR_SEVERE, 
	    "(%s): 0x%x (%d) errors encountered.\n", 
	    name, errorCount, errorCount);
    } else {
	errlog(DEBUG, 
	    "(%s): no errors encountered.\n", name);
    }
    return (errorCount);
}

int checkerboard_long(unsigned int data, unsigned char *mapbase,
		      unsigned char *name)
{
    int pageIndex, memIndex;
    int errorCount;
    unsigned int readLong, readLongAddr;

    /*
     * Loop through each 1MB page of memory and do a simple checkerboard
     * test.  Use 32 bit addressing.
     */
    errorCount = 0;
    for (pageIndex = 0; pageIndex < 16; pageIndex++) {
       /*
        * Setup the page pointer in the page control register.
        */
       pBoard->dram_page_cntrl = (pageIndex << 20);
       for (memIndex = 0, readLongAddr = (((int)mapbase) + U64_MEM_SIZE); 
	    memIndex < (U64_MEM_SIZE >> 2); memIndex++, readLongAddr += 4) {
	    *((unsigned int *)readLongAddr) = data;
       }
    }
    for (pageIndex = 0; pageIndex < 16; pageIndex++) {
       /*
        * Setup the page pointer in the page control register.
        */
       pBoard->dram_page_cntrl = (pageIndex << 20);
       errlog(DEBUG, "testing page %d, %s.\n", pageIndex, name);
       for (memIndex = 0, readLongAddr = (((int)mapbase) + U64_MEM_SIZE); 
	    memIndex < (U64_MEM_SIZE >> 2); memIndex++, readLongAddr += 4) {
	  readLong = *((unsigned int *)(readLongAddr));
	  if (readLong != data) {
	     errlog(ERR_SIMPLE, "0x%x, read 0x%x, exp 0x%x, rd^exp = 0x%x\n", 
		    readLongAddr, readLong, data, (readLong ^ data));
	     ++errorCount;
	  } 
       }
    }

    if (errorCount != 0) {
	errlog(ERR_SEVERE, 
	    "(%s): 0x%x (%d) errors encountered.\n", 
	    name, errorCount, errorCount);
    } else {
	errlog(DEBUG, 
	    "(%s): no errors encountered.\n", name);
    }
    return (errorCount);
}