/* park.c
	This example code shows how to direct access a generic SCSI device driver
that has been constructed in accordance with the specifications in the scsidisk.h
file. This is the resultant format from the Amiga Working Group on SCSI
interfacing standardization.

	It is used from the cli as
  "park <board number><LUN><SCSI address> [<device name>]"
with board number being a valid board for this driver in the range 0 through 7.
The LUN is a valid SCSI LUN, which are in the range 0 through 7. The SCSI address
is a valid SCSI device address. The device name defaults to HardFrame.device if
you enter nothing. You can enter "StarDrive.device" and the newest StarDrive
device driver will park the indicated unit. (This driver is as yet to be 
released as of this date, though.) Other device drivers may work depending on
the manufacturer's compliance with the specification. 

	As an added tweak to the code a unit number that is 1<board><LUN>SCSIId>
will cause the drive to unpark if it is there.

	© Joanne Dow, Wizardess Designs, 16 Dec 1988 All rights reserved.
 This may be freely copied as long as this notice remains here and the notice
remains in the executable version.
*/

/*#define	D(f)	f*/
/*#define	dprintf	printf*/
#define	D(f)

#include	"Park.h"

char DefaultName[] = "HardFrame.device";
char *DeviceName;

struct MsgPort IORP = {
	{0L, 0L, NT_MSGPORT, 0, 0L}, 0, SIGB_SINGLE, 0,
	{0, 0, 0, 0, 0}
};

struct IOStdReq IOR = {
	{ {0L, 0L, NT_MESSAGE, 0, 0L}, /* Message Succ, Pred, Type, Pri, Name */
	&IORP, 0 },			/* Message ReplyPort, Length */
	0, 0, 0, 0, 0,		/* IO Device, Unit, Command, Flags, Error */
	0L, 0L, 0L, 0L		/* IO Actual, Length, Data, Offset */
};

struct SCSICmd SC;

UBYTE SCCmd[10];

extern struct ExecBase *SysBase;


int
PromptedNumber(query, result)
char *query;
int result;
{
	char Data[81];

    printf(query, result);
    gets(Data);
    sscanf(Data, "%d", &result);
    return(result);
}

void
EndGame(code, format, arg1, arg2)
int code;
char *format, *arg1, *arg2;
{
	D(dprintf( "EndGame\n"));
	if (code != 0) {
		printf(format, arg1, arg2);
	}
	if (IOR.io_Device != 0) {
		D(dprintf("CloseDevice\n"));
		CloseDevice((struct IORequest *) &IOR);
	}
	exit(code);
}


int
main(argc, argv)
int argc;
char *argv[];
{
	struct Library *mbhf;
	int  unit, board, scsiID, scsiLUN;
	BOOL unpark;
	int result;

	printf( "	Microbotics HardFrame Park Utility Example\n");
	printf( "	           Version 1.0.\n" );
	printf( "	    Copyright © 1988 Wizardess Designs\n\n");

	unit = 0; /* For default. */
	if (( argc == 2 ) && ( argv[1][0] == '?' )) {
		printf( "usage: park UNIT [Device Name]\n" );
		exit ( 0 ); /* No unit number given. */
		}

	if ( argc < 2 ) {
		unit = PromptedNumber("Enter unit to park [%ld]: ", unit);
	}
	else {
		result = stcd_i( argv[1], &unit );
	}

	if (unpark = (unit > 999 )) unit -= 1000;

	if ( argc > 2 )
		DeviceName = argv[2];
	else
		DeviceName = DefaultName;
	
	/* Find the name in the device list if it is there. */
	mbhf = (struct Library *)
		FindName(&SysBase->DeviceList, DeviceName);
	if (mbhf == 0) {
		EndGame(20, "%s not found\n", DeviceName);
	}
	printf("%s release %ld.%ld\n", DeviceName,
		mbhf->lib_Version, mbhf->lib_Revision);

	/* finish IORP initialization */
	IORP.mp_SigTask = (struct Task *) FindTask(NULL);
	NewList(&IORP.mp_MsgList);

	board = unit/100;
	scsiLUN = (unit%100)/10;
	scsiID = unit%10;

	result = OpenDevice(DeviceName, unit, (struct IORequest *) &IOR, 0);
	if ( result ) {
		EndGame( 20, "%s will not Open. Likely %d is an invalid unit.",
				 DeviceName, unit );
		}

	if (unpark) printf( "Unp" );
	else printf( "P");
	printf( "arking board %d, ID %d, LUN %d.\n", board,
		 scsiID, scsiLUN );
	SC.scsi_Data = NULL;
	SC.scsi_Length = 0;
	SC.scsi_Command = SCCmd;
	SC.scsi_CmdLength = 6;
	SC.scsi_Flags = 0;
	SCCmd[0] = 0x1b;	/* Park */
	SCCmd[1] = scsiLUN<<5;
	SCCmd[2] = 0;
	SCCmd[3] = 0;
	SCCmd[5] = 0;
	if (unpark)
		SCCmd[4] = 1;  /* Set to 1 to unpark... */
	else
		SCCmd[4] = 0;  /* Set to 0 to park... */
	IOR.io_Command = HD_SCSICMD;
	IOR.io_Length = sizeof(SC);
	IOR.io_Data = (APTR) &SC;
	if ((DoIO((struct IORequest *) &IOR) == 0) && (SC.scsi_Actual > 18)) {
			D(dprintf("IOE: %ld, Actual: %ld, %08lx\n",
			  IOR.io_Error, SC.scsi_Actual));
	}
	CloseDevice((struct IORequest *) &IOR);
	IOR.io_Device = 0;
	EndGame(0);
return(0); /* Stop compiler squawk. */
}
