[comp.sys.amiga.tech] scsidisk.h and scsidirect.device - Inquiry example!

migh@cuuxb.ATT.COM (~XT6561110~Mike Hall~C24~M26a~6029~) (12/20/89)

 = In article <1753@agora.UUCP> billsey@.UUCP (Bill Seymour) writes:
 = >In article <1842@sauron.Columbia.NCR.COM: stevem@sauron.UUCP (Steve McClure) writes:
 = This is good news, thanks Bill.  I had talked to Supra and was told flatly
 = there was no example code.  I did however have minimal success using the
 = device.  SCSI devices responded, but I did not figure out how to read the 
 = results of an Inquiry.

In the back of Xetec's manual, they list a one-page routine to do "SCSI
direct".  They use the "harddisk.device", however.  Is that going to be
non-standard?

As for reading/interpreting the Inquiry data... I'm glad you asked! I was 
going to post this today, and you've given me a nice lead-in.. Thank you!

What follows is a shell archive of "inq.c" - the guy that examines the 
Inquiry response, and two other files.  I didn't like the way that Xetec's
implementation of accessing the SCSI device was so dense: open everything,
do it, close everything.  (I want to write a tape application that actually
works - unlike their own product...grrr.)  Sooo... I chopped it up into
OpenSCSI, DoSCSI, and CloseSCSI.  I've also invented a new structure to
hold all the crap - SCSIcb (SCSI command block).

I would appreciate near-lethal comments and criticisms of this code.  It 
wasn't written in the wee hours, but it _was_ getting pretty late... :-)
Thanks!

--- cut here --- --- --- --- --- --- --- --- --- ---

# The rest of this file is a shell script which will extract:
# inq.c scsinfc.c scsinfc.h
echo x - inq.c
cat >inq.c <<'!Funky!Stuff!'
/*
 *	SCSI Device Inquiry
 */

#include <exec/types.h>
#include <exec/io.h>
#include <devices/scsidisk.h>
#include <FastTrak.h>

#include 	"SCSInfc.h"
#include	<stdio.h>
#include	<string.h>

#define	MAX_PD_TYPE	10
char	*pdtypes[] = {
	"disk", "tape", "printer", "processor",
	"worm", "rodisk", "scanner", "optical", 
	"changer", "communication", "(unknown)"
};

#define	INQRESP	128
long	resp[INQRESP/4];	/* Inquiry response - watch alignment! */
char	cdb[10] =		/* SCSI command itself (ditto!) */
	{ 0x12, 0, 0, 0, INQRESP, 0, 0, 0, 0, 0 };

struct	SCSIcb	scb;		/* general SCSI control block */

void showinfo(unit, params)
short	unit;
char	params[];
{
	char	vendor[10], product[18], prodrev[6];
	int	rmb, devtype;

	devtype = params[0];
	if ( devtype < 0 || devtype > MAX_PD_TYPE )
		devtype = MAX_PD_TYPE+1;
	rmb = params[1]&0x80;
	strncpy(vendor, &params[8], 8);
	vendor[8] = '\0';
	strncpy(product, &params[16], 16);
	product[16] = '\0';
	strncpy(prodrev, &params[32], 4);
	prodrev[4] = '\0';

	printf(" \033[1m%d\033[0m:  %s %s	\033[7m%s\033[0m \033[7m%s\033[0m \033[7m%s\033[0m\n", 
		unit,
		rmb ? "Removable" : "Non-removable",
		pdtypes[devtype],
		vendor, product, prodrev);
}

void showfail(unit, r)
short	unit, r;
{
	printf(" \033[1m%d\033[0m:   \033[3;33mfail, %s\033[0;31m\n", 
						unit, fterrmsg(r));
}

void inquire(unit)
int	unit;
{
	int	r;

	scb.unit = unit;
	scb.SCmd.scsi_Data	= (APTR) resp;
	scb.SCmd.scsi_Length	= INQRESP;
	scb.SCmd.scsi_Command	= cdb;
	scb.SCmd.scsi_CmdLength = 6;
	scb.SCmd.scsi_Flags = SCSIF_READ;

	if ( r = OpenSCSI(&scb) ) {
		showfail(unit, r);
		return;
	}
	else if ( (r = DoSCSI(&scb)) ) {
		showfail(unit, r);
	} else {
		showinfo(unit, resp);
	}
	CloseSCSI(&scb);
}

