File:  [Apple Darwin 0.x] / driverkit / tests / dx.m
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:37:50 2018 UTC (8 years, 2 months ago) by root
Branches: MAIN, Apple
CVS tags: HEAD, Darwin03, Darwin02
Darwin 0.2 Driver Kit

/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
 * Reserved.  This file contains Original Code and/or Modifications of
 * Original Code as defined in and that are subject to the Apple Public
 * Source License Version 1.1 (the "License").  You may not use this file
 * except in compliance with the License.  Please obtain a copy of the
 * License at http://www.apple.com/publicsource and read it before using
 * this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
/*
 * dx - menu based device exerciser tool.
 *
 * HISTORY
 * 19-Mar-91    Doug Mitchell at NeXT
 *      Created.
 */
 
#import <bsd/sys/types.h>
#import <bsd/libc.h>
#import <driverkit/IOClient.h>
#import <driverkit/SCSIDiskClient.h>
#import <bsd/dev/SCSITypes.h>
#import <mach/mach_error.h>
#import "defaults.h"
#import "buflib.h"

/*
 * prototypes for private functions.
 */
static void usage(char **argv);
static void print_menu();
static void setupCDB();
static void setupScsiReq(scsiReq_t *scsiReq, SCSIDmaDir_t dir);

/*
 * Menu stuff.
 */
struct menu_entry {
	char 	menu_c;
	char	*name;
	void	(*men_fcn)();
};

/*
 * User commands.
 */
static void dxRead();
static void dxWrite();
static void cdbRead();
static void cdbWrite();
static void setTarget();
static void setLun();
static void setCount();
static void setBlock();
static void dxQuery();
static void dxCheckReady();
static void setByteCount();
static void setLoopCount();
static void getForm();
static void setForm();
static void getRemove();
static void fillWbuf();
static void dumpRbuf();
static void quit();
static void getDname();
static void dxEject();

struct menu_entry me_array[] = {

    {'r', "Read         " , dxRead	}, {'w', "Write        " , dxWrite	},
    {'R', "cdbRead      " , cdbRead	}, {'W', "cdbWrite     " , cdbWrite	},
    {'c', "Set Count    " , setCount	}, {'b', "Set Block    " , setBlock	},
    {'T', "Set Target   " , setTarget	}, {'L', "Set lun      " , setLun	},
    {'Q', "Query        " , dxQuery	}, {'u', "Check Ready  " , dxCheckReady	},
    {'y', "Max ByteCount" , setByteCount}, {'l', "Loop Count   " , setLoopCount	},
    {'f', "Get Formatted" , getForm	}, {'F', "Set Formatted" , setForm	},
    {'v', "Get Removable" , getRemove	}, {'C', "Set up CDB   " , setupCDB	},
    {'D', "GetDriveName " , getDname  }, {'e', "Eject        " , dxEject      },
    {'1', "Fill buffer  " , fillWbuf	}, {'2', "Dump Buffer  " , dumpRbuf	},
    {'x', "Exit         " , quit	}, {'h', "Help         " , print_menu	},
    {0,	NULL		 , NULL		}
};

#define BUFSIZE		(64 * 1024)

/*
 * Static variables.
 */
int ioTimeout = 10;
int target = 0;
int lun = 0;
id clientId;
int count = 1024;
int block = 0;
int byteCountMax = 4096;
int loopCount = 1;
u_char cdb[12];
char *hostname=HOST_DEFAULT;
char *devname=DEVICE_DEFAULT;
char *rbuf, *wbuf;
IOErrorString errorstr;

