This file contains a comparison between the old sg_header interface
of the Linux 'sg' driver, the new interface as introduced by Heiko Eißfeldt
and Jörg Schilling and the interface used by Douglas Gilbert.

After reading this text, you will be able to decide by your own which interface
is better for a new and enhanced 'sg' driver.

In its original form, the sg_header looked like this:

struct sg_header {
    int pack_len;
    int reply_len;
    int pack_id;
    int result;
    unsigned int twelve_byte:1;
    unsigned int other_flags:31;
    unsigned char sense_buffer[16];
};

It has the following problems:

-	It cannot see if a SCSI command could not be sent at all. 

-	It cannot get the SCSI status byte.  
	Cdrecord for that reason cannot report failing SCSI commands in some 
	situations. 
	The developers of the SANE project have been irritated when realising
	on Solaris that a scanner often return BUSY status on some commands.
	This is invisible on Linux.

-	It cannot get real DMA count of transfer.  
	Cdrecord cannot tell you if there is an DMA residual count. 

	This makes it impossible to use Linux to develop SCSI applications.
	If a developer cannot see if his new program interacts the right way with the drive,
	and if the drive really transfers the assumed number of bytes for a command,
	it is possible that the new application will not work correctly.

-	It cannot get number of bytes valid in auto sense data. 
	Cdrecord cannot tell you if device transfers no sense data at all. 

-	It fetches to few data in auto request sense (CCS/SCSI-2/SCSI-3 needs >= 18).

	SCSI-2 compliant and newer drives often include a pointer to the exact position
	of an illegal bit in the SCSI command. On Linux you cannot see this hint.

-	It cannot send SCSI commands with vendor unique lengths.


For this reason, Heiko Eißfeldt and I (Jörg Schilling) added a new interface to the sg driver
in April 1998 and the sg_header structure now looks this way:

struct sg_header {
/*
 * cmd_status contains:
 * driver_byte << 24 | host_byte << 16 | msg_byte << 8 | status_byte
 */
#define sg_cmd_status   pack_len
  int pack_len;			/* [i] length of incoming packet (including header) / [o] command status */
  int reply_len;		/* [i] maximum length of expected reply / [o] actual transfer count */
  int pack_id;			/* [i/o] id number of packet */
  int result;			/* [o] 0==ok, otherwise refer to errno codes */
  unsigned int twelve_byte :1;	/* [i] OBSOLETE: Force 12 byte command length (unused if want_new is set) */
  unsigned int want_new    :1;	/* [i] User requests new behavior */
  unsigned int grant_new   :1;	/* [o] Driver grants new behavior */
  unsigned int cdb_len     :5;	/* [i] Command descriptor block length 6..31 (mandatory) */
  unsigned int sense_len   :5;	/* [i/o] Set max / get actual sense length 0..31 (mandatory) */
  unsigned int other_flags :19;	/* for future use */
  unsigned char sense_buffer[SG_MAX_SENSE];/* [o] used only by reads */
				/* XXX mid-level currently only allocates 16 bytes to sense data,
				 * XXX this violates CCS, SCSI-2, SCSI-3, but upgrading would
				 * XXX break sg binary compatibility. If the mid-level is corrected,
				 * XXX we need to introduce a ioctl to read the sense data.
				 */
  /* command follows then data for command */
 };

-	It uses the (formerly) input only member pack_len to send back the SCSI cmd status.
	The format of the SCSI cmd status is identical to the format used inside the
	Linux kernel.

-	It defines the reply len to return the actual transfer count on return, so once the SCSI
	mid level layer supports this feature, it may be used.

-	It defines the twelve byte member to be obsolete and introduces a new field
	'cdb_len' instead.

-	It defines a new member 'sense_len' to contain the number of valid sense bytes
	in the sense_buffer.
	On input, this is used to define a maximum sense len for output.

-	It keeps 19 bits for future enhancements.

