~~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