From: jesup@cbmvax.commodore.com (Randell Jesup)
Newsgroups: comp.sys.amiga.programmer
Subject: Re: Sending SCSI Direct commands on an A3000
Date: 22 Aug 92 00:54:04 GMT
Reply-To: jesup@cbmvax.commodore.com (Randell Jesup)
Organization: Commodore, West Chester, PA

harp@netcom.com (Gregory O. Harp) writes:
>
>I need some pointers on sending SCSI Direct commands to a device
>plugged into my A3000.
>
>First of all, if someone already has a program that allows the user to
>send various commands I'd appreciate it if they would tell me how I

	This should get you started.  One of these days I should get around to
releasing scsidirect.c which uses these routines to allow you to play around
with innumerable scsi commands (it's built around the same engine as the
"dos_calls" program).

	Randell

/* scsi.c */

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

#include <clib/exec_protos.h>
#include <clib/alib_protos.h>

#include <stdio.h>

#include "scsi.h"

#define SAME 0

#define AllocNew(t)	((struct t *) AllocMem(sizeof(struct t),MEMF_CLEAR))

extern char *device;
extern int  unit;

struct IOStdReq *ior = NULL;
struct MsgPort *port = NULL;
int opened=FALSE;

void closedevice(void);

void closedevice ()
{
	if (opened)
		CloseDevice(ior);
	if (ior)
		DeleteStdIO(ior);
	if (port)
		DeletePort(port);

	opened = 0;
	ior = NULL;
	port = NULL;
}

int
opendevice (char *device, int unit)
{
	int i = 0;

	if (!(port = CreatePort(0L,0L)))
		goto cleanup;
	if (!(ior = CreateStdIO(port)))
		goto cleanup;

	printf("Opening device %s, unit %ld\n",device,unit);

	if (i = OpenDevice(device,unit,
			   (struct IORequest *) ior,0L))
	{
		printf("error %ld on open\n",i);
		goto cleanup;
	}
	return 0;

cleanup:
	closedevice();
	return i;
}

/* do any SCSI command using the supplied iorequest, ret 0=success or error */
/* data must be word aligned and dmaable */
/* ditto for command */

UBYTE  sensedata[255];
struct SCSICmd cmdblk;

int DoSCSI (struct IOStdReq *ior,
		   UWORD *command,
		   ULONG clen,
		   UWORD *data,
		   ULONG dlen,
		   ULONG flags);

void SendSCSI (struct IOStdReq *ior,
		     UWORD *command,
		     ULONG clen,
		     UWORD *data,
		     ULONG dlen,
		     ULONG flags);

int
DoSCSI (struct IOStdReq *ior,
		   UWORD *command,
		   ULONG clen,
		   UWORD *data,
		   ULONG dlen,
		   ULONG flags)/* only a ubyte used for actual xfer, rest for this rtn */
{

	SendSCSI(ior,command,clen,data,dlen,flags);
	WaitIO((struct IORequest *) ior);

#ifdef TEST_SCSI
printf("direct scsi return error %d, status %d\n",ior->io_Error,cmdblk.scsi_Status);
if (cmdblk.scsi_SenseActual)
{
int i;
printf("Sense data (length %d) = 0x",cmdblk.scsi_SenseActual);
for(i = 0; i < cmdblk.scsi_SenseActual; i++)
printf("%02.2x",sensedata[i]);
printf("\n");
}
#endif
	if (cmdblk.scsi_Status)
		return (int) cmdblk.scsi_Status;

	return (int) ior->io_Error;	/* see scsidisk.h for errors */
}

void
SendSCSI (struct IOStdReq *ior,
		     UWORD *command,
		     ULONG clen,
		     UWORD *data,
		     ULONG dlen,
		     ULONG flags)/* only a ubyte used for actual xfer, rest for this rtn */
{
	/* first set up ior */
	ior->io_Data    = (APTR) &cmdblk;
	ior->io_Length  = sizeof(cmdblk);
	ior->io_Actual  = ior->io_Offset = 0;
	ior->io_Command = HD_SCSICMD;

	/* now set up cmdblk */
	cmdblk.scsi_Data      = data;
	cmdblk.scsi_Length    = dlen;
	cmdblk.scsi_Actual    = 0;
	cmdblk.scsi_Command   = (UBYTE *) command;
	cmdblk.scsi_CmdLength = clen;
	cmdblk.scsi_CmdActual = 0;
	cmdblk.scsi_Flags     = flags & 0xff; /* probably not needed */
	cmdblk.scsi_Status    = 0;
	cmdblk.scsi_SenseData = sensedata;
	cmdblk.scsi_SenseLength = sizeof(sensedata);
	cmdblk.scsi_SenseActual = 0;
/*	cmdblk.scsi_NextLinked  = NULL;*/

	SendIO((struct IORequest *) ior);
}


/* scsi.h */

#define S_TEST_UNIT_READY	0x00
#define S_REZERO_UNIT		0x01
#define S_REQUEST_SENSE		0x03
#define S_FORMAT_UNIT		0x04
#define S_REASSIGN_BLOCKS	0x07
#define S_READ			0x08
#define S_WRITE			0x0a
#define S_SEEK			0x0b
#define S_INQUIRY		0x12
#define S_MODE_SELECT		0x15
#define S_RESERVE		0x16
#define S_RELEASE		0x17
#define S_COPY			0x18
#define S_MODE_SENSE		0x1a
#define S_START_STOP_UNIT	0x1b
#define S_PREVENT_ALLOW_REMOVAL	0x1e
#define S_READ_CAPACITY 	0x25
#define S_READ10		0x28
#define S_WRITE10		0x2a
#define S_WRITE_VERIFY		0x2e
#define S_VERIFY		0x2F
#define S_PREFETCH		0x34
#define S_SYNCHRONIZE_CACHE	0x35
#define	S_LOCK_UNLOCK_CACHE	0x36
#define S_READ_DEFECT_DATA	0x37
#define S_WRITE_BUFFER		0x3b
#define S_READ_BUFFER		0x3c
#define S_MODE_SELECT_10	0x55
#define S_MODE_SENSE_10		0x5a

/* sense codes */
#define CHECK_CONDITION		0x02

/* sense keys */
#define RECOVERED_ERROR		0x01
#define MEDIUM_ERROR		0x03
#define HARDWARE_ERROR		0x04
#define ILLEGAL_REQUEST		0x05

-- 
"Rev on the redline, you're on your own; seems like a lifetime, but soon it's
 gone..."  Foreigner
-
Randell Jesup, Jack-of-quite-a-few-trades, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.cbm.commodore.com  BIX: rjesup  
Disclaimer: Nothing I say is anything other than my personal opinion.
Newsgroups: comp.sys.amiga.programmer,comp.sys.amiga.misc