int main(int argc, char **argv)
{
	int arg;
	char instr[80];
	struct	menu_entry *mep;
	int ok;
	IOReturn rtn;
	kern_return_t krtn;
	
	/*
	 * Get standard defaults from environment or defaults.h
	 */
	get_default_t("hostname", &hostname, HOST_DEFAULT);
	get_default_t("devname", &devname, DEVICE_DEFAULT);

	for(arg=1; arg<argc; arg++) {
		switch(argv[arg][0]) {
		    case 'h':
		    	hostname = &argv[arg][2];
			break;
		    case 'd':
		    	devname = &argv[arg][2];
			break;
		    default:
		    	usage(argv);
		}
	}

	/*
	 * Instantiate and init the client object. Use SCSIDiskClient as
	 * default.
	 */
	rtn = [SCSIDiskClient clientOpen:devname
		hostName:hostname
		intentions:IO_INT_READ|IO_INT_WRITE
		idp:&clientId];
	if(rtn) {
		/*
		 * try opening read only.
		 */
		rtn = [SCSIDiskClient clientOpen:devname
			hostName:hostname
			intentions:IO_INT_READ
			idp:&clientId];
		if(rtn) {
			[SCSIDiskClient ioError:rtn
				logString:"Open"
				outString:errorstr];
			printf("%s...aborting\n", errorstr);
			exit(1);
		}
		else
			printf("...Warning: Device is Read-Only\n");
	}
	
	/*
	 * Allocate and init read and write buffers.
	 */
	krtn = vm_allocate(task_self(),
		(vm_address_t *)&rbuf,
		(vm_size_t)BUFSIZE,
		TRUE);
	if(krtn) {
		mach_error("vm_allocate", krtn);
		exit(1);
	}
	krtn = vm_allocate(task_self(),
		(vm_address_t *)&wbuf,
		(vm_size_t)BUFSIZE,
		TRUE);
	if(krtn) {
		mach_error("vm_allocate", krtn);
		exit(1);
	}
	bzero(rbuf, BUFSIZE);
	bzero(wbuf, BUFSIZE);
	
	/*
	 * Enter main loop.
	 */
	print_menu();
	while(1) {
		printf("Enter Selection: ");
		gets(instr);
		mep = me_array;
		ok = 0;
		while(mep->menu_c) {
			if(mep->menu_c == instr[0]) {
				ok = 1;
				(*mep->men_fcn)();
				break;
			}
			else
				mep++;
		}
		if(!ok)
			printf("***Illegal Selection\n");
	}
	return(0);
}

static void usage(char **argv)
{
	printf("usage: %s d[h=hostname] [d=devname]\n", argv[0]);
	exit(1);
}

static void print_menu() {
	
	struct menu_entry *mep;
	
	printf("\n");
	mep = me_array;
	while(mep->menu_c) {
		printf(" %c: %s  ",mep->menu_c,mep->name);
		mep++;
		if(mep->menu_c) {
			printf(" %c: %s  ",mep->menu_c,mep->name);
			mep++;
		}
		printf("\n");
	}
	printf("\n");
} /* print_menu() */

static void cdbRead()
{
	scsiReq_t scsiReq;
	scStatus rtn;
	
	setupScsiReq(&scsiReq, SCSI_DMA_READ);
	rtn = [clientId sdCdbRead:&scsiReq buf:rbuf];
	if(rtn) {
		[IOClient ioError:rtn
			logString:"sdCdbRead"
			outString:errorstr];
		printf("%s", errorstr);
	}
	else if(scsiReq.ioStatus)
		printf("...sdCdbRead: ioStatus = %d\n", scsiReq.ioStatus);
	else
		printf("...OK\n");
}

static void cdbWrite()
{
	scsiReq_t scsiReq;
	scStatus rtn;
	
	setupScsiReq(&scsiReq, SCSI_DMA_WRITE);
	rtn = [clientId sdCdbWrite:&scsiReq buf:wbuf];
	if(rtn) 
	if(rtn) {
		[IOClient ioError:rtn
			logString:"sdCdbWrite"
			outString:errorstr];
		printf("%s", errorstr);
	}
	else if(scsiReq.ioStatus)
		printf("...sdCdbWrite: ioStatus = %d\n", scsiReq.ioStatus);
	else
		printf("...OK\n");
}

