#include <sys/types.h>
#include <sys/ioctl.h>
#include <tmc/vmeio-ioctl.h>

extern int errno;
#include <stdio.h>

/*
 * Test internal loopback on Rev3 VMEIO board
 * using device driver interface
 */


main(ac, av)
char **av;
{
    int cc, fd, bs;
    char *buf1, *buf2;
    register int count = 1;
    register int iteration;
    register int docompare = 1;
    int cpid;
    int zero;

    if (ac < 2) {
	printf("usage: %s blocksize [count] [nocompare]\n", av[0]);
	exit(1);
    }

    bs = atoi(av[1]);
    if (ac > 2)
	count = atoi(av[2]);

    if (ac > 3)
	docompare = 0;
	
	
    if (cpid=fork()) {
	/* parent */
	while(wait(0) != cpid)
	    ;
	exit(0);
    }

    /* child */

    if ((fd = open("/dev/cmio0", 2)) < 0) {
	perror("open /dev/cmio0");
	exit(1);
    }


    if ((buf1 = (char *)valloc(bs)) == 0) {
	perror("valloc");
	exit(1);
    }

    if ((buf2 = (char *)valloc(bs)) == 0) {
	perror("valloc");
	exit(1);
    }

    { register long *n;
    for(n = (long *)buf1; n < (long *)&buf1[bs]; n++)
	*n = /*random()*/ 0xa5a5a5a5;
    }

    (void) ioctl(fd, VMEIO_DIAG_SET_LOOP, 0);

    iteration = 0;
    while(count < 0 || count-- > 0) {
	iteration++;
	if ((iteration % 100) == 0) {
	    printf("    %d\r", iteration);
	    fflush(stdout);
	}
	zero = 0;
	if (ioctl(fd, VMEIO_SET_RAM_PTR, &zero) < 0)
	    perror("VMEIO_SET_RAM_PTR ioctl");
	if ((cc = write(fd, buf1, bs)) < 0) {
	    printf("write buf1=0x%x bs=%d failed (%d), iteration %d\n", 
		buf1, bs, errno, iteration);
	    perror("write");
	    exit(1);
	}

	zero = 0;
	if (ioctl(fd, VMEIO_SET_RAM_PTR, &zero) < 0)
	    perror("VMEIO_SET_RAM_PTR ioctl");
	if ((cc = read(fd, buf2, bs)) < 0) {
	    printf("read buf2=0x%x bs=%d failed (%d), iteration %d\n", 
		buf2, bs, errno, iteration);
	    perror("read");
	    exit(1);
	}

	if (docompare) {
	    register long *n, *m;
	    for(n = (long *)buf1, m = (long *)buf2; 
		n < (long *)&buf1[bs]; n++, m++)
		if (*n != *m)
		    printf("data compare error, iteration %d, offset 0x%x, \nwrote 0x%x got 0x%x, diff 0x%x\n",
			   iteration,
			   (int)n - (int)buf1,
			   *n, *m, *m^*n);
	}
	
    }

}
	