This new interface is up and downwards compatible in binary and source.
The new interface is ordered from the driver by setting the 'want_new' flag and if the
driver sets the 'grant_new' flag on return, the application may rely on the returned
sg_header structure to conform to the new interface. All software that currently
uses the Linux 'sg' driver has been tested to be compatible with this interface.

This interface has been defined in April 1998, intensively tested and published on
July 21th 1998.


Douglas Gilberts sg_header looks this way:

struct sg_header
{
    int pack_len;    /* [o] reply_len (ie useless) ignored as input */
    int reply_len;   /* [i] max length of expected reply (inc. sg_header) */
    int pack_id;     /* [io] id number of packet (use ints >= 0) */
    int result;      /* [o] 0==ok, else (+ve) Unix errno code (e.g. EIO) */
    unsigned int twelve_byte:1;
        /* [i] Force 12 byte command length for group 6 & 7 commands  */
    unsigned int target_status:5;   /* [o] scsi status from target */
    unsigned int host_status:8;     /* [o] host status (see "DID" codes) */
    unsigned int driver_status:8;   /* [o] driver status+suggestion */
    unsigned int other_flags:10;    /* unused */
    unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases:
           when target_status is CHECK_CONDITION or 
           when target_status is COMMAND_TERMINATED or
           when (driver_status & DRIVER_SENSE) is true. */
};      /* This structure is 36 bytes long on i386 */

This interface has the following advantages compared to the interface 
from Heiko and me:

	% none

This interface has the following disadvantages compared to the interface 
from Heiko and me:

-	It hides the SCSI message byte from the user.
	As Douglas Gilbert's "driver enhancements" are intended to support
	tagged command queuing, knowledge of the message byte highly
	recommended.

-	Although the Linux kernel data structures hold the original
	and unmodified SCSI status byte as obtained from the SCSI host adapter,
	Douglas Gilbert's interface introduces artificial restrictions:

	-	Only 5 of the 8 SCSI status bits are available from user
		space. As the hidden bits from the status byte are defined
		"reserved" by the SCSI standard, it could happen that 
		the SCSI standard defines these bits to be included in
		future standards. Creating an interface with such 
		limitations will then prevent access to the newly defined 
		information.

		In addition, Douglas Gilbert uses internal kernel macros
		to right shift the status byte by one. This makes no sense
		and results in user land data that differs from the SCSI
		standard without a reason.

-	It does not allow to specify vendor unique SCSI cdb lengths.		
	
-	It does not allow the user to see whether SCSI sense data is actually
	available. The only way to check for arrived sense data is to
	check for nonzero fields inside the sense buffer.


Douglas Gilbert send me a mail on Sept. 22th 1998, two months after we published 
our SG patch. In his mail he send me his patches and asked whether I would 
agree on the new interface. I send him an answer that I would rather like to see
our interface but never got any answer from him that could show me that he
is willing to discuss the interface.


..... Now some time has gone and unfortunately, Alan Cox send the driver 
with Douglas Gilbert's interface to Linus although he promised me that he 
will wait until we have agreed on the best way to enhance the sg interface.

I would suggest to act in the following way:

Linux-2.2.x is considered to be stable, so no interface changes should be 
introduced to any driver. As the driver modes from Douglas Gilbert are 
compatible to the old 'sg' interface, we could simply ignore Douglas 
Gilbert's interface changes and wait for 2.3.x kernels to upcome and
then introduce the better interface which has been defined by Heiko and me.

--------------------------------------------------------------------------------

A discussion of the ioctl() interface that comes with Douglas Gilbert's 
sg changes will be added soon. 

As a quick preview, I can tell that it offers access to interfaces and
driver internals that should rather be hidden from user space as they 
are part of the driver abstraction.

Here is a short example:

The new ioctl SG_SET_FORCE_LOW_DMA is something that should never be accessible
from user space. Note that such an user interface may fail to port to other 
Linux platforms (like Sparc etc.).

