~~ODT~~
===== DATA RETRIEVAL =====
==== 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; 
    }; 
SCSI INQUIRY CDB structure
 
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; 
    }; 
SCSI READ CAPACITY CDB structure. 
 
 
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: 
a. IOCTL_SCSI_GET_INQUIRY_DATA 
b. IOCTL_SCSI_GET_CAPABILITIES 
c. IOCTL_SCSI_PASS_THROUGH 
d. IOCTL_SCSI_PASS_THROUGH_DIRECT 
 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 IOCTL_SCSI_PASS_THROUGH uses the SCSI_PASS_THROUGH structure. The 
IOCTL_SCSI_PASS_THROUGH_DIRECT uses the SCSI_PASS_THROUGH_DIRECT 
structure. 
 
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]; 
    } 
SCSI_PASS_THROUGH structure
 
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. 
{{ :ch10_handbook:stanag_directory_algorithm.png |}}
STANAG 4575 directory reading and decoding algorithm