static void setTarget()
{
	char instr[100];
	
	printf("Enter new target (CR = %d): ", target);
	gets(instr);
	if(instr[0]) 
		target = atoi(instr);
}

static void setLun()
{
	char instr[100];
	
	printf("Enter new lun (CR = %d): ", lun);
	gets(instr);
	if(instr[0]) 
		lun = atoi(instr);
}

static void setCount()
{
	printf("Enter new count (CR = %d): ", count);
	count = get_num(count, DEC);
}

static void setBlock()
{
	printf("Enter new block (CR = %d): ", block);
	block = get_num(block, DEC);
}

static void dxQuery()
{
	u_int queryData;
	IOReturn rtn;
	
	rtn = [clientId ioQuery:&queryData];
	if(rtn) {
		[IOClient ioError:rtn 
			  logString:"ioQuery"
			  outString:errorstr];
		printf(errorstr);
		return;
	}
	printf("   queryData = 0x%X\n", queryData);
	if(queryData & DQF_READABLE)
		printf("\tDQF_READABLE\n");
	if(queryData & DQF_WRITEABLE)
		printf("\tDQF_WRITABLE\n");
	if(queryData & DQF_RAND_ACC)
		printf("\tDQF_RAND_ACC\n");
        if(queryData & DQF_CAN_QUEUE)
		printf("\tDQF_CAN_QUEUE\n");
        if(queryData & DQF_CAN_RD_LOCK)
		printf("\tDQF_CAN_RD_LOCK\n");
        if(queryData & DQF_CAN_WRT_LOCK)
		printf("\tDQF_CAN_WRT_LOCK\n");
        if(queryData & DQF_IS_RD_LOCK)
 		printf("\tDQF_IS_RD_LOCK\n");
        if(queryData & DQF_IS_WRT_LOCK)
		printf("\tDQF_IS_WRT_LOCK\n");
        if(queryData & DQF_EXCLUSIVE)
		printf("\tDQF_EXCLUSIVE\n");
#ifdef	notdef
	printf("   block_size = 0x%X   dev_size = %d\n", 
		queryData.block_size, queryData.dev_size);
#endif	notdef
}

static void dxRead()
{
	u_int bytesXfr;
	IOReturn rtn;
		
	rtn = [clientId ioRead:block
		bytesReq:count
		buf:rbuf
		bytesXfr:&bytesXfr];
	if(rtn) {
		[IOClient ioError:rtn
			logString:"ioRead"
			outString:errorstr];
		printf("%s", errorstr);
		return;
	}
	if(bytesXfr != count) {
		printf("bytesXfr = 0x%x, expected 0x%x\n", 
			bytesXfr, count);
	}
}

static void dxWrite()
{
	u_int bytesXfr;
	IOReturn rtn;
	
	rtn = [clientId ioWrite:block
		bytesReq:count
		buf:wbuf
		bytesXfr:&bytesXfr];
	if(rtn) {
		[IOClient ioError:rtn
			logString:"ioWrite"
			outString:errorstr];
		printf("%s", errorstr);
		return;
	}
	if(bytesXfr != count) {
		printf("bytesXfr = 0x%x, expected 0x%x\n", 
			bytesXfr, count);
	}
}

static void dxCheckReady()
{
	DiskReadyState ready;
	IOReturn rtn;
	
	rtn = [clientId updateReadyState:&ready];
	if(rtn) {
		[IOClient ioError:rtn
			logString:"CheckReady"
			outString:errorstr];
		printf("%s", errorstr);
		return;
	}
	switch(ready) {
	    case IO_Ready:
	    	printf("...Disk Ready\n");
		break;
	    case IO_NotReady:
	    	printf("...Disk Not Ready\n");
		break;
	    case IO_NoDisk:
	    	printf("...No Disk\n");
		break;
	    case IO_Ejecting:
	    	printf("...Ejecting\n");
		break;
	}
	return;
}

static void setByteCount()
{
	printf("Enter new max byte count (CR = %d): ", byteCountMax);
	byteCountMax = get_num(byteCountMax, DEC);

}