void main(argc,argv)
int	argc;
char	*argv[];
{	
	int	unit;

	if ( argc > 2 || *argv[1] == '?' || 		/*  bad args    */
	    (*argv[1] == '-' && argv[1][1] == '?') ) {	/* (poor code!) */
		printf("Usage: %ls <unit>\n",argv[0]);
		exit(FALSE);
	}
	else if ( argc == 1 ) {				/* no args: do all */
		for ( unit = 0; unit <= 7; unit++ ) 
			inquire(unit);
	}
	else {						/* one arg: do one */
		unit = atoi(argv[1]);
		if ( unit < 0 || unit > 7 ) {
			printf("Use: %ls <unit>\n", argv[0]);
			exit(FALSE);
		}
		inquire(unit);
	}
}

!Funky!Stuff!
echo x - scsinfc.c
cat >scsinfc.c <<'!Funky!Stuff!'

/*
 *	SCSI general interface routines
 */

#include <exec/types.h>
#include <exec/io.h>
#include <devices/scsidisk.h>
#include <FastTrak.h>

#include "scsinfc.h"

int OpenSCSI(scb)
struct SCSIcb	*scb;
{
	int	ret;

	scb->flags = 0;
	if ( scb->Port = (struct MsgPort *)CreatePort("ft_Tools",0) ) {
		if ( scb->Req = (struct IOStdReq *)CreateStdIO(scb->Port) ) {
			if ( ret = OpenDevice("harddisk.device",
						scb->unit, scb->Req, 0) ) {
				DeleteStdIO(scb->Req);
				DeletePort(scb->Port);
			} else {
				scb->flags = 1;
				scb->Req->io_Command = 28;
				scb->Req->io_Data = (APTR)&scb->SCmd;
				scb->Req->io_Length = sizeof(struct SCSICmd);
			}
		}
	}
	return ret;
}
				
void CloseSCSI(scb)
struct SCSIcb *scb;
{
	if ( scb->flags ) {
		AbortIO(scb->Req);
		WaitIO(scb->Req);
		CloseDevice(scb->Req);
		scb->flags = 0;
	}
	if ( scb->Req ) {
		DeleteStdIO(scb->Req);
		scb->Req = NULL;
	}
	if ( scb->Port ) {
		DeletePort(scb->Port);
		scb->Port = NULL;
	}
}

int DoSCSI(scb)
struct	SCSIcb *scb;
{
	DoIO(scb->Req);
	/*  Or... SendIO(req); WaitIO(req); */
	/* Actual = scb->SCmd.scsi_Actual; */
	return (int) scb->SCmd.scsi_Status;
}


/*
 *	Return error message given FastTrak error code
 */
char *fterrmsg(err)
int	err;
{
	switch (err) {
	case FTERR_SelfUnit:	return "cannot issue SCSI command to self";
	case FTERR_DMA:		return "DMA error";
	case FTERR_Phase:	return "illegal or unexpected SCSI phase";
	case FTERR_Parity:	return "SCSI parity error";
	case FTERR_SelTimeout:	return "select timed out";
	case FTERR_BadStatus:	return "status and/or sense error";
	case FTERR_NoBoard:	return "open failed for non-existant board";
	default:		return "unknown error";
	}
}

!Funky!Stuff!
echo x - scsinfc.h
cat >scsinfc.h <<'!Funky!Stuff!'

/*
 *	definitions for SCSInfc.c
 */

struct	SCSIcb {	/* SCSI control block */
	short	flags;			/* open or not */
	short	unit;			/* which SCSI unit this is for */
	struct	IOStdReq *Req;		/* IORequest */
	struct	MsgPort	*Port;		/* and Message Port */
	struct	SCSICmd  SCmd;		/* and the SCSI Command ptrs */
};

int	OpenSCSI(struct SCSIcb *);
void	CloseSCSI(struct SCSIcb *);
int	DoSCSI(struct SCSIcb *);

char	*fterrmsg(int);
!Funky!Stuff!
------ that's all ---

Mike Hall	att!cuuxb!migh		migh@cuuxb.att.com