* sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
@ 2003-11-07 0:38 Pat LaVarre
2003-11-07 16:24 ` Pat LaVarre
2003-11-07 17:51 ` Patrick Mansfield
0 siblings, 2 replies; 14+ messages in thread
From: Pat LaVarre @ 2003-11-07 0:38 UTC (permalink / raw)
To: patmans; +Cc: linux-scsi
Patrick M:
Hi!
> http://marc.theaimsgroup.com/?l=linux-scsi&m=106762441112762
> List: linux-scsi
> Subject: Re: [PATCH/RFT] mode sense madness always use page 8
> From: Patrick Mansfield <patmans () us ! ibm ! com>
> Date: 2003-10-31 18:16:46
> ...
> > sudo ./plscsi /dev/sg1 -v -i x1C -x "5A 00 08:00:00:00 00 00:1C 00"
> > sudo ./plscsi /dev/sg1 -v -i 4 -x "5A 00 3F:00:00:00 00 00:04 00"
> > sudo ./plscsi /dev/sg1 -v -i 4 -x "5A 00 00:00:00:00 00 00:04 00"
> > sudo ./plscsi /dev/sg1 -v -i xFF -x "5A 00 3F:00:00:00 00 00:FF 00"
>
> Nice ...
>
> > Also personally I find the source for that
> > plscsi app impenetrably awful to read.
>
> Maybe you can rewrite it in c and get it into
> sg_utils.
I notice the equivalent C is smaller than any one edition of my plain
text inline cdrom.ko CDC_MMC_WR patches. So now this email ends with a
copy of what I have working so far.
$ mkdir gccscsi
$ cd gccscsi
$ wget ...
...
$ patch -p1 <...
patching file inq.c
patching file spinq.c
patching file Makefile
patching file gccscsi.h
patching file lscsi.c
$
$ make
gcc -Wall -o spinq spinq.c lscsi.c
$
$ sudo ./spinq /dev/cdrom
LITE-ON COMBO LTC-48161HKH0K
$
$ sudo ./spinq /dev/scd0
IOMEGA DVDRW4216INP-A 1.A0
$
$ gcc -c -Wall inq.c
$ # no worries
I'm trying to get to where we can easily write the many fun variations
on the concise inq.c rather than the verbose spinq.c that reads like an
SG_IO example from the web ... except without losing the freedom to
misalign stuff.
Mostly I'm now stuck wrestling with how to ask concisely to misalign the
struct sg_io_hdr_t, the cdb, the data, and/or the sense. I've coded a
few schemes that work, none yet concise. I want to be able to say
things like try the sg_io_hdr_t at N * x1000 - 1, then the cdb at +
x200, then the sense at + x206, then the data at + x21F. We could solve
this differently for scripts like inq.c and spinq.c that we interpret
entirely by gcc: for those to arrange mis/alignment we could declare a
__packed struct. But when interpreting a command line we don't have
that luxury unless we resort to printing the command line into a .c file
and then calling gcc.
I'm also not delighted to expose all the members of the struct sp in the
header, but as yet that's how I export its sizeof for the caller to
allocate.
Pat LaVarre
diff -Nur plscsi/inq.c gccscsi/inq.c
--- plscsi/inq.c 1969-12-31 17:00:00.000000000 -0700
+++ gccscsi/inq.c 2003-11-06 17:18:17.672894912 -0700
@@ -0,0 +1,13 @@
+#include "gccscsi.h"
+int main(int argc, char * argv[])
+{
+ --argc; ++argv;
+ while (0 < argc--) {
+ char const * dev = *argv++;
+ ALSO(dev);
+ }
+ I(0x24); Y("12 00:00:00 24 00");
+ DATA[8 + 0x10 + 8 + 4] = '\0';
+ printf("%s\n", &DATA[8]);
+ return 0;
+}
diff -Nur plscsi/spinq.c gccscsi/spinq.c
--- plscsi/spinq.c 1969-12-31 17:00:00.000000000 -0700
+++ gccscsi/spinq.c 2003-11-06 17:18:28.843196768 -0700
@@ -0,0 +1,35 @@
+#include "gccscsi.h"
+int main(int argc, char * argv[])
+{
+ int i = -1;
+
+ struct sp * sp = (struct sp *) calloc(1, sizeof *sp);
+ int max = 0x24;
+ char * data = (char *) calloc(1, max);
+
+ assert(sp != NULL);
+ assert(data != NULL);
+ assert((char *) sp < data);
+
+ --argc; ++argv;
+ assert(0 < argc);
+
+ if (sp_open(sp, argv[0]) < 0) {
+ sp_perror("sp_open");
+ } else {
+ sp_cdb(sp, "\x12\x00\x00\x00\x24\x00", 6);
+ i = sp_read(sp, &data[0], max);
+ if (i != 0) {
+ if (i == SP_THRU) {
+ sp_perror("sp_read");
+ } else {
+ fprintf(stderr, "sp_read: x%X\n", i);
+ }
+ } else {
+ data[8 + 0x10 + 8 + 4] = '\0';
+ printf("%s\n", &data[8]);
+ }
+ }
+
+ return i;
+}
diff -Nur plscsi/Makefile gccscsi/Makefile
--- plscsi/Makefile 1969-12-31 17:00:00.000000000 -0700
+++ gccscsi/Makefile 2003-11-06 17:15:14.615723832 -0700
@@ -0,0 +1,5 @@
+spinq: gccscsi.h spinq.c lscsi.c
+ gcc -Wall -o spinq spinq.c lscsi.c
+
+inq: gccscsi.h inq.c gccscsi.c lscsi.c
+ gcc -Wall -o inq inq.c gccscsi.c lscsi.c
diff -Nur plscsi/gccscsi.h gccscsi/gccscsi.h
--- plscsi/gccscsi.h 1969-12-31 17:00:00.000000000 -0700
+++ gccscsi/gccscsi.h 2003-11-05 15:07:46.000000000 -0700
@@ -0,0 +1,187 @@
+/* gccscsi.h
+ *
+ * Speak SCSI concisely wherever.
+ */
+
+/* Link with standard C libraries. */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Link with local C libraries. */
+
+#ifndef _WIN32
+#define sp_perror perror
+#include <endian.h>
+#include <scsi/sg.h>
+#else
+#include <windows.h>
+#include <ddk/ntddscsi.h>
+#endif
+
+/* Link with C++ clients. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Work with kebi-, mebi-, and gibi- bytes. */
+
+#define Ki (1 << 10) /* (1 << 10) = 1024 */
+#define Mi (Ki * Ki)
+#define Gi (Ki * Ki * Ki)
+
+/* Work with the bytes of integers. */
+
+#if __BYTE_ORDER == __BIG_ENDIAN /* if byte 0 = most significant */
+#define BIG(I, N) (((unsigned char *)&(I))[N])
+#define LIL(I, N) BIG(I, sizeof (I) - (N))
+#else /* else if byte 0 = least significant */
+#define LIL(I, N) (((unsigned char *)&(I))[N])
+#define BIG(I, N) LIL(I, sizeof (I) - (N))
+#endif
+
+/* Into a 32-bit exit int, compress zero else positive residue else: */
+
+#define SP_THRU 0x80000000 /* negative if trouble */
+#define SP_DATA_THRU 0x40000000 /* data not counted */
+#define SP_SENSE_THRU 0x20000000 /* sense not counted */
+//..... SP_LATE_THRU 0x10000000 /* timeout */
+
+#define SP_COMPARE 0x02000000 /* copied wrong data */
+#define SP_RESIDUE 0x01000000 /* copied too much or too little data */
+
+#define SP_SENSE 0x00800000 /* credible sense copied in */
+#define SP_DEFERRED 0x00400000 /* success wrongly predicted before now */
+#define SP_SK 0x000F0000 /* sk = sense key */
+#define SP_ASC 0x0000FF00 /* asc = additional sense code */
+#define SP_ASCQ 0x000000FF /* ascq = asc qualifier */
+
+#define SP_SK_ASC 0x000FFF00 /* sk plus asc */
+#define SP_SK_ASC_ASCQ 0x000FFFFF /* sk plus asc plus ascq */
+
+/* Link with lscsi.c or substitute. */
+
+#ifndef _WIN32
+struct sp
+{
+ sg_io_hdr_t sih;
+ int sense_align_hint;
+ char sense[0xFF];
+ int fd;
+};
+#else
+struct sp
+{
+ SCSI_PASS_THROUGH spt;
+ UCHAR cdb_tail[0xFF]; /* 16 unnecessary bytes */
+ int sense_align_hint;
+ UCHAR sense[0xFF];
+ HANDLE h;
+};
+#endif
+
+extern int sp_open(struct sp * sp, char const * name);
+extern void sp_align(struct sp * sp, int page, int offset);
+extern void sp_close(struct sp * sp);
+
+extern void sp_zero(struct sp * sp);
+extern char * sp_cdb(struct sp * sp, char * cdb, int max);
+extern char * sp_data(struct sp * sp, char * chars, int max);
+extern char * sp_sense(struct sp * sp, char * sense, int max);
+extern int sp_late(struct sp * sp, int s, int ns);
+
+extern int sp_say(struct sp * sp);
+extern int sp_read(struct sp * sp, char * to, int max);
+extern int sp_write(struct sp * sp, char const * from, int max);
+extern int sp_data_enough(struct sp * sp);
+extern int sp_sense_enough(struct sp * sp);
+
+extern void sp_perror(char const * st);
+
+/* Link with gccscsi.c */
+
+struct gcs;
+
+extern char * gcs_header(struct gcs * gcs);
+extern char * gcs_cdb(struct gcs * gcs);
+extern int gcs_cdb_enough(struct gcs * gcs);
+extern char * gcs_data(struct gcs * gcs);
+extern int gcs_allotted(struct gcs * gcs);
+extern int gcs_enough(struct gcs * gcs);
+extern char * gcs_sense(struct gcs * gcs);
+extern int gcs_sense_enough(struct gcs * gcs);
+extern void gcs_cdb_out(struct gcs * gcs, int max, int page, int offset);
+extern void gcs_sense_in(struct gcs * gcs, int max, int page, int offset);
+extern void gcs_in(struct gcs * gcs, int max, int page, int offset);
+extern void gcs_out(struct gcs * gcs, int max, int page, int offset);
+extern void gcs_beyond(struct gcs * gcs, int beyond);
+extern void gcs_quiet(struct gcs * gcs);
+extern void gcs_verbose(struct gcs * gcs);
+extern void gcs_late(struct gcs * gcs, int s, int ns);
+extern void gcs_cdb_with(struct gcs * gcs, char const * st);
+extern void gcs_with(struct gcs * gcs, char const * st);
+extern int gcs_yes_no(struct gcs * gcs);
+extern void gcs_yes(struct gcs * gcs, char const * cdb);
+extern void gcs_no(struct gcs * gcs, char const * cdb);
+extern void gcs_also(struct gcs * gcs, char const * name);
+extern void gcs_each(struct gcs * gcs);
+extern void gcs_exit(struct gcs * gcs, char const * file, int line);
+extern struct gcs * gcs(void);;
+
+/* Speak SCSI concisely from a single thread. */
+
+#define ALSO(N) gcs_also(gcs(), (N))
+#define EXIT() gcs_exit(gcs(), __FILE__, __LINE__)
+#define YN(ST) gcs_yes_no(gcs(), (ST))
+
+#undef A
+#define B(B) gcs_beyond(gcs(), (B))
+#undef C /* gcs --compare */
+#undef D
+#define E() gcs_each(gcs())
+#undef F /* gcs --from */
+#undef G
+#undef H /* gcs --help */
+#define I(I) gcs_in(gcs(), (I), 4096, 0)
+#undef J
+#undef K
+#define L(S, NS) gcs_late(gcs(), (S), (NS))
+#undef M
+#define N(ST) gcs_no(gcs(), (ST))
+#define O(O) gcs_out(gcs(), (O), 4096, 0)
+#undef P /* gcs --please */
+#define Q() gcs_quiet(gcs())
+#undef R /* gcs --repeat */
+#define S(S) gcs_sense_in(gcs(), (S), 4, 0)
+#undef T /* gcs --to */
+#undef U
+#define V() gcs_verbose(gcs())
+#define W(ST) gcs_with(gcs(), (ST))
+#define Y(ST) gcs_yes(gcs(), (ST))
+#undef Z
+
+#define CDB (gcs_cdb(gcs()))
+#define CDB_ENOUGH (gcs_cdb_enough(gcs()))
+
+#define DATA (gcs_data(gcs()))
+#define ALLOTTED (gcs_allotted(gcs()))
+#define ENOUGH (gcs_enough(gcs()))
+
+#define SENSE (gcs_sense(gcs()))
+#define SENSE_ENOUGH (gcs_sense_enough(gcs()))
+
+/* Trace execution without a debugger. */
+
+#define T() fprintf(stderr, "file %s line %d\n", __FILE__, __LINE__)
+
+/* Yes link with C++ clients. */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* end of file */
diff -Nur plscsi/lscsi.c gccscsi/lscsi.c
--- plscsi/lscsi.c 1969-12-31 17:00:00.000000000 -0700
+++ gccscsi/lscsi.c 2003-11-05 15:59:42.000000000 -0700
@@ -0,0 +1,316 @@
+/* lscsi.c
+ *
+ * Interpret the arbitrary sp_ SCSI pass thru of "gccscsi.h"
+ * via SG_IO since <scsi/sg.h> version 3 i.e. since Linux kernel 2.4.
+ *
+ * Bugs include:
+ *
+ * Suppose auto sense occurred if ioctl SG_IO returns nonnegative.
+ * Do not distinguish ioctl failed from auto sense unintelligible.
+ * Pass thru the data per cdb limit of one contiguous virtual allocation.
+ * Pass thru the xFF limits on CDB length and sense length.
+ * Trust caller to avoid null pointers and negative lengths.
+ *
+ * Simplifications include:
+ *
+ * Require caller to mis/align struct, cdb, sense, and data.
+ * Never pass thru -1 SG_DXFER_NONE with nonnull dxferp.
+ * Never pass thru -4 SG_DXFER_TO_FROM_DEV.
+ * Never pass thru -5 SG_DXFER_UNKNOWN.
+ *
+ * See also: http://lxr.linux.no/source/Documentation/CodingStyle
+ */
+
+/* Link with standard C libraries. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Link with local C libraries. */
+
+#include <fcntl.h>
+#include <scsi/sg.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+/* Link with ../gccscsi/. */
+
+#include "gccscsi.h"
+
+#define USUAL_SENSE 0x12 /* x12 Win XP/2K, x0E Win ME/9X */
+#define USUAL_SECONDS (28 * 60 * 60) /* 28 hours = more than a day */
+
+/* Exit after printing why. */
+
+static void exits(char const * st, char const * file, int line)
+{
+ if (*st != '\0') {
+ fprintf(stderr, "%s: ", st);
+ }
+ fprintf(stderr, "file %s line %d\n", file, line);
+ exit(-line);
+}
+
+/* Exit after printing errno. */
+
+static void exite(char const * st, char const * file, int line)
+{
+ int en = errno;
+ perror(st);
+ fprintf(stderr, "errno %d at file %s line %d\n", en, file, line);
+ exit(-line);
+}
+
+/* Disconnect. */
+
+void sp_close(struct sp * sp)
+{
+ int i = close(sp->fd);
+ if (i != 0) exite("close", __FILE__, __LINE__);
+ sp->fd = -1;
+}
+
+/* Begin a new command, but stay connected. */
+
+void sp_zero(struct sp * sp)
+{
+ sg_io_hdr_t * sih = &sp->sih;
+ memset(sih, '\0', sizeof *sih);
+ sih->interface_id = 'S';
+ sih->dxfer_direction = SG_DXFER_NONE; /* often -1 */
+ sp_sense(sp, &sp->sense[0], USUAL_SENSE);
+ sp_late(sp, USUAL_SECONDS, 0);
+}
+
+/* Connect and return nonnegative, else decide errno. */
+
+int sp_open(struct sp * sp, char const * name)
+{
+ int mode = (O_RDONLY | O_NONBLOCK);
+ int fd = open(name, mode);
+ sp_zero(sp);
+ sp->fd = fd;
+ if (0 <= fd) {
+ int version = 0;
+ int i = ioctl(fd, SG_GET_VERSION_NUM, &version);
+ if (0 <= i) {
+ if (30000 <= version) {
+// fprintf(stderr, "%d\n", fd);
+ return fd;
+ }
+ }
+ sp_close(sp);
+ errno = EINVAL;
+ }
+ return -1;
+}
+
+/* Hint from where and how much CDB to copy out, return where. */
+
+char * sp_cdb(struct sp * sp, char * cdb, int max)
+{
+ sg_io_hdr_t * sih = &sp->sih;
+ unsigned char uch = ((unsigned char) max);
+ if (uch != max) exits("large", __FILE__, __LINE__);
+ sih->cmd_len = uch;
+ sih->cmdp = cdb;
+ return sih->cmdp;
+}
+
+/* Hint where and how much data to copy in or out, return where. */
+
+char * sp_data(struct sp * sp, char * data, int max)
+{
+ sg_io_hdr_t * sih = &sp->sih;
+ sih->dxfer_len = max;
+ sih->dxferp = data;
+ return sih->dxferp;
+}
+
+/* Hint to where and how much sense to copy in, return where. */
+
+char * sp_sense(struct sp * sp, char * sense, int max)
+{
+ sg_io_hdr_t * sih = &sp->sih;
+ unsigned char uch = ((unsigned char) max);
+ if (uch != max) exits("large", __FILE__, __LINE__);
+ sih->mx_sb_len = uch;
+ sih->sbp = sense;
+ return sih->sbp;
+}
+
+/* Hint when to time out and reset, return ns. */
+
+int sp_late(struct sp * sp, int s, int ns)
+{
+ sg_io_hdr_t * sih = &sp->sih;
+ int ms = ((s * 1000) + ((ns + 999999) / 1000 / 1000));
+ if ((ms / 1000) != s) exits("large", __FILE__, __LINE__);
+ sih->timeout = ms;
+ return ((sih->timeout % 1000) * 1000 * 1000);
+}
+
+/* Zero all but the least significant set bit of a mask. */
+
+static int lsb(int mask)
+{
+ return (mask & -mask);
+}
+
+/* Construct an sp_read/ sp_write exit int from bits of auto sense. */
+
+static int int_from_sense(char const * chars, int length)
+{
+ int exit_int = SP_THRU; /* unintelligible sense */
+
+ /* Require minimal sense. */
+
+ if (2 < length) {
+ int sk = (chars[2] & 0x0F);
+ int response_code = (chars[0] & 0x7F);
+ if ((response_code == 0x70) || (response_code == 0x71)) {
+ exit_int |= SP_SENSE; /* intelligible sense */
+
+ /* Distinguish x70 Current vs. other sense. */
+
+ if (response_code != 0x70) {
+ exit_int |= SP_DEFERRED;
+ }
+
+ /* Pass back SK. */
+
+ exit_int |= (sk * lsb(SP_SK));
+
+ /* Interpret additional length, not quite like t10. */
+
+ if (7 < length) {
+ int al = (chars[7] & 0xFF);
+ if (al != 0x00) {
+ int max = (7 + 1 + al);
+ if (max < length) {
+ length = max;
+ }
+ }
+ }
+
+ /* Pass back ASC and ASCQ. */
+
+ if (0xC < length) {
+ int asc = (chars[0xC] & 0xFF);
+ exit_int |= (asc * lsb(SP_ASC));
+ }
+ if (0xD < length) {
+ int ascq = (chars[0xD] & 0xFF);
+ exit_int |= (ascq * lsb(SP_ASCQ));
+ }
+ }
+ }
+ return exit_int;
+}
+
+/* Pass thru. Return zero else positive residue else negative trouble. */
+
+int sp_say(struct sp * sp)
+{
+ int fd = sp->fd;
+ sg_io_hdr_t * sih = &sp->sih;
+ int max = sih->dxfer_len;
+ char const * sense_chars = sih->sbp;
+ int sense_max = sih->mx_sb_len;
+ int i;
+ int residue;
+ int sense_enough;
+ int exit_int;
+
+ /* Trust caller to have decided much. */
+
+ ; /* sih->interface_id */
+ ; /* sih->cmdp sih->cmd_len sih->sbp sih->mx_sb_len sih->timeout */
+ ; /* sih->dxfer_direction sih->dxferp sih->dxfer_len */
+
+ /* Trust caller to have zeroed much. */
+
+ ; /* sih->iovec_count sih->flags sih->pack_id sih->usr_ptr */
+ ; /* sih->status sih->masked_status sih->msg_status */
+ ; /* sih->sb_len_wr sih->host_status sih->drive_status */
+ ; /* sih->resid sih->duration sih->info */
+
+ /* Trace. */
+
+#if 0
+ fprintf(stderr, "%d '%c' %d %dms\n",
+ fd, sih->interface_id, sih->dxfer_direction, sih->timeout);
+ fprintf(stderr, "x %X %X %X\n",
+ sih->cmd_len, sih->mx_sb_len, sih->dxfer_len);
+#endif
+
+ /* Speak. */
+
+ i = ioctl(fd, SG_IO, sih);
+ residue = sih->resid;
+ sense_enough = sih->sb_len_wr;
+
+ /* Compress much into the exit int. */
+
+ exit_int = residue; /* zero if ok else positive residue */
+
+ if (i < 0) {
+ exit_int = SP_THRU; /* ioctl failed */
+ } else if ((residue < 0) || (max < residue)) {
+ exit_int = SP_THRU;
+ exit_int |= SP_DATA_THRU; /* data not counted */
+ } else if ((sih->info & SG_INFO_OK_MASK) != SG_INFO_OK) {
+ if ((sense_enough < 0) || (sense_max < sense_enough)) {
+ exit_int = SP_THRU;
+ exit_int |= SP_SENSE_THRU; /* sense not counted */
+ } else {
+ exit_int = SP_THRU;
+ exit_int |= int_from_sense(sense_chars, sense_enough);
+ if (0 != residue) {
+ exit_int |= SP_RESIDUE;
+ }
+ }
+ }
+
+ return exit_int;
+}
+
+/* Pass thru and copy zero or more bytes of data in. */
+
+int sp_read(struct sp * sp, char * to, int max)
+{
+ sg_io_hdr_t * sih = &sp->sih;
+ sp_data(sp, to, max);
+ sih->dxfer_direction = SG_DXFER_FROM_DEV; /* often -3 */
+ return sp_say(sp);
+}
+
+/* Pass thru and copy zero or more bytes of data out. */
+
+int sp_write(struct sp * sp, char const * from, int max)
+{
+ sg_io_hdr_t * sih = &sp->sih;
+ sp_data(sp, (char *) from, max);
+ sih->dxfer_direction = SG_DXFER_TO_DEV; /* often -2 */
+ return sp_say(sp);
+}
+
+/* Get the last length of data copied in. */
+
+int sp_data_enough(struct sp * sp)
+{
+ sg_io_hdr_t * sih = &sp->sih;
+ return (sih->dxfer_len - sih->resid);
+}
+
+/* Get the last length of sense copied in. */
+
+int sp_sense_enough(struct sp * sp)
+{
+ sg_io_hdr_t * sih = &sp->sih;
+ return sih->sb_len_wr;
+}
+
+/* end of file */
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-07 0:38 sg utils sg_io -i 0x24 -y "12 00:00:00 24 00" Pat LaVarre
@ 2003-11-07 16:24 ` Pat LaVarre
2003-11-07 16:56 ` Pat LaVarre
2003-11-07 17:51 ` Patrick Mansfield
1 sibling, 1 reply; 14+ messages in thread
From: Pat LaVarre @ 2003-11-07 16:24 UTC (permalink / raw)
To: dougg; +Cc: patmans, linux-scsi
> plscsi is starting to look remarkably like FreeBSD's
> camcontrol utility. Perhaps we should be looking at
> implementing camcontrol in Linux.
Fun web trail, thanks:
http://www.google.com/search?q=man+camcontrol
Unix Man Page For 8 camcontrol
http://www.svbug.com/cgi-bin/man.cgi?comd=8+camcontrol
I've seen a legion of pr*prietary tools that do this same work. My most
recent survey appears at:
http://members.aol.com/ppaatt/#storage
Pat LaVarre
P.S. Please yell at me offline if I chose wrong to give you this email
in pieces.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-07 16:24 ` Pat LaVarre
@ 2003-11-07 16:56 ` Pat LaVarre
2003-11-07 17:09 ` Pat LaVarre
0 siblings, 1 reply; 14+ messages in thread
From: Pat LaVarre @ 2003-11-07 16:56 UTC (permalink / raw)
To: dougg; +Cc: patmans, linux-scsi
> Perhaps we should be looking at
> implementing camcontrol in Linux.
Implementing, yes. Copying, no. I have a series of arguments, this
email presents only the First:
> Unix Man Page For 8 camcontrol
> http://www.svbug.com/cgi-bin/man.cgi?comd=8+camcontrol
I vote (: vehemently :) against merging into sg utils the camcontrol
etc. practice of ...
... obscuring the plain hex by substituting English at this level. For
example, in place of:
camcontrol tur da0
camcontrol eject -n cd -u 1 -v
camcontrol inquiry -D
I vote for:
sg_io -y "00 00:00:00 00 00"
sg_io -y "1B 01:00:00 02 00"
sg_io -i 0x24 -y "12 00:00:00 24 00"
Already we have sg_scan sg_inq sg_turs for less precise communication.
I vote for the hex because I can see what it means. With those
camcontrol examples, I have to guess whether they sometimes or always
mean the hex I intend.
I'm not opposed to offering text & gui as well. I just want text & gui
made available separately. Some of my ideas for a gui full of natural
language text cribbed from the t10 fiction appear as screen shots near
the end of the web trail:
Pat LaVarre et alia
http://members.aol.com/ppaatt/
Directly manipulating storage devices
http://members.aol.com/ppaatt/#storage
2.1. Arbitrary transparent pass thru of SCSI.
2.1.1. Via Java GUI
screen shots
http://members.aol.com/plforth/console/scsi/
http://members.aol.com/plforth/console/scsi/javaspt3c.png
(and others)
Although few people can easily give SCSI pass thru privilege to a Java
applet, I surprised myself by discovering that an unsigned unprivileged
Java applet here remains useful. In practice I found I left the
voluminous text & GUI on the web, then where I was actually working I
fetched the command line app and copy-pasted the command line args I
wanted from the applet.
Pat LaVarre
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-07 16:56 ` Pat LaVarre
@ 2003-11-07 17:09 ` Pat LaVarre
2003-11-07 17:17 ` Pat LaVarre
0 siblings, 1 reply; 14+ messages in thread
From: Pat LaVarre @ 2003-11-07 17:09 UTC (permalink / raw)
To: dougg; +Cc: patmans, linux-scsi
> > Perhaps we should be looking at
> > implementing camcontrol in Linux.
>
> Implementing, yes. Copying, no.
> I have a series of arguments, ...
>
> > Unix Man Page For 8 camcontrol
> > http://www.svbug.com/cgi-bin/man.cgi?comd=8+camcontrol
I think arg parsing is an issue.
I see the camcontrol man page includes such off-putting apologetic
fragments as:
"The sense information from the test unit ready command would not get
printed out, since the first getopt(3) call in camcontrol bails out when
it sees the second argument to -c (0x00), above.
"If the CDB specified causes data to be transfered to or from the SCSI
device in question, you MUST specify either
... -i len fmt ... -o len fmt [args] ..."
I particular want the common things to remain concise.
I choke over the idea of having to specify fmt in addition to len of -i
or -o.
Part of why I find plscsi/ unreadable, even though I wrote plscsi/
myself, is that in plscsi/ I resorted to rewriting getopts to fix this
kind of thing.
Since then I think I have by now found my way to a (more?) fully
getopt-compatible parsing of args. That gccscsi.h I posted #define's A
thru Z macros that correspond to proposed sg_io args -a thru -z.
1) That -d is unused appears as, e.g.:
#undef D
2) That some options exist only for the command line appears as, e.g.:
#undef P /* gcs --please */
The -p or --please option is an interlock. You have to add it to pass
thru such things as non-standard CDB lengths, the op x04 Format that
smashes disks, and the -y "12 00:00:00 00" Inquiry for Zero that crashes
many version of Linux 2.4.
3) Seeing that the args are single can be difficult, e.g.:
#define L(S, NS) gcs_late(gcs(), (S), (NS))
I figure at the command line we parse $s.fraction and convert to the
standard posix int pair (seconds, nanoseconds).
4) Seeing that the args are omitted or single can be easy, e.g.:
#define Q() gcs_quiet(gcs())
#define S(S) gcs_sense_in(gcs(), (S), 4, 0)
Pat LaVarre
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-07 17:09 ` Pat LaVarre
@ 2003-11-07 17:17 ` Pat LaVarre
0 siblings, 0 replies; 14+ messages in thread
From: Pat LaVarre @ 2003-11-07 17:17 UTC (permalink / raw)
To: dougg; +Cc: patmans, linux-scsi
> > > Perhaps we should be looking at
> > > implementing camcontrol in Linux.
> >
> > Implementing, yes. Copying, no.
> > I have a series of arguments, ...
Or maybe not so very many. Mostly, I find camcontrol disappointingly
large.
> > > Unix Man Page For 8 camcontrol
> > > http://www.svbug.com/cgi-bin/man.cgi?comd=8+camcontrol
>
> I think arg parsing is an issue.
>
> I see the camcontrol man page includes such off-putting ...
Personally I think even my own plscsi/ is too large. I'm hoping gccscsi
by contrast is small enough to demo kernel trouble (and proposed plug 'n
play patches).
For example, offline recently I thought I saw someone report that a
cdb-unexpectedly-short doesn't pass thru 2.6.0 to usb mass. Seeing
plscsi say that doesn't tell us the kernel has an issue there: we have
to ask, and we cannot easily answer, does plscsi have an issue there.
I care most here about transparency: easily establishing more confidence
that I know what I asked the kernel than if I had written an ad hoc test
program
I figure I can achieve transparency by remembering reuse proves my
general test program free of the simple errors I might make in an ad hoc
test program, but I have to keep my general test program small enough to
let me easily read over, step thru, maybe even copy-paste-edit out, just
the lines of code that I need.
Pat LaVarre
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-07 0:38 sg utils sg_io -i 0x24 -y "12 00:00:00 24 00" Pat LaVarre
2003-11-07 16:24 ` Pat LaVarre
@ 2003-11-07 17:51 ` Patrick Mansfield
2003-11-07 18:11 ` Pat LaVarre
1 sibling, 1 reply; 14+ messages in thread
From: Patrick Mansfield @ 2003-11-07 17:51 UTC (permalink / raw)
To: Pat LaVarre; +Cc: linux-scsi
On Thu, Nov 06, 2003 at 05:38:36PM -0700, Pat LaVarre wrote:
Do you have a tar ball or such of all the code? Or is this still very much
a work in progress?
I don't see all the functions in the patch, for example, gcs_in.
I was going to say put the functions in a library, but maybe you already
are headed that way. Then create a libsgio or such, and users like
sg_utils, scsi_id, cdrecord, scsidev, etc. could link with sgio.
And lose the macros I, Y, etc, just use the function name, or at least
have more meaningful macro names.
The command line plscsi could support both long and short names (-i or
--gcs-in).
-- Patrick Mansfield
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-07 17:51 ` Patrick Mansfield
@ 2003-11-07 18:11 ` Pat LaVarre
2003-11-07 18:27 ` Pat LaVarre
0 siblings, 1 reply; 14+ messages in thread
From: Pat LaVarre @ 2003-11-07 18:11 UTC (permalink / raw)
To: patmans; +Cc: dougg, linux-scsi
Patrick M:
>
Hi! Immediate attention! Wow. Thank you.
> Do you have a tar ball or such of all the code?
> Or is this still very much a work in progress?
Yes release early release often.
> I don't see all the functions in the patch, for example, gcs_in.
That patch just gives you enough to compile & link & run the verbose,
spinq.c, and to compile without linking the alternative, concise,
inq.c. I don't mean to be coy, I'm just trying not to overwhelm the
list, I've thought about this problem in isolation for nearly a decade
without before now finding anyone else on Earth who cared.
> I was going to say put the functions in a library, but maybe you already
> are headed that way. Then create a libsgio or such, and users like
> sg_utils, scsi_id, cdrecord, scsidev, etc. could link with sgio.
Aye. Yes I did try this already. Most recent demo might be the
lscsi.so of the gccscsi tar ball on the web. There I called the .so
library from gforth, which more directly offers dynamic link than static
link, again I built both Linux & Win XP/2K.
> And lose the macros I, Y, etc, just use the function name, or at least
> have more meaningful macro names.
I'm trying to distinguish two kinds of test code.
In spinq.c we see the meaningful subroutine names we like already - yes?
I'm not sure you agree we want to write any other kind of code?
In inq.c we see cryptic macro names. Those cryptic names correspond
directly to the -a thru -z options of a "nice" tool like plscsi or
camcontrol or my now proposed sg_io.
For example, if our command line is -i x24 -y "12 00:00:00 24 00" then
our C code is { I(0x24); Y("12 00:00:00 24 00"); }. When you learn the
one cryptic syntax, you learn the other cryptic syntax, modulo some
transliteration.
I'm thinking if we like a cryptic command line, then so too we like
cryptic C code. We write inq.c, not just spinq.c, depending on our
audience.
I'm in two minds over the name sg_io. I'm guessing that's the name that
the sg utils audience will want, but I'm confident that name won't mean
anything on the other operating systems and having to find how to type _
will annoy people.
I figure for those other folk we will offer a gcs command line, and let
people ignore the fact that a gcs command line and an sg_io command line
accomplish the same thing with the same syntax.
Or maybe we'd rather say gcs always. But if the cost of getting gcs
into sg utils is to say sg_io for Linux only, then I figure we pay that
cost.
> The command line plscsi could support both long and short names (-i or
> --gcs-in).
Ouch, sorry, yes I left that part of the patch out, I find I have to
sneaker net it here, please stay tuned.
Pat LaVarre
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-07 18:11 ` Pat LaVarre
@ 2003-11-07 18:27 ` Pat LaVarre
2003-11-07 18:31 ` Pat LaVarre
0 siblings, 1 reply; 14+ messages in thread
From: Pat LaVarre @ 2003-11-07 18:27 UTC (permalink / raw)
To: patmans; +Cc: dougg, linux-scsi
> > The command line plscsi could support both long and short names (-i or
> > --gcs-in).
>
> Ouch, sorry, yes I left that part of the patch out, I find I have to
> sneaker net it here, please stay tuned.
As follows. --yes, --in, --out, etc., very much like plscsi --help
says. Perhaps the key fragment is the zero or one arg per option usage
and default values description:
"-b --beyond $length // else 0\n"
"-c --compare\n"
"-e --each\n"
"-f --from $fn // else stdin\n"
"-h --help\n"
"-i --in $length // else 0.4096.0 = 0 aligned at 4 KiB\n"
"-l --late $seconds // else 100800.000 = 28 hours\n"
"-n --no $hex\n"
"-o --out $length // else 0.4096.0 = 0 aligned at 4 KiB\n"
"-p --please // else audit cdb length, etc.\n"
"-q --quiet\n"
"-r --repeat $count // else 1\n"
"-s --sense $length // else 18.4.0 = x12 aligned at 4 bytes\n"
"-t --to $fn // else stdout\n"
"-v --verbose\n"
"-w --with $hex // else -w \"AE\"\n"
"-y --yes $hex // else -i x24 -y \"12 00:00:00 24 00\"\n"
"\n" ...
"gsc $dev -v -i 0x24 -y \"12 00:00:00 24 00\" // Inquiry\n"
"gsc $dev -v -i 8 -y \"25 00 00:00:00:00 00 00:00 00\" // Read Max LBA\n"
"gsc $dev -v -y \"00 00:00:00 00 00\" // Test Unit Ready\n"
"gsc $dev -v -y \"1B 00:00:00 00 00\" // Stop Unit\n"
"gsc $dev -v -y \"1B 00:00:00 01 00\" // Start Unit\n"
"gsc $dev -v -y \"1B 00:00:00 02 00\" // Stop Then Eject\n"
Again I say I'm not happy with the treatment of misalignment.
Diff'ed against this version, striving to keep the gccscsi.c small, I
find maybe now I'm learning towards a deeply arcane multi-arg option
such as:
--align 0x1000 -1 0x234 0x345 0x456
By that I mean, with respect to what kind of interesting alignment
boundary (x1000), say where to position the sg_io_hdr_t (-1), the cdb
(0x234), the sense (x345), and the data (x456).
> > Do you have a tar ball ...
>
> Yes release early release often.
Tar ball to list is forbidden, no? So I launched this thread with a
normal small patch, but then in this post I have included a version of
the command line parser as plain text inline.
Pat LaVarre
--- gsc.c
/* gsc.c
*
* Interpret a command line in terms of "gccscsi.h".
*/
/* Link with local C libraries. */
#include "gccscsi.h"
#include "version.h"
/* Step thru implicit and command line args. */
static char const * const * args;
/* Remember some command line args. */
static int interpret_dash = 1;
static int interpret_compare = 0;
static int interpret_please = 0;
static int interpret_repeat = 1;
static int interpret_yes = -1;
static char const * interpret_from = NULL;
static char const * interpret_to = NULL;
/* Summarise command line syntax. */
#define USAGE \
"gsc $dev... -e -yiowp -acfnlrst -bhqv $args... // $comment..."
/* Complain of command line syntax. */
static void confused_exit(void)
{
fprintf(stderr, "Usage: %s\nMore details at: gss --help\n", USAGE);
exit(-__LINE__);
}
/* Convert to CDB length from CDB[0]. */
static int to_cdb_length(int op, int guess)
{
switch (op & 0xE0) { /* &xE0 = "group" */
case 0x00: return 6; /* x00 .. x1F */
case 0x20: return 10;/* x20 .. x3F */
case 0x40: return 10; /* x40 .. x5F */
case 0x60: break; /* x60 .. x7F reserved */
case 0x80: break; /* x80 .. x9F reserved */
case 0xA0: return 12; /* xA0 .. xBF */
case 0xC0: break; /* xC0 .. xDF vendor-specific */
case 0xE0: break; /* xE0 .. xFF vendor-specific */
}
return guess;
}
/* Complain of SCSI pass thru known to crash operating systems. */
static void displeased_exit(char const * st)
{
fprintf(stderr, "Say --please to pass thru %s\n", st);
exit(-__LINE__);
}
/* Exit without risking a crash. */
static void audit_gss(struct gss * gss)
{
char const * cdb = gss_get_cdb(gss);
int op = (cdb[0] & 0xFF);
int enough = to_cdb_length(op, -1);
if (gss_get_cdb_enough(gss) != enough) {
displeased_exit("non-standard CDB length");
}
if (cdb[0] == 0x04) {
displeased_exit("op x04 Format");
}
if ((cdb[0] == 0x12) && (gss_get_chars_length(gss) == 0)) {
displeased_exit("op x12 Inquiry for zero");
}
if ((cdb[0] == 0x1A) && (gss_get_chars_length(gss) < 8)) {
displeased_exit("op x1A Mode Sense 6 for less than 8");
}
}
/* Open a file to read from. */
static FILE * open_from(char const * fn)
{
if (*fn == '\0') {
return stdin; /* FIXME: might be opened "rt" */
} else {
FILE * fi = fopen(fn, "rb");
if (fi != NULL) {
return fi;
}
perror("gss:from:fopen");
exit(-__LINE__);
}
}
/* Fill with copies of the beginning. */
static void fill(char * chars, int index, int length)
{
char const * home = chars;
int step = index;
for (;;) {
chars += step; length -= step;
step = ((length < index) ? length : index);
if (step <= 0) break;
memmove(chars, home, step);
index += step;
}
}
/* Read once to fill with copies, else fill with '\0' nul. */
static void read_to_fill(FILE * fi)
{
int length = gss_get_chars_length(gss_first);
if (0 < length) {
char * chars = gss_get_chars(gss_first);
int io = fread(chars, 1, length, fi);
if ((0 <= io) && (io <= length)) {
chars[0] = '\0';
if (io == 0) ++io;
fill(chars, io, length);
} else {
if (ferror(fi)) {
perror("gss:from:fread");
} else {
fprintf(stderr, "gss:from:feof\n");
}
exit(-__LINE__);
}
}
}
/* Copy the data before passing the data out. */
char const * new_copy(struct gss * gss)
{
int length = gss_get_chars_length(gss);
if (0 < length) {
char * chars = gss_get_chars(gss);
char * new_chars = calloc(1, length);
if (new_chars != NULL) {
memcpy(new_chars, chars, length);
return new_chars;
}
perror("gss:compare:calloc");
exit(-__LINE__);
}
return NULL;
}
/* Compare the data passed out to the data passed in. */
static int compare_copy(struct gss * gss, int rc, char const * was)
{
int enough = gss_get_chars_enough(gss);
if (0 < enough) {
char * chars = gss_get_chars(gss);
if (memcmp(was, chars, enough) != 0) {
if (0 < rc) rc = SP_RESIDUE;
rc |= SP_PASS_THRU;
rc |= SP_COMPARE;
}
}
return rc;
}
/* Open a file to write to. */
static FILE * open_to(char const * fn)
{
if (*fn == '\0') {
return stdout; /* FIXME: might be opened "wt" */
} else {
FILE * fi = fopen(fn, "wb");
if (fi != NULL) {
return fi;
}
perror("gss:to:fopen");
exit(-__LINE__);
}
}
/* Write once. */
static void write_to(FILE * fi)
{
int length = gss_get_chars_length(gss_first);
if (0 < length) {
char * chars = gss_get_chars(gss_first);
int io = fwrite(chars, 1, length, fi);
if (io != length) {
perror("gss:to:fwrite");
exit(-__LINE__);
}
}
}
/* Interpret --yes or --no. */
static void run(char const * hex)
{
struct gss * gss = gss_first;
int please = interpret_please;
int compare = interpret_compare;
int repeat = interpret_repeat;
int yes = interpret_yes;
char const * from_fn = interpret_from;
char const * to_fn = interpret_to;
FILE * from_fi = NULL;
FILE * to_fi = NULL;
char const * was = NULL;
int tolerable = 0;
int rc = 0;
/* Audit. */
if (!please) {
audit_gss(gss);
}
if (to_fn != NULL) {
to_fi = open_to(to_fn);
}
/* Start up. */
if (from_fn != NULL) {
from_fi = open_from(from_fn);
}
if (from_fi != NULL) {
read_to_fill(from_fi);
}
if (compare) {
was = new_copy(gss);
}
/* Speak, maybe repeatedly. */
while (0 < repeat--) {
rc = gss_hex_try(gss, hex);
if (compare) {
rc = compare_copy(gss, rc, was);
}
if (tolerable == 0) {
tolerable = ((0 < rc) ? rc : -1);
}
if ((0 < rc) && (rc == tolerable)) {
rc = 0;
}
if (yes != (rc == 0)) {
break;
}
}
/* Shut down. */
if (to_fi != NULL) {
write_to(to_fi);
}
exit(rc);
}
static char const * arg_read(void)
{
if (*args == NULL) {
confused_exit();
}
return *args++;
}
static int to_int(char const * st)
{
st = st;
return 0;
}
static void helpful_exit(void)
{
char const * st = /* one line per option, sorted by name */
"-b --beyond $length // else 0\n"
"-c --compare\n"
"-e --each\n"
"-f --from $fn // else stdin\n"
"-h --help\n"
"-i --in $length // else 0.4096.0 = 0 aligned at 4 KiB\n"
"-l --late $seconds // else 100800.000 = 28 hours\n"
"-n --no $hex\n"
"-o --out $length // else 0.4096.0 = 0 aligned at 4 KiB\n"
"-p --please // else audit cdb length, etc.\n"
"-q --quiet\n"
"-r --repeat $count // else 1\n"
"-s --sense $length // else 18.4.0 = x12 aligned at 4 bytes\n"
"-t --to $fn // else stdout\n"
"-v --verbose\n"
"-w --with $hex // else -w \"AE\"\n"
"-y --yes $hex // else -i x24 -y \"12 00:00:00 24 00\"\n"
"\n" /*" 1234567 1234567 1234567 1234567 1234567 1234567 1234567 tab stops */
"gsc $dev -v -i 0x24 -y \"12 00:00:00 24 00\" // Inquiry\n"
"gsc $dev -v -i 8 -y \"25 00 00:00:00:00 00 00:00 00\" // Read Max LBA\n"
"gsc $dev -v -y \"00 00:00:00 00 00\" // Test Unit Ready\n"
"gsc $dev -v -y \"1B 00:00:00 00 00\" // Stop Unit\n"
"gsc $dev -v -y \"1B 00:00:00 01 00\" // Start Unit\n"
"gsc $dev -v -y \"1B 00:00:00 02 00\" // Stop Then Eject\n"
"...\n"
;
printf("Usage: %s\n\n%s\n\n%s\n", USAGE, st, VERSION);
exit(0);
}
static char const * abbreviate(char const * st)
{
if (strcmp(st, "--align")) return "-a";
if (strcmp(st, "--beyond")) return "-b";
if (strcmp(st, "--compare")) return "-c";
if (strcmp(st, "--each")) return "-e";
if (strcmp(st, "--from")) return "-f";
if (strcmp(st, "--help")) return "-h";
if (strcmp(st, "--in")) return "-i";
if (strcmp(st, "--late")) return "-l";
if (strcmp(st, "--no")) return "-n";
if (strcmp(st, "--out")) return "-o";
if (strcmp(st, "--please")) return "-p";
if (strcmp(st, "--quiet")) return "-q";
if (strcmp(st, "--repeat")) return "-r";
if (strcmp(st, "--sense")) return "-s";
if (strcmp(st, "--to")) return "-t";
if (strcmp(st, "--verbose")) return "-v";
if (strcmp(st, "--with")) return "-w";
if (strcmp(st, "--yes")) return "-y";
return st;
}
static void step(char const * st)
{
if (strcmp(st, "--")) {
interpret_dash = 0;
} else if (strcmp(st, "-a")) { /* align $page $offset */
int l = to_int(arg_read());
int o = to_int(arg_read());
gss_align(gss_first, l, o);
} else if (strcmp(st, "-b")) { /* beyond $length */
int b = to_int(arg_read());
gss_verbose_limit(gss_first, b);
} else if (strcmp(st, "-c")) { /* compare */
interpret_compare = 1;
} else if (strcmp(st, "-e")) { /* each */
gss_each(NULL);
} else if (strcmp(st, "-f")) { /* from $fn */
interpret_from = arg_read();
} else if (strcmp(st, "-h")) { /* help */
helpful_exit();
} else if (strcmp(st, "-i")) { /* in $length */
int i = to_int(arg_read());
gss_in_limit(gss_first, i);
} else if (strcmp(st, "-l")) { /* late $s $ns */
int s = to_int(arg_read());
int ns = to_int(arg_read());
gss_define_late(gss_first, s, ns);
} else if (strcmp(st, "-n")) { /* no $hex */
interpret_yes = 0;
run(arg_read());
} else if (strcmp(st, "-o")) { /* out $length */
int o = to_int(arg_read());
gss_out_limit(gss_first, o);
} else if (strcmp(st, "-p")) { /* please */
interpret_please = 1;
} else if (strcmp(st, "-q")) { /* quiet */
int b = 0;
gss_verbose_limit(gss_first, b);
} else if (strcmp(st, "-r")) { /* repeat $count */
interpret_repeat = to_int(arg_read());
} else if (strcmp(st, "-s")) { /* sense $length $page $offset */
int s = to_int(arg_read());
int l = to_int(arg_read());
int o = to_int(arg_read());
gss_sense_stress(gss_first, s, l, o);
} else if (strcmp(st, "-t")) { /* to $fn */
interpret_to = arg_read();
} else if (strcmp(st, "-v")) { /* verbose */
int b = 1;
gss_verbose_limit(gss_first, b);
} else if (strcmp(st, "-w")) { /* with $hex */
gss_hex_with(gss_first, arg_read());
} else if (strcmp(st, "-y")) { /* yes $hex */
interpret_yes = 1;
run(arg_read());
} else {
char const * name = arg_read();
if ((name[0] == '-') && interpret_dash) {
confused_exit();
}
gss_also(gss_first, name);
}
}
static void interpret(char const * const * argv)
{
args = argv;
while (*args != NULL) {
step(abbreviate(arg_read()));
}
}
int main(int argc, char const * const * argv)
{
char const * const preface[] = {
"--align", "4096", "0",
"--beyond", "0",
"--in", "0",
"--late", "100800", "0", /* 100800 = 28 * 60 * 60 */
"--out", "0",
"--quiet",
"--repeat", "1",
"--sense", "12", "16", "0",
"--with", "AE",
NULL
};
char const * const inquiry[] = {
"--in", "x24", "--yes", "12 00:00:00 24 00",
NULL
};
interpret(preface);
interpret(argv);
if (interpret_yes < 0) {
interpret(inquiry);
}
return 0;
}
/* end of file */
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-07 18:27 ` Pat LaVarre
@ 2003-11-07 18:31 ` Pat LaVarre
2003-11-11 23:52 ` Pat LaVarre
0 siblings, 1 reply; 14+ messages in thread
From: Pat LaVarre @ 2003-11-07 18:31 UTC (permalink / raw)
To: patmans; +Cc: dougg, linux-scsi
Offline kindly I was asked about "documentation".
We have man camcontrol.
Also we have slightly obsolete documentation in place in man page style
as section "3. Syntax" of:
http://members.aol.com/plscsi/
Also we have the PLScsi Tutorial, which I now see coincidentally gives
some of the same examples as man camcontrol:
http://members.aol.com/plscsi/tutorial/
Also from that plscsi/ web site we have such alternatives as:
MTX for SCSI ... Device Control [Linux]
http://mtx.badtux.net/
scu = a SCSI Command Utility [Linux/ Win]
http://www.bit-net.com/~rmiller/scu.html
scsitool [Dos]
http://www.nu2.nu/scsitool/
cizer [Apple Mac OS before X]
...
Pat LaVarre
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-07 18:31 ` Pat LaVarre
@ 2003-11-11 23:52 ` Pat LaVarre
2003-11-14 3:09 ` Douglas Gilbert
2003-11-26 16:15 ` Pat LaVarre
0 siblings, 2 replies; 14+ messages in thread
From: Pat LaVarre @ 2003-11-11 23:52 UTC (permalink / raw)
To: patmans; +Cc: dougg, linux-scsi
The SG_IO analogue in BSD may be:
http://www.google.com/search?q=man+SCIOCCOMMAND
The corresponding struct appears in such sources as:
http://cvsup.pt.freebsd.org/cgi-bin/cvsweb/cvsweb.cgi/src/sys/sys/scsiio.h?rev=1.9.4.2&content-type=text/x-cvsweb-markup&cvsroot=NetBSD
Same as ever, again there we see CDB for length, data for expected
length returning actual length, sense for expected length returning
actual length.
Pat LaVarre
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-11 23:52 ` Pat LaVarre
@ 2003-11-14 3:09 ` Douglas Gilbert
2003-11-26 16:15 ` Pat LaVarre
1 sibling, 0 replies; 14+ messages in thread
From: Douglas Gilbert @ 2003-11-14 3:09 UTC (permalink / raw)
To: Pat LaVarre; +Cc: linux-scsi
Pat LaVarre wrote:
> The SG_IO analogue in BSD may be:
>
> http://www.google.com/search?q=man+SCIOCCOMMAND
>
> The corresponding struct appears in such sources as:
>
> http://cvsup.pt.freebsd.org/cgi-bin/cvsweb/cvsweb.cgi/src/sys/sys/scsiio.h?rev=1.9.4.2&content-type=text/x-cvsweb-markup&cvsroot=NetBSD
>
> Same as ever, again there we see CDB for length, data for expected
> length returning actual length, sense for expected length returning
> actual length.
Pat,
I don't think the above references are correct. FreeBSD has been
using SCSI's Common Access Method (CAM) for some time. Your can
find one document at www.t10.org (drafts section under the SCSI-2
heading). More appropriate is the withdrawn CAM-3 draft standard (see
www.t10.org/ftp/t10/drafts/cam3/cam3r03.pdf ). That is where you
will find the structure sg_io_hdr was modelled on (struct ccb_scsiio3).
Another way to find SCSI pass-through mechanisms is to look
at Joerg Schilling's libscg. A simpler way may be to look at
smartmontools ( smartmontools.sourceforge.net ) and compare
os_linux.c , os_freebsd.c and os_solaris.c
Doug Gilbert
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
2003-11-11 23:52 ` Pat LaVarre
2003-11-14 3:09 ` Douglas Gilbert
@ 2003-11-26 16:15 ` Pat LaVarre
1 sibling, 0 replies; 14+ messages in thread
From: Pat LaVarre @ 2003-11-26 16:15 UTC (permalink / raw)
To: linux-scsi
> again there we see CDB for length, data for expected
> length returning actual length, sense for expected length returning
> actual length.
ftp://members.aol.com/plscsi/linux/plscsi.tar.gz
says g++ rather than gcc in that Makefile for the sake of that minority
of folk who have gcc/g++ configured so that gcc fails to link after
compiling .cpp.
http://members.aol.com/plscsi/linux/plscsi.tar.gz
fetches the same, but via http rather than via ftp.
Neither, whoops, yet give us the following popular patch that often
makes such commands work as:
plscsi /dev/hdc
plscsi /dev/hdd
plscsi /dev/scd0
Pat LaVarre
diff -Nur plscsi.2002-09-21/sgio.cpp plscsi/sgio.cpp
--- plscsi.2002-09-21/sgio.cpp 2002-09-21 13:25:18.000000000 -0600
+++ plscsi/sgio.cpp 2003-11-26 09:10:59.109906736 -0700
@@ -116,6 +116,7 @@
sgio->theErrFile = stderr;
sgio->theOpenMode = O_RDWR; /* O_RDONLY often works */
+ sgio->theOpenMode = O_RDONLY|O_NONBLOCK;
sgio->theFileDescriptor = -1;
sgio->theSgVersionNum = 0; /* 0 = unknown */
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
@ 2003-11-27 17:15 Pat LaVarre
0 siblings, 0 replies; 14+ messages in thread
From: Pat LaVarre @ 2003-11-27 17:15 UTC (permalink / raw)
To: linux-scsi
> ftp://members.aol.com/plscsi/linux/plscsi.tar.gz
> http://members.aol.com/plscsi/linux/plscsi.tar.gz
> ...
> Neither, whoops, yet give us ...
> - O_RDWR
> + O_RDONLY|O_NONBLOCK
> ... SG_IO ... ioctl ...
Fixed.
However, I dreamed up this patch only by guessing from hints found on
the web, not from reading a document anywhere. At first glance
O_RDONLY | O_NONBLOCK works better than O_RDWR. No disk required, no
disk spin up implied, even when the name is /dev/hd$v or /dev/scd$v$n
rather than /dev/sg$n. But as yet I'm none too sure what this change
actually means.
Pat LaVarre
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: sg utils sg_io -i 0x24 -y "12 00:00:00 24 00"
@ 2003-12-03 0:17 Pat LaVarre
0 siblings, 0 replies; 14+ messages in thread
From: Pat LaVarre @ 2003-12-03 0:17 UTC (permalink / raw)
To: linux-scsi
> > - O_RDWR
> > + O_RDONLY|O_NONBLOCK
> ...
> I dreamed up this patch only by guessing from
> hints found on the web, not from reading a
> document anywhere.
Possibly we recommend open O_NONBLOCK for SG_IO.
Evidence in favour of that conjecture includes the following, not close
to block/scsi_ioctl.c in the kernel source, but yes close in author
space:
---
From: linux-2.6.0-test11/Documentation/cdrom/cdrom-standard.tex
...
1997/12/28 ...
...
We therefore propose to use the flag $O_NONBLOCK$ to indicate
that the device is opened just for issuing $ioctl$
commands. Strictly, the meaning of $O_NONBLOCK$ is that opening and
subsequent calls to the device don't cause the calling process to
wait. We could interpret this as ``don't wait until someone has
inserted some valid data-\cdrom.'' Thus, our proposal of the
implementation for the $open()$ call for \cdrom s is:
...
\begin{itemize}
...
\item If no other flags are set than $O_RDONLY$, the device is opened
for data transfer, and the return value will be 0 only upon successful
initialization of the transfer. The call may even induce some actions
on the \cdrom, such as closing the tray.
...
\item If the option flag $O_NONBLOCK$ is set, opening will always be
successful, unless the whole device doesn't exist. The drive will take
no actions whatsoever.
...
\end{itemize}
---
Pat LaVarre
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2003-12-03 0:18 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-11-07 0:38 sg utils sg_io -i 0x24 -y "12 00:00:00 24 00" Pat LaVarre
2003-11-07 16:24 ` Pat LaVarre
2003-11-07 16:56 ` Pat LaVarre
2003-11-07 17:09 ` Pat LaVarre
2003-11-07 17:17 ` Pat LaVarre
2003-11-07 17:51 ` Patrick Mansfield
2003-11-07 18:11 ` Pat LaVarre
2003-11-07 18:27 ` Pat LaVarre
2003-11-07 18:31 ` Pat LaVarre
2003-11-11 23:52 ` Pat LaVarre
2003-11-14 3:09 ` Douglas Gilbert
2003-11-26 16:15 ` Pat LaVarre
-- strict thread matches above, loose matches on Subject: below --
2003-11-27 17:15 Pat LaVarre
2003-12-03 0:17 Pat LaVarre
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).