

/*  SCSIinfo.c   

	Interactive Video Systems, 1990


    This program demonstrates how to communicate with a the
 Trumpcard's SCSI device using Commodore's recomended SCSI call
 format.


 */


#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/memory.h"
#include "exec/interrupts.h"
#include "exec/ports.h"
#include "exec/libraries.h"
#include "exec/io.h"
#include "exec/tasks.h"
#include "exec/execbase.h"
#include "exec/devices.h"

#include "devices/scsidisk.h"
#include "devices/trackdisk.h"





/* name of the device driver...

 "IVS_SCSI.device"	for standard Trumpcard
 "IVS_SCSIpro.device"	for Trumpcard Professional"

 */

#define SCSI_DEVICE_NAME "IVS_SCSIpro.device"





struct MsgPort *diskport;
struct IOExtTD *diskreq;
BYTE diskbuffer[512];
BYTE *diskdata;
int i;

UBYTE	Cmd_Buf[20];

struct SCSICmd SCSIcmd;


extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();





/* read the drive's capacity in blocks... */

void Read_Capacity()
{


/* command string to send the drive... refer to your drive manual and/or 
   the ANSI SCSI specification */

static UBYTE Capacity_Cmd[] = {0x25,0,0,0,0,0,0,0,0,0};

/* structure to hold the data returned from the drive */
static UBYTE Disk_Data[50];

ULONG Cap;

	SCSIcmd.scsi_CmdLength	= 10;  		/* bytes in command */
	SCSIcmd.scsi_Command    = (UBYTE *)&Capacity_Cmd;
	SCSIcmd.scsi_Length	= 8;   		/* return bytes expected */
	SCSIcmd.scsi_Data	= (UWORD *)&Disk_Data;
	SCSIcmd.scsi_Flags	= 1;

	diskreq->iotd_Req.io_Data    = (APTR)&SCSIcmd;
	diskreq->iotd_Req.io_Command = HD_SCSICMD;

	DoIO(diskreq);
  
 	Cap=(Disk_Data[0]<<24)|(Disk_Data[1]<<16)|(Disk_Data[2]<<8)|(Disk_Data[3]);

	printf("Blocks On Drive...........%d\n\n",Cap);

	/* for testing... */
	/* for(i=0;i<=9;i++) printf("%d\n",Disk_Data[i]); */

} /* end Read_Capacity */





/* Inquire about various parameters... */

void Inquiry()
{

static UBYTE Inquiry_Cmd[] = {0x12,0,0,0,49,0};
static UBYTE Disk_Data[50];

	SCSIcmd.scsi_CmdLength	= 6;  		/* bytes in command */
	SCSIcmd.scsi_Command    = (UBYTE *)&Inquiry_Cmd;
	SCSIcmd.scsi_Length	= 49;   	/* return bytes expected */
	SCSIcmd.scsi_Data	= (UWORD *)&Disk_Data;
	SCSIcmd.scsi_Flags	= 1;

	diskreq->iotd_Req.io_Data    = (APTR)&SCSIcmd;
	diskreq->iotd_Req.io_Command = HD_SCSICMD;

	DoIO(diskreq);
  
  
    if (SCSIcmd.scsi_Status == 0) {
	printf("Device Type Code..........%d\n",Disk_Data[0]);   
	printf("Device Type Qualifier.....%d\n",Disk_Data[1]);
	printf("Revision Level............%d\n",Disk_Data[2]);
	printf("Response Type SRD.........%d\n",Disk_Data[3]);
	printf("Additional Length.........%d\n",Disk_Data[4]);

	printf("Manufacturer Name..........");
	   for (i=8;i<16;i++) printf("%c",Disk_Data[i]);
	   printf("\n");
	printf("Product Name..............");
	   for (i=16;i<32;i++) printf("%c",Disk_Data[i]);
	   printf("\n");
	
	printf("Rev Level.......[32-35]...[%d,%d,%d,%d] in ASCII ->[",
	       Disk_Data[32],Disk_Data[33],Disk_Data[34],Disk_Data[35]);
	       for (i=32;i<36;i++) printf("%c", 
		   ((Disk_Data[i]>31)&&(Disk_Data[i]<128))? Disk_Data[i]:32);
	       printf("]\n");

	printf("# of Extents..............%d\n",Disk_Data[36]*256+Disk_Data[37]);
	printf("Group 0 Commands..........%d\n",Disk_Data[38]);
	printf("Commands ( 0- 7)..........%d\n",Disk_Data[39]);
	printf("Commands ( 8- F)..........%d\n",Disk_Data[40]);
	printf("Commands (10-17)..........%d\n",Disk_Data[41]);
	printf("Commands (18-1F)..........%d\n",Disk_Data[42]);
	printf("Group 1 Commands..........%d\n",Disk_Data[43]);
	printf("Commands (20-27)..........%d\n",Disk_Data[44]);
	printf("Commands (28-2F)..........%d\n",Disk_Data[45]);
	printf("Commands (30-37)..........%d\n",Disk_Data[46]);
	printf("Commands (38-3F)..........%d\n",Disk_Data[47]);
	printf("End of List...............%d\n",Disk_Data[48]);
       }

} /* end Inquiry */




/* Retrieve pages of data from the drive... */

