ndev_bcopy.c 4.92 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_GIO_MEMTEST_BASE	10

static int gio_bcopytest(TEST_REF *test_ref);

/*
 * 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 (fast bcopy)", 	U64_GIO_MEMTEST_BASE+0, gio_bcopytest},
    {"",0,0}
};

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

static int gio_bcopyInit();
static int gio_bcopyDo(TEST_REF *test_ref);

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

    diaginit(TestRefs, gio_bcopyInit, gio_bcopyDo);

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

static int gio_bcopyInit()
{
    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 gio_bcopyDo(TEST_REF *test_ref)
{
    int rc;

    errlog(INFO_START,
      "%s: starting test %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(INFO_END, "... test %s PASSED", TestName);
    } else {
	errlog(INFO_END, "... FAILED");
    }
    return(NumFailures);
}

/*
 * Return value: number of errors encountered.  "Zero" indicates success.
 */
int
gio_bcopytest(TEST_REF *test_ref)
{
    int mmemFd;
    unsigned char *mapbase;
    int pageIndex, memIndex;
    struct u64_board *pBoard;
    int c;
    int verbose = 0;
    int errorCount0, errorCount1;
    unsigned int readLong, readLongAddr;
    unsigned short readShort, readShortAddr;
    unsigned int *oneMeg;

    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);
    oneMeg = (unsigned int *)malloc(U64_MEM_SIZE);
    if (oneMeg == NULL) {
	errlog(ERR_SEVERE, 
	  "%s: cannot malloc 0x%x bytes for private buffer\n", 
	  test_ref->name, U64_MEM_SIZE);
    }
    bzero(oneMeg, U64_MEM_SIZE);

    /*
     * Loop through each 1MB page of memory and clear memory to a
     * known, changing pattern (simple address to address test).  Then
     * go through and do a fast bcopy clear of memory (using our bzeroed 
     * buffer)& validate.  Use 32 bit addressing.
     */
    for (pageIndex = 0, errorCount0 = 0; pageIndex < 16; pageIndex++) {

	errlog(DEBUG, 
	  "testing page %d, addr to addr.\n", pageIndex);

	/*
	 * Setup the page pointer in the page control register.
	 */
	pBoard->dram_page_cntrl = (pageIndex << 20);

	/*
	 * Write address to address slowly, using proven (slow) 32 bit method.
	 */
	for (memIndex = 0, 
	  readLongAddr = (((int)mapbase) + U64_MEM_SIZE); 
	  memIndex < (U64_MEM_SIZE >> 2); memIndex++, readLongAddr += 4) {
	    *((unsigned int *)readLongAddr) = readLongAddr;
	}

	/*
	 * Clear memory using bcopy and bzeroed buffer.
	 */
	bcopy( oneMeg, (((int)mapbase) + U64_MEM_SIZE), U64_MEM_SIZE ); 

	for (memIndex = 0,
	  readLongAddr = (((int)mapbase) + U64_MEM_SIZE); 
	  memIndex < (U64_MEM_SIZE >> 2); memIndex++, readLongAddr += 4) {
	    readLong = *((unsigned int *)(readLongAddr));

	    if (readLong != 0) {
		errlog(ERR_SIMPLE, 
		  "0x%x, read 0x%x, exp 0x%x, rd^exp = 0x%x\n", 
		  readLongAddr, readLong, 0, 
		  (readLong ^ 0));
		++errorCount0;
	    }
	}
    }

    if (errorCount0 > 0) {
	errlog(ERR_SEVERE, 
	    "(addr to addr test): 0x%x (%d) errors encountered.\n", 
	    errorCount0, errorCount0);
    } else {
	errlog(DEBUG, 
	    "(addr to addr test): no errors encountered.\n");
    }
    return(errorCount0);
}