home *** CD-ROM | disk | FTP | other *** search
- /*
- ***** SCSIutil
- *
- * A utility to do some low-level operations to a SCSI disk, e.g.
- *
- * - start/stop motor
- * - read sectors
- * - read disk capacity info
- * - get inquiry info (manufacturers name etc)
- * - seek to a sector's cylinder (use to park heads)
- *
- * NOTE: this program is based on SCSI information taken from
- * the accompanying documentation of a NEC D3841 SCSI disk.
- * I don't know the extent to which SCSI standards are
- * supported by that disk.
- *
- * These commands work on the above disk. But a seek to
- * sector -1 (park on the NEC disk) fails on my Quantum 105.D
- *
- ***** Written by Gary Duncan
- *
- * Bug reports etc via e-mail to gduncan@philips.oz.au) , or mail to
- *
- * Gary Duncan
- * Philips PTS
- * 23 Lakeside Dr
- * Tally-Ho Technology Park
- * Burwood East Vic 3151
- * Australia
- *
- *
- ***** Freely distributable for non-commercial purposes
- *
- * Complies under Lattice 5.10
- * - needs AmigaDosA 2.0 #includes
- *
- ***** Thanks to Markus Illenseer for some beta-testing.
- *
- ***** Function List :-
- *
- * motor ()
- * read_sec ()
- * init ()
- * seek ()
- * inquiry()
- * read_capacity()
- * gcomp()
- * GetDevName()
- * breakcheck()
- * chkabort()
- * err_str()
- * usage()
- * sense_errs()
- *
- */
-
- #define VERSION "1.1"
-
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <exec/types.h>
- #include <exec/io.h>
- #include <exec/execbase.h>
- #include <exec/nodes.h>
- #include <exec/memory.h>
- #include <devices/trackdisk.h>
- #include <devices/scsidisk.h>
- #include <libraries/dos.h>
- #include "scsi_priv.h"
-
- #define BYTES_PER_LINE 16
- #define SENSE_LEN 252
- #define MAX_DATA_LEN 252
- #define PAD 0
- #define LINE_BUF (128)
-
- #define OFFS_KEY 2
- #define OFFS_CODE 12
-
- /*
- * we open ( if no -d option) the first *scsi*.device in the device list.
- */
- #define SCSI_STRING "scsi"
-
- typedef struct MsgPort MSGPORT;
- typedef struct IOStdReq IOSTDREQ;
- typedef struct List LIST;
- typedef struct Node NODE;
- typedef struct SCSICmd SCSICMD;
-
- #undef FALSE
- #undef TRUE
- typedef enum
- {
- FALSE = 0, TRUE
- } BOOLEAN;
-
- UBYTE *ip_buf = NULL;
- UBYTE *scsi_data = NULL;
- UBYTE *scsi_sense = NULL;
- UBYTE *dev = "";
- MSGPORT *mp_ptr = NULL;
- IOSTDREQ *io_ptr = NULL;
- SCSICMD scsi_cmd;
- int scsi_id = -1;
- int on_off = -1;
- UBYTE *pname;
- UBYTE buffer[LINE_BUF];
- int secno = -1;
- /*
- * function decs
- */
- void usage ();
- void motor ();
- void read_capacity ();
- void read_sec ();
- void read_sec_scsi ();
- void inquiry ();
- void seek ();
- UBYTE *sense_errs ();
- UBYTE *GetDevName ();
- BOOLEAN init ();
- UBYTE *err_str ();
-
-
- /*********************************************************************
- *
- * main
- *
- *
- */
-
- main (argc, argv)
-
- int argc;
- char **argv;
- {
- UBYTE *p;
- int j = 0;
-
- /*
- * see if a SCSI.device specified
- */
- if (strncmp (argv[1], "-d", 2) == 0)
- {
- j = 1;
- dev = argv[1] + 2;
- }
- else if ((dev = GetDevName (SCSI_STRING)) == NULL)
- {
- usage ("Error : no *scsi*.device in device list\n");
- exit (1);
- }
- pname = argv[0];
- if (argc < (j + 2))
- {
- usage (""); /* help inquiry */
- exit (1);
- }
-
- if (argc < (j + 3))
- {
- usage ("Error : Not enough params\n");
- exit (1);
- }
- if (*(p = argv[j + 2]) != '-')
- {
- usage ("Error : bad option\n"); /* help inquiry */
- exit (1);
- }
-
- /*
- * pick up SCSI id ; do a rough check
- */
- sscanf (argv[j + 1], "%d", &scsi_id);
- if (scsi_id < 0)
- {
- usage ("Error : Bad scsi id\n");
- exit (1);
- }
-
-
- /*
- * now set up structures etc for SCSI xfer
- */
- if (init () == FALSE)
- goto error;
-
- /*
- ********************** now examine the options
- */
- switch (*++p)
- {
- /*
- **** read capacity
- */
- case 'c':
- read_capacity ();
- break;
-
- /*
- **** inquiry
- */
- case 'i':
- inquiry ();
- break;
-
- /*
- **** read sectors
- */
- case 'R':
- if (argc != (j + 4))
- {
- usage ("Error : bad param count\n");
- exit (1);
- }
- /*
- * get sector #
- */
- if (sscanf (argv[j + 3], "%d", &secno) != 1)
- {
- usage ("Error : Bad sec no\n");
- exit (1);
- }
-
- read_sec ();
- break;
-
- case 'r':
- if (argc != (j + 4))
- {
- usage ("Error : bad param count\n");
- exit (1);
- }
- /*
- * get sector #
- */
- if (sscanf (argv[j + 3], "%d", &secno) != 1)
- {
- usage ("Error : Bad sec no\n");
- exit (1);
- }
-
- read_sec_scsi ();
- break;
-
- /*
- **** seek to cylinder containing secno
- */
- case 's':
- if (argc != (j + 4))
- {
- usage ("Error : bad param count\n");
- exit (1);
- }
- /*
- * get sector #
- */
- if (sscanf (argv[j + 3], "%d", &secno) != 1)
- {
- usage ("Error : Bad sec no\n");
- exit (1);
- }
-
- seek ();
- break;
-
- /*
- **** fill sector with a byte
- */
- case 'f':
- if (argc != (j + 5))
- {
- usage ("Error : bad param count\n");
- exit (1);
- }
-
- /*
- * get sector #
- */
- sscanf (argv[j + 3], "%d", &secno);
- if (secno == -1)
- {
- usage ("Error : Bad sec no\n");
- exit (1);
- }
- break;
-
- /*
- **** stop/start motor
- */
- case 'm':
- if (argc != (j + 4))
- {
- usage ("Error : bad param count\n");
- exit (1);
- }
- sscanf (argv[j + 3], "%d", &on_off);
- if ((on_off == -1) || ((on_off != 0) && (on_off != 1)))
- {
- usage ("Error : motor control must be 0 or 1\n");
- exit (1);
- }
-
- motor ();
- break;
-
- default:
- usage ("Error : bad option\n"); /* help inquiry */
- exit (1);
- }
-
- error:
-
- if (io_ptr)
- {
- CloseDevice ((IOSTDREQ *) io_ptr);
- DeleteStdIO (io_ptr);
- }
-
- if (mp_ptr)
- DeletePort (mp_ptr);
-
- if (ip_buf)
- FreeMem (ip_buf, TD_SECTOR);
-
- if (scsi_data)
- FreeMem (scsi_data, MAX_DATA_LEN);
-
- if (scsi_sense)
- FreeMem (scsi_sense, SENSE_LEN);
-
- }
-
- /*********************************************************************
- *
- * Initialisation function
- *
- *
- */
- BOOLEAN
- init ()
- {
- if ((scsi_data = (UBYTE *) AllocMem (MAX_DATA_LEN, MEMF_CHIP | MEMF_CLEAR)) == NULL)
- {
- fprintf (stderr, "AllocMem(0) Fail\n");
- return FALSE;
- }
-
- if ((scsi_sense = (UBYTE *) AllocMem (SENSE_LEN, MEMF_CHIP || MEMF_CLEAR)) == NULL)
- {
- fprintf (stderr, "AllocMem(1) Fail\n");
- return FALSE;
- }
-
- if ((ip_buf = (UBYTE *) AllocMem (TD_SECTOR, MEMF_CHIP)) == NULL)
- {
- fprintf (stderr, "AllocMem(2) Fail\n");
- return FALSE;
- }
-
- if ((mp_ptr = (MSGPORT *) CreatePort (NULL, 0)) == NULL)
- {
- fprintf (stderr, "CreatePort Fail\n");
- return FALSE;
- }
-
- if ((io_ptr = (IOSTDREQ *) CreateStdIO (mp_ptr)) == NULL)
- {
- fprintf (stderr, "CreateStdIO Fail\n");
- return FALSE;
- }
-
- if (OpenDevice (dev, scsi_id, io_ptr, 0) != 0)
- {
- fprintf (stderr,
- "Error %d while opening SCSI dev \"%s\", unit (%d)\n",
- io_ptr->io_Error, dev, scsi_id);
-
- return FALSE;
- }
-
- return TRUE;
- }
-
- /*********************************************************************
- *
- * function to read sectors from a starting sector #
- * - similar adjacent lines are suppressed on printout.
- *
- * - uses trackdisk.device
- */
-
- void
- read_sec ()
-
- {
- UBYTE *sec_click_ptr; /* click = 16 bytes */
- UBYTE *pref;
- UBYTE *p;
- UWORD j;
- UWORD k;
- int err;
-
- /*
- * keep printing sectors until ^C , or until error
- */
- io_ptr->io_Command = CMD_READ;
- io_ptr->io_Length = TD_SECTOR;
- io_ptr->io_Data = (APTR) ip_buf;
- io_ptr->io_Offset = secno * TD_SECTOR; /* will be updated... */
-
-
- /*
- * keep reading sectors : stop on ^C on bad sector #
- */
- for (;; ++secno)
- {
- UBYTE *ss;
- UWORD m_sec_offs;
-
- if (breakcheck ()) /* ^C ? */
- break;
-
- io_ptr->io_Offset = secno * TD_SECTOR; /* sector offset */
-
- DoIO ((IOSTDREQ *) io_ptr);
- if ((err = io_ptr->io_Error) == 0)
- {
- printf ("\n");
- /*
- * scan this sector ...
- */
- for (sec_click_ptr = pref = ip_buf, m_sec_offs = 0;
- m_sec_offs < TD_SECTOR;
- m_sec_offs += BYTES_PER_LINE, sec_click_ptr += BYTES_PER_LINE)
- {
- int xxxlen = strlen (" xx"); /* byte */
-
- if (breakcheck ())
- break;
- /*
- * don't print line if same contents as previous
- */
- if (gcomp (sec_click_ptr, pref, BYTES_PER_LINE) == TRUE)
- {
- if (m_sec_offs > 1)
- continue; /* same */
- }
- (void) setmem (buffer, sizeof (buffer), ' '); /* put spaces in buffer */
-
- sprintf (buffer, "%05X:%03X = ", secno, m_sec_offs);
-
- /* set up for loop */
-
- k = strlen (buffer);
- ss = buffer + k;
- k += (BYTES_PER_LINE * xxxlen) + 1;
- for (p = sec_click_ptr, j = 0;
- j < BYTES_PER_LINE;
- ss += xxxlen, ++j, ++k)
- {
- UBYTE dd = *p++;
- UBYTE que = (isascii (dd) && isprint (dd)) ? dd : '.';
- sprintf (ss, " %02X", dd); /* 2 hex charas */
- buffer[k] = que;
- }
-
- buffer[strlen (buffer)] = ' ';
- buffer[k++] = '\n';
- buffer[k++] = '\0';
-
- printf ("%s", buffer);
- pref = sec_click_ptr;
-
- }
- }
- else
- {
- /* else DoIO error */
-
- fprintf (stderr, "Error : sec = %ld dec , $%lX , [%s]\n",
- secno, secno, sense_errs (err));
-
- return;
- }
- }
- }
-
- /*********************************************************************
- *
- * function to read sectors from a starting sector #
- * - similar adjacent lines are suppressed on printout.
- *
- * - uses scsi device directly
- */
-
- void
- read_sec_scsi ()
-
- {
- static struct CMD_XREAD
- {
- UBYTE cmd;
- UBYTE lba[3];
- UBYTE numb_secs;
- UBYTE pad;
- } command =
- {
- SCSI_CMD_RD,
- 0, 0, 0,
- 0,
- PAD
- };
-
- UBYTE *sec_click_ptr; /* click = 16 bytes */
- UBYTE *pref;
- UBYTE *p;
- UWORD j;
- UWORD k;
- int err;
-
- /*
- * keep printing sectors until ^C , or until error
- */
-
-
- io_ptr->io_Command = HD_SCSICMD;
- io_ptr->io_Length = sizeof (SCSICMD);
- io_ptr->io_Data = (APTR) & scsi_cmd;
-
- scsi_cmd.scsi_Command = (UBYTE *) & command;
- scsi_cmd.scsi_CmdLength = sizeof (command);
- scsi_cmd.scsi_Flags = SCSIF_READ | SCSIF_AUTOSENSE;
- scsi_cmd.scsi_Data = (APTR) ip_buf;
- scsi_cmd.scsi_Length = 512;
- scsi_cmd.scsi_SenseData = scsi_sense;
- scsi_cmd.scsi_SenseLength = SENSE_LEN;
-
- /*
- * keep reading sectors : stop on ^C on bad sector #
- */
- for (;; ++secno)
- {
- UBYTE *ss;
- UWORD m_sec_offs;
-
- command.lba[2] = secno;
- command.lba[1] = secno >> 8;
- command.lba[0] = (secno >> 8) & 0x1F;
-
- command.numb_secs = 1;
-
- if (breakcheck ()) /* ^C ? */
- break;
-
- io_ptr->io_Offset = secno * TD_SECTOR; /* sector offset */
-
- DoIO ((IOSTDREQ *) io_ptr);
- if ((err = io_ptr->io_Error) == 0)
- {
- printf ("\n");
- /*
- * scan this sector ...
- */
- for (sec_click_ptr = pref = ip_buf, m_sec_offs = 0;
- m_sec_offs < TD_SECTOR;
- m_sec_offs += BYTES_PER_LINE, sec_click_ptr += BYTES_PER_LINE)
- {
- int xxxlen = strlen (" xx"); /* byte */
-
- if (breakcheck ())
- break;
- /*
- * don't print line if same contents as previous
- */
- if (gcomp (sec_click_ptr, pref, BYTES_PER_LINE) == TRUE)
- {
- if (m_sec_offs > 1)
- continue; /* same */
- }
- (void) setmem (buffer, sizeof (buffer), ' '); /* put spaces in buffer */
-
- sprintf (buffer, "%05X:%03X = ", secno, m_sec_offs);
-
- /* set up for loop */
-
- k = strlen (buffer);
- ss = buffer + k;
- k += (BYTES_PER_LINE * xxxlen) + 1;
- for (p = sec_click_ptr, j = 0;
- j < BYTES_PER_LINE;
- ss += xxxlen, ++j, ++k)
- {
- UBYTE dd = *p++;
- UBYTE que = (isascii (dd) && isprint (dd)) ? dd : '.';
- sprintf (ss, " %02X", dd); /* 2 hex charas */
- buffer[k] = que;
- }
-
- buffer[strlen (buffer)] = ' ';
- buffer[k++] = '\n';
- buffer[k++] = '\0';
-
- printf ("%s", buffer);
- pref = sec_click_ptr;
-
- }
- }
- else
- {
- /* else DoIO error */
-
- fprintf (stderr, "Error : sec = %ld dec , $%lX , [%s]\n",
- secno, secno, sense_errs (err));
- return;
- }
- }
- }
-
- /*********************************************************************
- *
- * function to stop/start motor on SCSI device
- *
- */
-
- void
- motor ()
-
- {
- static struct CMD_SSU
- {
- UBYTE cmd;
- UBYTE imm;
- UBYTE pad_a[2];
- UBYTE start_stop;
- UBYTE pad_b;
- } command =
- {
- SCSI_CMD_SSU,
- 0,
- PAD, PAD,
- 0,
- PAD
- };
-
- int err;
-
- command.start_stop = on_off;
-
- io_ptr->io_Command = HD_SCSICMD;
- io_ptr->io_Length = sizeof (SCSICMD);
- io_ptr->io_Data = (APTR) & scsi_cmd;
-
- scsi_cmd.scsi_Command = (UBYTE *) & command;
- scsi_cmd.scsi_CmdLength = sizeof (command);
- scsi_cmd.scsi_Flags = SCSIF_READ | SCSIF_AUTOSENSE;
- scsi_cmd.scsi_SenseData = scsi_sense;
- scsi_cmd.scsi_SenseLength = SENSE_LEN;
-
-
- (void) DoIO ((IOSTDREQ *) io_ptr);
- if ((err = io_ptr->io_Error) != 0)
- {
- fprintf (stderr, "Error : [%s]\n", sense_errs (err));
- }
- }
-
- /*********************************************************************
- *
- * function to seek to a cylinder
- *
- */
-
- void
- seek ()
-
- {
- static struct CMD_SEEK
- {
- UBYTE cmd;
- UBYTE pad_a;
- ULONG lba;
- UBYTE pad[4];
- } command =
- {
- SCSI_CMD_SKX,
- PAD,
- 0,
- PAD, PAD, PAD, PAD
- };
-
- int err;
- /*
- * load sector # (log block addr)
- */
-
- command.lba = secno;
-
- io_ptr->io_Command = HD_SCSICMD;
- io_ptr->io_Length = sizeof (SCSICMD);
- io_ptr->io_Data = (APTR) & scsi_cmd;
-
- scsi_cmd.scsi_Command = (UBYTE *) & command;
- scsi_cmd.scsi_CmdLength = sizeof (command);
- scsi_cmd.scsi_Flags = SCSIF_READ | SCSIF_AUTOSENSE;
- scsi_cmd.scsi_SenseData = scsi_sense;
- scsi_cmd.scsi_SenseLength = SENSE_LEN;
-
-
- (void) DoIO ((IOSTDREQ *) io_ptr);
- if ((err = io_ptr->io_Error) != 0)
- {
- fprintf (stderr, "Error : sec = %ld dec , $%lX , [%s]\n",
- secno, secno, sense_errs (err));
- }
- }
-
- /*********************************************************************
- *
- * function to make an inquiry
- *
- */
-
- void
- inquiry ()
- {
- static struct CMD_INQUIRY
- {
- UBYTE cmd;
- UBYTE pad_a[3];
- UBYTE len;
- UBYTE pad_b;
- } command =
- {
- SCSI_CMD_INQ,
- PAD, PAD, PAD,
- 0,
- PAD
- };
- UBYTE *sec_click_ptr; /* click = 16 bytes */
- UBYTE *p;
- UBYTE *ss;
- UWORD m_sec_offs;
- UWORD k;
- int err;
- int j;
-
- command.len = MAX_DATA_LEN;
-
- io_ptr->io_Command = HD_SCSICMD;
- io_ptr->io_Length = sizeof (struct SCSICmd);
- io_ptr->io_Data = (APTR) & scsi_cmd;
-
- scsi_cmd.scsi_Data = (UWORD *) scsi_data;
- scsi_cmd.scsi_Length = MAX_DATA_LEN;
- scsi_cmd.scsi_Command = (UBYTE *) & command;
- scsi_cmd.scsi_CmdLength = sizeof (command);
- scsi_cmd.scsi_Flags = SCSIF_READ | SCSIF_AUTOSENSE;
- scsi_cmd.scsi_SenseData = scsi_sense;
- scsi_cmd.scsi_SenseLength = SENSE_LEN;
-
-
- (void) DoIO ((IOSTDREQ *) io_ptr);
-
- if ((err = io_ptr->io_Error) == 0)
- {
- int rem = scsi_cmd.scsi_Actual;
-
- printf ("\n");
- /*
- * now print it out
- */
- for (sec_click_ptr = scsi_data, m_sec_offs = 0;
- ;
- m_sec_offs += BYTES_PER_LINE, sec_click_ptr += BYTES_PER_LINE)
- {
- int xxxlen = strlen (" xx"); /* byte */
-
- (void) setmem (buffer, sizeof (buffer), ' '); /* put spaces in buffer */
-
- sprintf (buffer, "%3X = ", m_sec_offs);
-
- /* set up for loop */
-
- k = strlen (buffer);
- ss = buffer + k;
- k += (BYTES_PER_LINE * xxxlen) + 1;
- for (p = sec_click_ptr, j = 0;
- j < BYTES_PER_LINE;
- ss += xxxlen, ++j)
- {
- UBYTE dd = *p++;
- UBYTE que = (isascii (dd) && isprint (dd)) ? dd : '.';
- sprintf (ss, " %02X", dd); /* 2 hex charas */
- buffer[k++] = que;
- if (--rem == 0)
- break;
- }
-
- buffer[strlen (buffer)] = ' ';
- buffer[k++] = '\n';
- buffer[k++] = '\0';
-
- printf ("%s", buffer);
- if (rem <= 0)
- return;
- }
- }
- else
- /* error */
- {
- fprintf (stderr, "Error : %s\n", sense_errs (err));
-
- }
- }
-
- /*********************************************************************
- *
- * function to read disk capacity
- *
- */
-
- void
- read_capacity ()
- {
- static struct CMD_READ_CAPACITY
- {
- UBYTE cmd;
- UBYTE pad_a;
- ULONG lba;
- UBYTE pad_b[2];
- UBYTE pmi;
- UBYTE pad_c;
- } command =
- {
- SCSI_CMD_RCP,
- PAD,
- 0, /* start from sec 0 */
- PAD, PAD,
- 0,
- PAD
- };
-
- int err;
-
- io_ptr->io_Command = HD_SCSICMD;
- io_ptr->io_Length = sizeof (struct SCSICmd);
- io_ptr->io_Data = (APTR) & scsi_cmd;
-
- scsi_cmd.scsi_Data = (UWORD *) scsi_data;
- scsi_cmd.scsi_Length = MAX_DATA_LEN;
- scsi_cmd.scsi_Command = (UBYTE *) & command;
- scsi_cmd.scsi_CmdLength = sizeof (command);
- scsi_cmd.scsi_Flags = SCSIF_READ | SCSIF_AUTOSENSE;
- scsi_cmd.scsi_SenseData = scsi_sense;
- scsi_cmd.scsi_SenseLength = SENSE_LEN;
-
-
- (void) DoIO ((IOSTDREQ *) io_ptr);
-
- if ((err = io_ptr->io_Error) == 0)
- {
- ULONG sec_no = *((ULONG *) & scsi_data[0]);
- ULONG sec_size = *((ULONG *) & scsi_data[4]);
-
- printf ("Max Sec = %6ld , sec size = %4ld (capacity = %6ld KB)\n",
- sec_no, sec_size, (sec_no * sec_size) / 1024);
- }
- else
- {
- fprintf (stderr, "Error : %s \n", sense_errs (err));
- }
- }
-
- /*********************************************************************
- *
- * function to compare two binary strings
- *
- * returns FALSE if different
- */
-
- int
- gcomp (p1, p2, len)
-
- char *p1;
- char *p2;
- int len;
- {
- while (len--)
- {
- if (*p1++ != *p2++)
- return (FALSE);
- }
- return (TRUE);
- }
-
- /*********************************************************************
- *
- * searches DeviceList for a device name with a given string in it.
- * - if found returns with a pointer to it, else NULL
- */
-
- extern struct ExecBase *SysBase;
-
- UBYTE *
- GetDevName (grep)
-
- char *grep;
- {
- LIST *lh = (LIST *) SysBase->DeviceList.lh_Head;
- NODE *ln;
-
- for (ln = lh->lh_Head; ln->ln_Succ; ln = ln->ln_Succ)
- {
- UBYTE *p = ln->ln_Name;
-
- while (*p != '.')
- {
- if (strncmp (p, grep, 4) == 0)
- {
- return (ln->ln_Name);
- }
- ++p;
- }
- }
-
- return (NULL); /* not found */
- }
-
- /*********************************************************************
- *
- * Break (^C) function
- *
- */
-
- int
- breakcheck ()
- {
- int zz = SetSignal (0L, 0L) & SIGBREAKF_CTRL_C;
-
- if (zz)
- {
- printf ("\n^C");
- }
- return (zz);
- }
-
- /*********************************************************************
- *
- * tell Lattice to return
- */
- int
- chkabort (void)
- {
- return (0);
- }
-
-
- /*********************************************************************
- *
- * function to return an error string
- *
- *
- */
-
- UBYTE *
- err_str (err)
-
- int err;
- {
-
- static UBYTE *errors[] =
- {
- " cannot issue SCSI command to self ",
- " DMA error ",
- " illegal or unexpected SCSI phase ",
- " SCSI parity error ",
- " Select timed out ",
- " status and/or sense error "
- };
-
- err -= 40;
-
- if ((err < 0) || (err > 5))
- return ("Error out-of-range");
- else
- return (errors[err]);
- }
-
- /*********************************************************************
- *
- * usage function
- *
- *
- */
-
- void
- usage (p)
- char *p;
- {
- static char *zz[] =
- {
- "Inquiry : SCSIutil [-dscsi_dev] scsi_id -i\n",
- "Read sectors (2) : -R sec_no\n",
- "Read sectors : -r sec_no\n",
- "Read capacity : -c\n",
- /* "Fill sector : -f sec_no byte\n", */
- "Stop/Start motor : -m {0=stop,1=start}\n",
- "Seek to sector (3) : -s sec_no\n",
- "\n",
- "Note 1: usually scsi_id = (BOARD * 100) + (LUN * 10) + SCSI_TARGET_ID\n",
- " 2: uses trackdisk.device\n",
- " 3: to park heads, try sec_no of -1\n",
- "" /* TERM */
- };
-
- int j = 0;
-
-
- printf ("%s", p);
- printf ("Usage : SCSIutil V%s [%s : %s] - written by Gary Duncan\n",
- VERSION, __DATE__, __TIME__, pname);
-
- while (*zz[j++])
- printf ("%s", zz[j - 1]);
- }
-
- /*********************************************************************
- *
- * sense_errs function ; prints sense errors
- *
- *
- */
-
- UBYTE *
- sense_errs (err)
-
- int err;
- {
- typedef struct
- {
- BYTE code;
- BYTE sense;
- UBYTE *ptr;
- } S_ERRS;
-
- /*
- * only the likely, interesting ones filled in, e.g media errors
- */
- static S_ERRS x[] =
- {
- 0x00, 0x00, "No error",
- 0x01, 0x04, "?",
- 0x02, 0x04, "?",
- 0x03, 0x04, "?",
- 0x04, 0x02, "?",
- 0x06, 0x04, "?",
- 0x09, 0x04, "?",
- 0x10, 0x03, "?",
- 0x10, 0x04, "?",
- 0x11, 0x03, "?",
- 0x12, 0x03, "?",
- 0x13, 0x03, "?",
- 0x14, 0x03, "?",
- 0x15, 0x04, "Seek error ",
- 0x17, 0x01, "?",
- 0x18, 0x01, "?",
- 0x19, 0x03, "?",
- 0x1A, 0x05, "?",
- 0x20, 0x05, "Invalid command op code",
- 0x21, 0x05, "Illegal sector address",
- 0x24, 0x05, "?",
- 0x25, 0x05, "Invalid LUN",
- 0x26, 0x05, "Invalid field in parameter list",
- 0x29, 0x06, "?",
- 0x2A, 0x06, "?",
- 0x31, 0x03, "?",
- 0x32, 0x01, "?",
- 0x32, 0x03, "?",
- 0x40, 0x04, "?",
- 0x41, 0x04, "?",
- 0x42, 0x04, "Power-on diagnostic failure",
- 0x43, 0x04, "?",
- 0x45, 0x04, "Select / reselect failure ",
- 0x47, 0x04, "SCSI Interface Parity Error",
- 0x48, 0x0B, "?",
- 0x49, 0x0B, "Illegal message drive can't support",
- -1, -1, "ILLEGAL sense!!"
- };
-
- int j = 0;
- UBYTE *p;
- char sense;
- char code;
-
- /*
- * verify that sense data looks valid
- */
- if (((scsi_cmd.scsi_Status & 2) == 0) ||
- (scsi_cmd.scsi_SenseActual < OFFS_KEY))
- {
- return ("");
- }
- sense = scsi_cmd.scsi_SenseData[OFFS_KEY] & 0xF;
- code = scsi_cmd.scsi_SenseData[OFFS_CODE];
-
- do
- {
- p = x[j].ptr;
- if ((x[j].code == code) && (x[j].sense == sense))
- break;
- } while (x[j++].code != -1);
-
- return (p);
- }
-