Subject: update on scsi issues in -current
To: None <port-next68k@netbsd.org>
From: Darrin B. Jewell <dbj@netbsd.org>
List: port-next68k
Date: 04/17/2001 11:31:14
> THIS IS A MESSAGE IN 'MIME' FORMAT.
> If you are reading this, your mail reader may not support MIME.
> Some parts of this message will be readable as plain text.

--mysteryboxofun
Content-Type: text/plain

So I hacked on the -current sources this weekend and committed some
changes from my local tree.  I had planned to get that out of the way
and to test chuq's ELF upgrade, but I didn't get to the ELF testing.
I hope to do that shortly.

I tested scsi in -current, which doesn't work well enough for general
use yet.  DMA transfers work much of the time, but too often they get
corrupted.  I have included in this email the torture test I have been
using.  Given a random seed and a maximum file size, it writes or
reads a test dataset to/from a part of that file using a few randomly
chosen parameters.

At least one source of corruption has to do with the dma engine
prematurely shutting down before the transfer is completed.  I have
been testing two different configurations of the DMA driver, one where
it automatically restarts the DMA engine and the other where it
expects the attached device driver to handle the premature shutdown.

Currently, when I try to auto restart the DMA, I do so incorrectly and
get corrupted data.  If I don't restart the DMA, the esp scsi driver
never gets the completion interrupt and times out.  I will continue to
experiment and hopefully will eventually find the right combination to
get consistent scsi behavior.  It may be useful to go back to the 1.5
patches and run the torture test some more to see if it was more
stable than the -current sources.

Darrin

--mysteryboxofun
Content-Type: text/plain; charset=US-ASCII; name="testio.c"
Content-Description: ~/testio.c
Content-Disposition: attachment; filename="testio.c"


/*
 * Copyright (c) 1999, 2000, 2001 Darrin B. Jewell
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by Darrin B. Jewell
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#include <openssl/rc4.h>

/* Size of a block: */
#define BLKSIZE 512

/* Maximum number of blocks allowed in a single io operation: */
#define MAXBLKS (1<<11)					/* 2048 */

unsigned char zeros[BLKSIZE*MAXBLKS] = { 0 };
unsigned char rands[BLKSIZE*MAXBLKS] = { 0 };

