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.).