User Tools

Site Tools


Export page to Open Document format


Small Computer Systems Interface (SCSI) Protocol

Recorded data from a Chapter 10 recorder is retrieved by transferring it to a host computer over one of several interfaces provided by the recorder. Chapter 10 requires that each Removable Memory Module (RMM) provide an IEEE 1394b standard data download port. Chapter 10 also requires that each recorder provide either a Fibre Channel or IEEE 1394b data download port and, optionally, an Ethernet download port.

The protocol for data download over the various interface types is the Small Computer Systems Interface (SCSI) block transfer protocol. Overall SCSI operation is defined in the SCSI Architecture Model 2 (SAM-2) document. Common commands are defined in the SCSI Primary Commands (SPC-2) document. Commands for block devices are defined in SCSI Block Commands 2 (SBC-2) document.

The SCSI architecture is a client-server model. The client is the user application (the “initiator”), requesting services (status, data, etc.) from the SCSI server device (the “target”). An application client is independent of the underlying interconnect and SCSI transport protocol. Each SCSI target is identified by a target device name. Targets are addressed using the target device name. Different transports support different methods for uniquely naming SCSI targets. Each target device also supports one or more Logical Unit Numbers (LUNs). Logical Unit Numbers are used to support different services from a single SCSI target device. For example, an RMM provides disk file access using LUN 0, and Real Time Clock access using LUN 1.

The SAM defines a Command Descriptor Block (CDB) structure along with associated user input and output buffers. The CDBs are used to issue commands to SCSI devices. The SCSI protocol defines a large number of commands to support a wide range of devices. The Chapter 10 standard only requires a small subset of the complete SCSI command set to be implemented to support the RMM and remote data access block transfer device. A CDB can be 6, 10, 12, or 16 bytes in length. Chapter 10 currently only requires 6 and 10-byte CDBs. Note that multi-byte CDB values such as a Logical Block Address (LBA) are big endian in the CDB and require writing to the CDB a byte at a time from a little-endian processor to write the multi-byte values in proper order.

The SCSI INQUIRY command is used to query the SCSI device about its capabilities. The structures for the INQUIRY CDB and the Control field are shown below.

struct SuCdbInquiry 
    uint8_t uOpCode; // Operation code = 0x12 
    uint8_t bEVPD : 1; // Enable vital product data 
    uint8_t bCmdDt : 1; // Command support data 
    uint8_t Reserved1 : 6; // 
    uint8_t uPageOpCode; // Page or operation code 
    uint8_t Reserved2; // 
    uint8_t uAllocLength; // Allocation length 
    struct SuCdbControl suControl; 


struct SuCdbControl 
    uint8_t bLink : 1; 
    uint8_t Obsolete : 1; 
    uint8_t bNACA : 1; 
    uint8_t Reserved : 3; 
    uint8_t uVendor : 2; 

SCSI CDB Control field structure

The data download interface is required to support the standard INQUIRY response shown in the structure below. Also required are the Supported Vital Product page, Unit Serial Number page, and Device Identification page.

struct SuCdbInquiryStdData 
    uint8_t uPeriphType     : 5;    // Peripheral device type 
    uint8_t uPeriphQual     : 3;    // Peripheral qualifier 
    uint8_t uReserved1      : 7; 
    uint8_t bRMB            : 1;    // Removable medium 
    uint8_t uVersion;               // Version 
    uint8_t uFormat         : 4;    // Response data format 
    uint8_t bHiSup          : 1;    // Hierarchical support 
    uint8_t bNormACA        : 1;    // Support normal ACA bit 
    uint8_t uReserved2      : 1; 
    uint8_t bAERC           : 1;    // Asynchronous event reporting cap 
    uint8_t uAddLength;             // Length of additional parameters 
    uint8_t uReserved3      : 7; 
    uint8_t bSCCS           : 1;    // Embedded storage array supported 
    uint8_t bAddr16         : 1;    // Not used 
    uint8_t uReserved4      : 2; 
    uint8_t bMChngr         : 1;    // Medium changer 
    uint8_t bMultiP         : 1;    // Multi-port device 
    uint8_t bVS1            : 1;    // Vendor specific 
    uint8_t bEncServ        : 1;    // Enclosure service 
    uint8_t bBQue           : 1;    // Basic queing 
    uint8_t bVS2            : 1;    // Vendor specific 
    uint8_t bCmdQue         : 1;    // Command queuing supported 
    uint8_t uReserved5      : 1; 
    uint8_t bLinked         : 1;    // Linked commands supported 
    uint8_t bSync           : 1;    // Not used 
    uint8_t bWBus16         : 1;    // Not used 
    uint8_t uReserved6      : 1; 
    uint8_t bRelAddr        : 1;    // Relative addressing supported 
    uint8_t uVendorID[8];           // 
    uint8_t uProductID[16];         // 
    uint8_t uProductRev[4];         // 