void Mode_Sense()
{

static UBYTE Sense_0[] = {0x1A,0,0,0,16,0};
static UBYTE Page0[20];

static UBYTE Sense_3[] = {0x1A,0,3,0,36,0};
static UBYTE Page3[40];

static UBYTE Sense_4[] = {0x1A,0,4,0,30,0};
static UBYTE Page4[40];


    /*********** Get Page 0 ***********/

	SCSIcmd.scsi_CmdLength	= 6;  
	SCSIcmd.scsi_Command    = (UBYTE *)&Sense_0;
	SCSIcmd.scsi_Length	= 16; 
	SCSIcmd.scsi_Data	= (UWORD *)&Page0;
	SCSIcmd.scsi_Flags	= 1;

	diskreq->iotd_Req.io_Data    = (APTR)&SCSIcmd;
	diskreq->iotd_Req.io_Command = HD_SCSICMD;

	DoIO(diskreq);

	/* HexDump(&Page0,16); */
    
    /*********** Get Page 3 ***********/


	SCSIcmd.scsi_CmdLength	= 6;  
	SCSIcmd.scsi_Command    = (UBYTE *)&Sense_3;
	SCSIcmd.scsi_Length	= 36; 
	SCSIcmd.scsi_Data	= (UWORD *)&Page3;
	SCSIcmd.scsi_Flags	= 1;

	diskreq->iotd_Req.io_Data    = (APTR)&SCSIcmd;
	diskreq->iotd_Req.io_Command = HD_SCSICMD;

	DoIO(diskreq);


	/* HexDump(&Page3,36); */
  
 
    /*********** Get Page 4 ***********/


	SCSIcmd.scsi_CmdLength	= 6;  
	SCSIcmd.scsi_Command    = (UBYTE *)&Sense_4;
	SCSIcmd.scsi_Length	= 30; 
	SCSIcmd.scsi_Data	= (UWORD *)&Page4;
	SCSIcmd.scsi_Flags	= 1;

	diskreq->iotd_Req.io_Data    = (APTR)&SCSIcmd;
	diskreq->iotd_Req.io_Command = HD_SCSICMD;

	DoIO(diskreq);


	/* HexDump(&Page4,30); */
  

        printf("Number of Cylinders.......%d\n",Page4[15]*256+Page4[16]);
	printf("Number of Heads...........%d\n",Page4[17]);
	printf("Sectors per Track.........%d\n",Page3[23]);
	printf("Data bytes per sector.....%d\n",Page3[24]*256+Page3[25]);
	printf("Interleave................%d\n",Page3[27]);

	printf("\n");

} /* end ModeSense */
	



/* 
   Most SCSI drives are self parking--
   but here's the commands anyway. 

 */

void UnPark()
{



/* this is the start/stop unit command... 1 = start */
static UBYTE UnPark_Cmd[] = {0x1B,0,0,0,1,0};
static UBYTE Disk_Data[50];

	SCSIcmd.scsi_CmdLength	= 6;  /* bytes in command */
	SCSIcmd.scsi_Command    = (UBYTE *)&UnPark_Cmd;
	SCSIcmd.scsi_Length	= 0;   /* return bytes expected */
	SCSIcmd.scsi_Data	= (UWORD *)&Disk_Data;
	SCSIcmd.scsi_Flags	= 1;

	diskreq->iotd_Req.io_Data    = (APTR)&SCSIcmd;
	diskreq->iotd_Req.io_Command = HD_SCSICMD;

	DoIO(diskreq);
  


} /* end UnPark */





void Park()
{


/* start/stop unit command... 0 = stop */
static UBYTE Park_Cmd[] = {0x1B,0,0,0,0,0};
static UBYTE Disk_Data[50];

	SCSIcmd.scsi_CmdLength	= 6;  /* bytes in command */
	SCSIcmd.scsi_Command    = (UBYTE *)&Park_Cmd;
	SCSIcmd.scsi_Length	= 0;   /* return bytes expected */
	SCSIcmd.scsi_Data	= (UWORD *)&Disk_Data;
	SCSIcmd.scsi_Flags	= 1;

	diskreq->iotd_Req.io_Data    = (APTR)&SCSIcmd;
	diskreq->iotd_Req.io_Command = HD_SCSICMD;

	DoIO(diskreq);
  


} /* end Park */




/* to look at raw data */
void HexDump(P,L)
UBYTE *P;
int L;
{
int i;

	printf("\n");
	for (i=0;i<L;i++) printf("%2X ",P[i]);
	printf("\n");

} /* end HexDump */







main()
{
    SHORT error;
    int devicenum;

	diskdata = &diskbuffer[0];

	diskport = CreatePort(0,0);
	if(diskport==0) exit(100);
	
	diskreq = (struct IOExtTD *)CreateExtIO(diskport,
					  	sizeof(struct IOExtTD));
	/* can we open a port? */
	if (diskreq == 0) { DeletePort(diskport); exit(200); }

	printf("Enter Device # ->");
	scanf("%d",&devicenum);

	/* is device there? */
        error = OpenDevice(SCSI_DEVICE_NAME,devicenum,diskreq,0);

	/* failed?? */
	if (error !=0) {printf("\n Error %d During Open\n",error);
		 	 DeleteExtIO(diskreq,sizeof(struct IOExtTD));
			 DeletePort(diskport);
			 exit(100); }


	/* all systems go! */

	Read_Capacity(); 
	Inquiry(); 
	Mode_Sense();


	CloseDevice(diskreq);

	DeleteExtIO(diskreq,sizeof(struct IOExtTD));
	DeletePort(diskport);

} /* end main */ 