static void setLoopCount()
{
	printf("Enter new loop count (CR = %d): ", loopCount);
	loopCount = get_num(loopCount, DEC);
}

static void setupCDB()
{
	char instr[80];
	int i;
	
	printf("Hit ESC anytime to quit.\n");
	for(i=0; i<12; i++) {
		printf("Enter CDB byte %d (CR = 0x%x): ", i, cdb[i]);
		gets(instr);
		switch(instr[0]) {
		    case '\0':
		    	break;			/* take default */
		    case 0x1b:			
		    	return;			/* ESC - done */
		    default:
		    	cdb[i] = atoh(instr);
			break;
		}
	}
}

static void getForm()
{
	u_int formFlag;
	IOReturn rtn;
	
	rtn = [clientId getFormatted:&formFlag];
	if(rtn) {
		[IOClient ioError:rtn
			logString:"getFormatted"
			outString:errorstr];
		printf("%s", errorstr);
		return;
	}
	if(formFlag)
		printf("...Disk Formatted\n");
	else
		printf("...Disk Unformatted\n");
}

static void setForm()
{
	u_int formFlag;
	IOReturn rtn;
	char instr[80];
	
	printf("New formatted value (0/1): ");
	gets(instr);
	if(instr[0] == '1')
		formFlag = 1;
	else
		formFlag = 0;		
	rtn = [clientId setFormatted:formFlag];
	if(rtn) {
		[IOClient ioError:rtn
			logString:"setFormatted"
			outString:errorstr];
		printf("%s", errorstr);
		return;
	}
	else
		printf("...OK\n");
}

static void getRemove()
{
	u_int removeFlag;
	IOReturn rtn;
	
	rtn = [clientId getRemovable:&removeFlag];
	if(rtn) {
		[IOClient ioError:rtn
			logString:"getRemovable"
			outString:errorstr];
		printf("%s", errorstr);
		return;
	}
	if(removeFlag)
		printf("...Removable Disk\n");
	else
		printf("...Fixed Disk\n");
}

static void fillWbuf()
{
	char instr[80];
	int i;
	
	printf("z = zero\ni = incrementing\nd = decrementing\n");
	printf("Enter pattern: ");
	gets(instr);
	switch(instr[0]) {
	    case 'z':
	    	bzero(wbuf, BUFSIZE);
		break;
	    case 'i':
		for(i=0; i<BUFSIZE; i++)
			wbuf[i] = i;
		break;
	    case 'd':
		for(i=0; i<BUFSIZE; i++)
			wbuf[i] = BUFSIZE - i;
		break;
	    default:
	    	printf("***Illegal selection***\n");
		break;
	}
}

static void dumpRbuf()
{
	dump_buf((u_char *)rbuf, BUFSIZE);
}

static void getDname()
{
/*	const char *name; */
	
	printf("...getDriveName not supported\n");
	return;
#ifdef	notdef
	name = [clientId getDriveName];
	if(name == NULL) {
		printf("NULL drivename\n");
		return;
	}
	printf("Drive Name = %s\n", name);
	return;
#endif	notdef
}

static void dxEject()
{
	IOReturn rtn;
	
	rtn = [clientId eject];
	if(rtn) {
		[IOClient ioError:rtn
			logString:"eject"
			outString:errorstr];
		printf("%s", errorstr);
		return;
	}
	printf("...OK\n");
}

/*
 * Internal functions.
 */
static void setupScsiReq(scsiReq_t *scsiReq, SCSIDmaDir_t dir)
{
	bzero(scsiReq, sizeof(scsiReq_t));
	scsiReq->target = target;
	scsiReq->lun	= lun;
	scsiReq->cdb    = *(cdb_t *)cdb;
	scsiReq->dmaDir = dir;
	scsiReq->dmaMax = byteCountMax;
	scsiReq->ioTimeout = ioTimeout;
	scsiReq->disconnect = 1;
}

static void quit()
{
	exit(0);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.