int
main(int argc, char *argv[])
{
	int ret;
	int fd;
	int r;
	unsigned char *buf;
	unsigned char *iobuf;
	int total = 0;
	unsigned long seed;
	unsigned long blkcnt;
	const char *filename;
	unsigned long ioblen;
	unsigned long ioalgn;
	unsigned long iosize;
	unsigned long iooffs;
	int writeflag;
	RC4_KEY key;

	if (argc != 5) {
		fprintf(stderr,"usage: %s read|write seed blkcnt filename\n",argv[0]);
		return(EXIT_FAILURE);
	}
	
	writeflag = !strcmp(argv[1],"write");
	seed = strtoul(argv[2],NULL,10);
	blkcnt = strtoul(argv[3],NULL,10);
	filename = argv[4];

	{
		unsigned char sbuf[4];
		sbuf[0] = (seed>>24)&0xff;
		sbuf[1] = (seed>>16)&0xff;
		sbuf[2] = (seed>>8)&0xff;
		sbuf[3] = (seed&0xff);
		RC4_set_key(&key,4,sbuf);
	}

	RC4(&key,100,zeros,rands);
	{
		unsigned long rnd;
		rnd = rands[0]|(rands[1]<<8)|(rands[2]<<16)|(rands[3]<<24);
		iosize  = (rnd%blkcnt)+1;  /* size of the region read/written, in blocks */
		rnd = rands[4]|(rands[5]<<8)|(rands[6]<<16)|(rands[7]<<24);
		iooffs  = rnd%(blkcnt-iosize+1);	/* offset of the region read/written, in blocks */
		rnd = rands[8]|(rands[9]<<8)|(rands[10]<<16)|(rands[11]<<24);
		ioblen  = (rnd%(MAXBLKS>iosize?iosize:MAXBLKS))+1;	/* number of blocks per read/write */
		rnd = rands[12]|(rands[13]<<8)|(rands[14]<<16)|(rands[15]<<24);
		ioalgn  = (rnd%BLKSIZE);	  /* alignment of data in a block */
	}

	fprintf(stdout,
			"seed   = %lu (0x%lx)\tSpecified random number seed.\n"
			"blkcnt = %lu (0x%lx)\tSpecified number of blocks available on media.\n"
			"ioblen = %lu (0x%lx)\tBlocks per read or write operation.\n"
			"ioalgn = %lu (0x%lx)\tByte alignment of data in a read or write operation.\n"
			"iosize = %lu (0x%lx)\tBlocks to be read or written.\n"
			"iooffs = %lu (0x%lx)\tBlocks offset from beginning of media.\n",
			seed,seed,
			blkcnt,blkcnt,
			ioblen,ioblen,
			ioalgn,ioalgn,
			iosize,iosize,
			iooffs,iooffs);
	fflush(stdout);

	{
		assert(ioalgn < ioblen*BLKSIZE);
		buf = malloc(ioblen*BLKSIZE+ioalgn);
		assert(buf);
		iobuf = buf+ioalgn-((unsigned long)buf%ioalgn);
	}

	fd = open(filename,(writeflag?O_WRONLY:O_RDONLY|O_RSYNC)|O_SYNC|O_DSYNC|O_CREAT, 0x777);
	if (fd == -1) {
		perror("open");
		return(EXIT_FAILURE);
	}
	fprintf(stdout,"open successful\n");

	{
		off_t or;
		or = lseek(fd,iooffs*BLKSIZE,SEEK_SET);
		if (or == -1) {
			perror("lseek");
			return(EXIT_FAILURE);
		}
		assert(or == iooffs*BLKSIZE);
	}
	fprintf(stdout,"lseek successful\n");

	{
		long i;
		for(i=0;i<(ioblen*BLKSIZE);i++) {
			iobuf[i] = 0xff;
		}
	}
	fprintf(stdout,"pages initialized\n");

	do {
		if (writeflag) {
			fprintf(stdout,"s");
			fflush(stdout);
			/* Seed the buffer with random values */
			RC4(&key,ioblen*BLKSIZE,zeros,iobuf);
			fprintf(stdout,"w");
			fflush(stdout);
			r = write(fd,iobuf,ioblen*BLKSIZE);
			if (r == -1) {
				perror("write");
				return(EXIT_FAILURE);
			}
		} else {
			long i;
			fprintf(stdout,"0");
			fflush(stdout);
			memset(iobuf,0,ioblen*BLKSIZE);
			fprintf(stdout,"r");
			fflush(stdout);
			r = read(fd,iobuf,ioblen*BLKSIZE);
			if (r == -1) {
				perror("read");
				return(EXIT_FAILURE);
			}
			if (r != ioblen*BLKSIZE) {
				fprintf(stderr,"short read, got %d, expecting %ld\n",r,ioblen*BLKSIZE);
				return(EXIT_FAILURE);
			}
			fprintf(stdout,"s");
			fflush(stdout);
			/* Seed a buffer with expected random values */
			RC4(&key,ioblen*BLKSIZE,zeros,rands);
			fprintf(stdout,"c");
			fflush(stdout);
			/* compare the buffer with expected values */
			if (memcmp(iobuf,rands,ioblen*BLKSIZE)) {
				for(i=0;i<(ioblen*BLKSIZE);i++) {
					if (iobuf[i] != rands[i]) {
						fprintf(stderr,"Data mismatched at byte %ld (0x%08lx) got %d (0x%02x) expecting %d (0x%02x)\n",
								total+i,total+i,iobuf[i],iobuf[i],rands[i],rands[i]);
						return(EXIT_FAILURE);
					}
				}
				abort();
			}
		}
		assert(r >= 0);
		total += r;
		if (r != ioblen*BLKSIZE) {
			fprintf(stdout,"\n%s returned %d, total %d (0x%08x)\n",
					writeflag?"write":"read",r,total,total);
			return(EXIT_FAILURE);
		}
		fprintf(stdout,".");
		fflush(stdout);
	} while(r && (total < (iosize*BLKSIZE)));

	r = close(fd);
	if (r == -1) {
		perror("close");
		return(EXIT_FAILURE);
	}
	fprintf(stdout,"close successful\n");

	free(buf);

	return(EXIT_SUCCESS);
}


--mysteryboxofun--