SCSI INQUIRY data structure

The SCSI READ CAPACITY command is used to query the disk device about its size. The structure for the READ CAPACITY CDB is shown below.

struct SuCdbReadCapacity10 
    uint8_t uOpCode;            // Operation code = 0x25 
    uint8_t uReserved1;         // 
    uint8_t uLBA_3_MSB;         // Logical block address, MSB 
    uint8_t uLBA_2;             // Logical block address 
    uint8_t uLBA_1;             // Logical block address 
    uint8_t uLBA_0_LSB;         // Logical block address, LSB 
    uint8_t uReserved2;         // 
    uint8_t uReserved3;         // 
    uint8_t bPMI        : 1;    // Partial medium indicator 
    uint8_t uReserved3  : 7;    // 
    struct SuCdbControl suControl; 


This command returns the number of available logical blocks and the logical block size in bytes, shown in the structure below. Note that returned values are big endian and must be byte swapped before they can be used on a little endian processor.

struct SuCdbReadCapacityData 
    uint64_t uBlocks;           // Logical blocks (big endian!) 
    uint64_t uBlockSize;        // Block size (big endian!) 

SCSI READ CAPACITY data structure

The SCSI READ command is used to read logical blocks of data from the disk device. The SCSI protocol provides five different READ commands with various capabilities and sizes of the CDB. The Chapter 10 standard only requires the 10 byte variant of the READ command. The structure for the READ CDB is shown below. This command returns the data from the requested logical blocks.

struct SuCdbRead10 
    uint8_t uOpCode;            // Operation code = 0x28 
    uint8_t bReserved1  : 1;    // 
    uint8_t bFUA_NV     : 1;    // Force unit access non-volatile 
    uint8_t Reserved2   : 1;    // 
    uint8_t bFUA        : 1;    // Force unit access 
    uint8_t bDPO        : 1;    // Disable page out 
    uint8_t bRdProtect  : 3;    // Read protect 
    uint8_t uLBA_3_MSB;         // Logical block address, MSB 
    uint8_t uLBA_2;             // Logical block address 
    uint8_t uLBA_1;             // Logical block address 
    uint8_t uLBA_0_LSB;         // Logical block address, LSB 
    uint8_t uGroupNum   : 5;    // Group number 
    uint8_t Reserved3   : 3;    // 
    uint8_t uTransLength_1_MSB; // Transfer length, MSB 
    uint8_t uTransLength_0_LSB; // Transfer length, LSB 
    struct SuCdbControl suControl; 

SCSI READ(10) CDB structure

IEEE 1394

IEEE 1394 defines the Serial Bus Protocol (SBP-2) for transporting CDBs and data over a 1394 bus to a SCSI target. The basic unit of information in SBP-2 is the Operation Request Block (ORB). The ORBs encapsulate the information in SCSI CDBs and input/output buffers, as well as additional information needed by the 1394 bus. The 1394 bus operates by exposing a shared memory address space, negotiated during device initialization. CDBs carried within SBP packets are written to the SCSI target device shared memory, and associated data is written to and read from shared memory.

When interfacing to an RMM, LUN 0 is used for disk access. LUN 1 is used for interfacing to the RMM Real Time Clock.

When interfacing to a recorder, LUN 0 is used for disk access.

Fibre Channel

Fibre Channel defines the Fibre Channel Protocol (FCP) for transporting CDBs and data over a Fibre Channel bus to a SCSI target. The basic unit of information in FCP is the Information Unit (IU). FCP defines several types of IUs used to communicate with SCSI targets. Fibre Channel also defines the Fibre Channel Private Loop (FCPL) SCSI Direct Attach (FC-PLDA) protocol. The FC-PLDA further defines the implementation of SCSI over Fibre Channel. Chapter 10 requires conformance to FC-PLDA.

