/* * SCSI_Direct.c * * The following program demonstrates the use of the HD_SCSICmd to send a * MODE SENSE to a unit on the requested device (default scsi.device). This * code can be easily modified to send other commands to the drive. * * Compile with SAS C 5.10 lc -b1 -cfistq -v -y -L * * Run from CLI only */ #include <exec/types.h> #include <exec/memory.h> #include <exec/io.h> #include <devices/scsidisk.h> #include <dos/dosextens.h> #include <clib/exec_protos.h> #include <clib/alib_protos.h> #include <stdlib.h> #include <stdio.h> #ifdef LATTICE int CXBRK(void) { return(0); } /* Disable SAS CTRL/C handling */ int chkabort(void) { return(0); } /* really */ #endif #define BUFSIZE 256 UBYTE *buffer; /* a data buffer used for mode sense data */ struct IOStdReq SCSIReq; /* a standard IORequest structure */ struct SCSICmd Cmd; /* where the actual SCSI command goes */ UBYTE Sense[20]; /* buffer for request sense data */ struct MsgPort Port; /* our ReplyPort */ void ShowSenseData(void); static UBYTE TestReady[] = { 0,0,0,0,0,0 }; /* not used but here for */ static UBYTE StartUnit[] = { 0x1b,0,0,0,1,0 }; /* illustration of other */ static UBYTE StopUnit[] = { 0x1b,0,0,0,0,0 }; /* commands. */ static UBYTE ModeSense[]={ 0x1a,0,0xff,0,254,0 }; /* the command being sent */ void main(int argc, char **argv) { int unit,tval,i; char *dname = "scsi.device"; UBYTE *tbuf; if ((argc < 2) || (argc > 3)) { printf("Usage: %s unit [xxxx.device]\n",argv[0]); exit(100); } unit = atoi( argv[1] ); if (argc == 3) dname = argv[2]; buffer = (UBYTE *) AllocMem(BUFSIZE, MEMF_PUBLIC|MEMF_CLEAR); if (!buffer) { printf("Couldn't get memory\n"); exit(100); } Port.mp_Node.ln_Pri = 0; /* setup the ReplyPort */ Port.mp_SigBit = AllocSignal(-1); Port.mp_SigTask = (struct Task *)FindTask(0); NewList( &(Port.mp_MsgList) ); SCSIReq.io_Message.mn_ReplyPort = &Port; if (OpenDevice( dname, unit, &SCSIReq, 0)) { printf("Couldn't open unit %ld on %s\n",unit,dname); FreeMem( buffer,BUFSIZE ); exit(100); } SCSIReq.io_Length = sizeof(struct SCSICmd); SCSIReq.io_Data = (APTR)&Cmd; SCSIReq.io_Command = HD_SCSICMD; /* the command we are sending */ Cmd.scsi_Data = (UWORD *)buffer; /* where we put mode sense data */ Cmd.scsi_Length = 254; /* how much we will accept */ Cmd.scsi_CmdLength = 6; /* length of the command */ Cmd.scsi_Flags = SCSIF_AUTOSENSE|SCSIF_READ; /* do automatic REQUEST_SENSE */ /* set expected data direction */ Cmd.scsi_SenseData =(UBYTE *)Sense; /* where sense data will go */ Cmd.scsi_SenseLength = 18; /* how much we will accept */ Cmd.scsi_SenseActual = 0; /* how much has been received */ Cmd.scsi_Command=(UBYTE *)ModeSense;/* issuing a MODE_SENSE command */ DoIO( &SCSIReq ); /* send it to the device driver */ if (Cmd.scsi_Status) ShowSenseData(); /* if bad status then show it */ else { printf("\nBlock descriptor header\n"); printf("=======================\n"); printf("Mode Sense data length = %d\n",(short)buffer[0]); printf("Block descriptor length = %d\n",(short)buffer[3]); tbuf = &buffer[4]; printf("Density code = %d\n",(short)tbuf[0]); tval = (tbuf[1]<<16) + (tbuf[2]<<8) + tbuf[3]; printf("Number of blocks = %ld\n",tval); tval = (tbuf[5]<<16) + (tbuf[6]<<8) + tbuf[7]; printf("Block size = %ld\n",tval); tbuf += buffer[3]; /* move to page descriptors */ while ((tbuf - buffer) < buffer[0]) { switch (tbuf[0] & 0x7f) { case 1: printf("\nError Recovery Parameters\n"); printf("=========================\n"); printf("Page length = %d\n",(short)tbuf[1]); printf("DISABLE CORRECTION = %d\n",(short)tbuf[2]&1); printf("DISABLE XFER ON ERROR = %d\n",(short)(tbuf[2]>>1)&1); printf("POST ERROR = %d\n",(short)(tbuf[2]>>2)&1); printf("ENABLE EARLY CORRECTION = %d\n",(short)(tbuf[2]>>3)&1); printf("READ CONTINUOUS = %d\n",(short)(tbuf[2]>>4)&1); printf("TRANSFER BLOCK = %d\n",(short)(tbuf[2]>>5)&1); printf("AUTO READ REALLOCATION = %d\n",(short)(tbuf[2]>>6)&1); printf("AUTO WRITE REALLOCATION = %d\n",(short)(tbuf[2]>>7)&1); printf("Retry count = %d\n",(short)tbuf[3]); printf("Correction span = %d\n",(short)tbuf[4]); printf("Head offset count = %d\n",(short)tbuf[5]); printf("Data strobe offset count= %d\n",(short)tbuf[6]); printf("Recovery time limit = %d\n",(short)tbuf[7]); tbuf += tbuf[1]+2; break; case 2: printf("\nDisconnect/Reconnect Control\n"); printf("============================\n"); printf("Page length = %d\n",(short)tbuf[1]); printf("Buffer full ratio = %d\n",(short)tbuf[2]); printf("Buffer empty ratio = %d\n",(short)tbuf[3]); tval = (tbuf[4]<<8)+tbuf[5]; printf("Bus inactivity limit = %d\n",tval); tval = (tbuf[6]<<8)+tbuf[7]; printf("Disconnect time limit = %d\n",tval); tval = (tbuf[8]<<8)+tbuf[9]; printf("Connect time limit = %d\n",tval); tval = (tbuf[10]<<8)+tbuf[11]; printf("Maximum burst size = %d\n",tval); printf("Disable disconnection = %d\n",(short)tbuf[12]&1); tbuf += tbuf[1]+2; break; case 3: printf("\nDevice Format Parameters\n"); printf("========================\n"); printf("Page length = %d\n",(short)tbuf[1]); tval = (tbuf[2]<<8)+tbuf[3]; printf("Tracks per zone = %d\n",tval); tval = (tbuf[4]<<8)+tbuf[5]; printf("Alternate sectors/zone = %d\n",tval); tval = (tbuf[6]<<8)+tbuf[7]; printf("Alternate tracks/zone = %d\n",tval); tval = (tbuf[8]<<8)+tbuf[9]; printf("Alternate tracks/volume = %d\n",tval); tval = (tbuf[10]<<8)+tbuf[11]; printf("Sectors per track = %d\n",tval); tval = (tbuf[12]<<8)+tbuf[13]; printf("Bytes per sector = %d\n",tval); tval = (tbuf[14]<<8)+tbuf[15]; printf("Interleave = %d\n",tval); tval = (tbuf[16]<<8)+tbuf[17]; printf("Track skew factor = %d\n",tval); tval = (tbuf[18]<<8)+tbuf[19]; printf("Cylinder skew factor = %d\n",tval); tbuf += tbuf[1]+2; break; case 4: printf("\nDrive Geometry Parameters\n"); printf("=========================\n"); printf("Page length = %d\n",(short)tbuf[1]); tval = (tbuf[2]<<16)+(tbuf[3]<<8)+tbuf[4]; printf("Number of cylinders = %ld\n",tval); printf("Number of heads = %d\n",(short)tbuf[5]); tval = (tbuf[6]<<16)+(tbuf[6]<<8)+tbuf[8]; printf("Start write precomp = %ld\n",tval); tval = (tbuf[9]<<16)+(tbuf[10]<<8)+tbuf[11]; printf("Start reduced write = %ld\n",tval); tval = (tbuf[12]<<8)+tbuf[13]; printf("Drive step rate = %d\n",tval); tval = (tbuf[14]<<16)+(tbuf[15]<<8)+tbuf[16]; printf("Landing zone cylinder = %ld\n",tval); tbuf += tbuf[1]+2; break; default: printf("\nVendor Unique Page Code %2x\n",(short)tbuf[0]); printf("==========================\n"); for (i=0; i<=tbuf[1]+1; i++ ) printf("%x ",(short)tbuf[i]); printf("\n"); tbuf += tbuf[1]+2; } } } CloseDevice( &SCSIReq ); FreeMem( buffer, BUFSIZE ); FreeSignal(Port.mp_SigBit); } void ShowSenseData(void) { int i; for (i=0; i<18; i++) printf("%x ",(int)Sense[i]); printf("\n"); }