Internet Small Computer Systems Interface (iSCSI)

The Internet Engineering Task Force (IETF) has published Request For Comment (RFC) 3270 defining the iSCSI protocol for transporting CDBs over Transmission Control Protocol/Internet Protocol (TCP/IP) based network to an SCSI target. Chapter 10 identifies iSCSI as the standard protocol for recorder data access over Ethernet. The basic unit of information in iSCSI is the Protocol Data Unit (PDU). The PDUs encapsulate the information in SCSI CDBs and input/output buffers as well as additional information needed by the underlying IP network. The PDUs are transported over a TCP connection, usually using well known port number 860 or 3260. The actual port number used is not specified in Chapter 10.

For an iSCSI initiator to establish an iSCSI session with an iSCSI target, the initiator needs the IP address, the TCP port number, and the iSCSI target name information. There are several methods that may be used to find targets. An iSCSI supports the following discovery mechanisms:

  • Static Configuration: This mechanism assumes that the IP address, TCP port, and the iSCSI target name information are already available to the initiator. The initiators need to perform no discovery in this approach. The initiator uses the IP address and the TCP port information to establish a TCP connection; it also uses the iSCSI target name information to establish an iSCSI session. This discovery option is convenient for small iSCSI setups.
  • SendTargets: This mechanism assumes that the target's IP address and TCP port information are already available to the initiator. The initiator then uses this information to establish a discovery session to the Network Entity. The initiator then subsequently issues the SendTargets text command to query information about the iSCSI targets available at the particular Network Entity (IP address).
  • Zero-Configuration: This mechanism assumes that the initiator does not have any information about the target. In this option, the initiator can either multicast discovery messages directly to the targets or it can send discovery messages to storage name servers. Currently, there are many general purpose discovery frameworks available. Service Location Protocol (SLP [RFC2608] and Internet Storage Name Service (iSNS [iSNS]) are two popular discovery protocols.

Target discovery is not specified in Chapter 10.

When interfacing to a recorder, LUN 0 or LUN 32 is used for disk access. For command and control, LUN 1 or LUN 33 is used.

Software Interface

All recorder data download interfaces appear as SCSI block Input/Output (I/O) devices, and respond to the subset of SCSI commands set forth in Chapter 10. However, different operating systems provide vastly different types of Application Programming Interfaces (API) for communicating with recorders and RMMs over the various data download interfaces specified in Chapter 10.

The Microsoft Windows device driver environment helps remove a lot of complexity from communicating over the various data interfaces. Windows plug and play drivers are able to discover various types of SCSI devices connected to them, to initialize and configure them, and then offer a single programming interface for user application programs.

The interface used by Windows application to send SCSI commands to a SCSI device is called SCSI Pass Through (SPT). Windows applications can use SPT to communicate directly with SCSI devices using the Win32 API DeviceIoControl() call and the appropriate I/O control (IOCTL) code.

Before any IOCTLs can be sent to a SCSI device, a handle for the device must be obtained. The Win32 API CreateFile() is used to obtain this handle and to define the sharing mode and the access mode. Note that Windows may require security priviledges above those normally granted to a regular user to call CreateFile(). The access mode must be specified as (GENERIC_READ | GENERIC_WRITE). The key to obtaining a valid handle is to supply the proper filename for the device that is to be opened.

For Chapter 10 SCSI devices, the SCSI class driver defines an appropriate name. If the device is unclaimed by a SCSI class driver (the usual case), then a handle to the SCSI port driver is required. The filename in this case is “\\.\ScsiN:”, where N = 0, 1, 2, etc. The number N corresponds to the SCSI host adapter card number that controls the desired SCSI device. When the SCSI port name is used, the Win32 application must set the proper PathId, TargetId, and LUN in the SCSI pass through structure.

Once a valid handle to a SCSI device is obtained, then appropriate input and output buffers for the requested IOCTL must be allocated and, in some cases, filled in correctly.

There are several IOCTLs that the SCSI port driver supports; these include:


The IOCTL_SCSI_GET_INQUIRY_DATA returns a SCSI_ADAPTER_BUS_INFO structure for all devices that are on the SCSI bus. The structure member, BusData, is a structure of type SCSI_BUS_DATA; it contains an offset to the SCSI Inquiry data, which is also stored as a structure, SCSI_INQUIRY_DATA.

The SCSI_INQUIRY_DATA structure contains a member named DeviceClaimed. DeviceClaimed indicates whether or not a class driver has claimed this particular SCSI device. If a device is claimed, all SCSI pass through requests must be sent first through the class driver, which will typically pass the request unmodified to the SCSI port driver. If the device is unclaimed, the SCSI pass through requests are sent directly to the SCSI port driver.

For IOCTL_SCSI_GET_INQUIRY_DATA, no data is sent to the device; data is only read from the device. Set lpInBuffer to NULL and nInBufferSize to zero. The output buffer might be quite large, as each SCSI device on the bus will provide data that will fill three structures for each device: SCSI_ADAPTER_BUS_INFO, SCSI_BUS_DATA, and SCSI_INQUIRY_DATA. Allocate a buffer that will hold the information for all the devices on that particular SCSI adapter. Set lpOutBuffer to point to this allocated buffer and nOutBufferSize to the size of the allocated buffer.

The IOCTL_SCSI_GET_CAPABILITIES returns an IO_SCSI_CAPABILITIES structure. This structure contains valuable information about the capabilities of the SCSI adapter. Two items of note are the MaximumTransferLength, which is a byte value indicating the largest data block that can be transferred in a single SCSI Request Block (SRB), and the MaximumPhysicalPages, which is the maximum number of physical pages that a data buffer can span.

The two IOCTLs (IOCTL_SCSI_PASS_THROUGH and IOCTL_SCSI_PASS_ THROUGH_DIRECT) allow SCSI Command Descriptor Blocks (CDB) to be sent from a Win32 application to a SCSI device. Depending on which IOCTL is sent, a corresponding pass through structure is filled out by the Win32 application.


The SCSI_PASS_THROUGH structure is shown below.

    USHORT Length; 
    UCHAR ScsiStatus; 
    UCHAR PathId; 
    UCHAR TargetId; 
    UCHAR Lun; 
    UCHAR CdbLength; 
    UCHAR SenseInfoLength; 
    UCHAR DataIn; 
    ULONG DataTransferLength; 
    ULONG TimeOutValue; 
    ULONG DataBufferOffset; 
    ULONG SenseInfoOffset; 
    UCHAR Cdb[16]; 


The structures SCSI_PASS_THROUGH and SCSI_PASS_THROUGH_DIRECT are virtually identical. The only difference is that the data buffer for the SCSI_PASS_THROUGH structure must be contiguous with the structure. This structure member is called DataBufferOffset and is of type ULONG. The data buffer for the SCSI_PASS_THROUGH_DIRECT structure does not have to be contiguous with the structure. This structure member is called DataBuffer and is of type PVOID.

For the two SCSI pass through IOCTLs, IOCTL_SCSI_PASS_THROUGH and IOCTL_SCSI_PASS_THROUGH_DIRECT, both lpInBuffer and lpOutBuffer can vary in size depending on the Request Sense buffer size and the data buffer size. In all cases, nInBufferSize and nOutBufferSize must be at least the size of the SCSI_PASS_THROUGH (or SCSI_PASS_THROUGH_DIRECT) structure. Once the appropriate input and output buffers have been allocated, then the appropriate structure must be initialized.

The Length is the size of the SCSI_PASS_THROUGH structure. The ScsiStatus should be initialized to 0. The SCSI status of the requested SCSI operation is returned in this structure member. The PathId is the bus number for the SCSI host adapter that controls the SCSI device in question. Typically, this value will be 0, but there are SCSI host adapters that have more than one SCSI bus on the adapter. The TargetId and Lun are the SCSI ID number and logical unit number for the device.

The CdbLength is the length of the CDB. Typical values are 6, 10, and 12 up to the maximum of 16. The SenseInfoLength is the length of the SenseInfo buffer. DataIn has three possible values; SCSI_IOCTL_DATA_OUT, SCSI_IOCTL_DATA_IN and SCSI_IOCTL_DATA_UNSPECIFIED. The DataTransferLength is the byte size of the data buffer. The TimeOutValue is the length of time, in seconds, until a time-out error should occur; this can range from 0 to a maximum of 30 minutes (1800 seconds).

The DataBufferOffset is the offset of the data buffer from the beginning of the pass through structure. For the SCSI_PASS_THROUGH_DIRECT structure, this value is not an offset, but rather is a pointer to a data buffer. The SenseInfoOffset is similarly an offset to the SenseInfo buffer from the beginning of the pass through structure. Finally, the sixteen remaining bytes are for the CDB data. The format of this data must conform to the SCSI-2 standard.

Standardization Agreement (STANAG) 4575 Directory

Chapter 10 recorders and RMMs make their data available for downloading over one of their supported download ports. To the application program, the data download port appears as a block I/O disk device at SCSI LUN 0. The directory structure on the disk is a modified version of the STANAG 4575 file structure definition. The STANAG file system has been developed to enable the downloading of very large sequential files into support workstations. It supports only logically contiguous files in a single directory. The data can be physically organized any way appropriate to the media, including multiple directories, as long as the interface to the NATO Advanced Data Storage Interface (NADSI) “sees” a single directory of files in contiguous logical addresses.

Disk blocks are accessed by Logical Block Address (LBA). It is common in many operating systems (OSs) and disk structures for block 0 to be a Master Boot Record (MBR). An MBR typically contains OS boot code and/or information for dividing a disk device into multiple partitions. Chapter 10 does not support MBRs or partitions. Block 0 is considered reserved, and its contents are undefined and unused.

The beginning of the STANAG directory is always read from logical block 1. The complete disk directory may span multiple disk blocks. Directory blocks are organized as a double linked list of blocks. Other than the first directory block, subsequent directory blocks can be any arbitrary block number.

A STANAG 4575 directory block has the structure shown below. IRIG 106-03 and IRIG 106-04 defined the STANAG 4575 directory data as “little-endian.” Subsequent IRIG 106 versions have defined directory data as “big-endian.” Applications can test the achMagicNumber and uRevLink values to determine whether big-endian or little-endian is being used. If big-endian is being used, multi-byte values will need to be byte swapped before they can be used on a little endian processor such as an Intel x86 found in desktop computers. The various fields in the directory block are covered in detail in the Chapter 10 standard.

struct SuStanag4575DirBlock 
    uint8_t achMagicNumber[8]   // "FORTYtwo" 
    uint8_t uRevNumber;         // IRIG 106 Revision number 
    uint8_t uShutdown;          // Dirty shutdown 
    uint16_t uNumEntries;       // Number of file entries 
    uint32_t uBlockSize;        // Bytes per block 
    uint8_t achVolName[32];     // Volume Name 
    uint64_t uFwdLink;          // Forward link block 
    uint64_t uRevLink;          // Reverse link block 
    struct SuStanag4575FileBlock asuFileEntry[4]; 

STANAG 4575 Directory Block structure

The asuFileEntry[] array holds information about individual files. Its structure is shown below. The size of the asuFileEntry[] array will vary depending on the disk block size. For a size of 512 bytes per disk block, the asuFileEntry[] array will have four elements.

struct SuStanag4575FileBlock 
    uint8_t achFileName[56];    // File name 
    uint64_t uFileStart;        // File start block addr 
    uint64_t uFileBlkCnt;       // File block count 
    uint64_t uFileSize;         // File size in bytes 
    uint8_t uCreateDate[8];     // File create date 
    uint8_t uCreateTime[8];     // File create time 
    uint8_t uTimeType;          // Date and time type 
    uint8_t achReserved[7];     // 
    uint8_t uCloseTime[8];      // File close time 

STANAG 4575 File Entry structure

A complete disk file directory is read starting at LBA 1. The first directory block is read and all file entries in that block are read and decoded. Then the next directory block, LBA equal to the value in uFwdLink, is read and decoded. Directory reading is finished when the uFwdLink equals the current LBA. This algorithm is shown in below.

STANAG 4575 directory reading and decoding algorithm

ch10_handbook/data_retrieval.txt · Last modified: 2014/05/29 14:34 by bob