Chapter 6. Programming a Drive Control Program (DCP)

This chapter provides a tutorial to DCP programming, and includes the following topics:

6.1. About the DCP

A DCP (drive control program) translates between the OpenVault ADI and the actual device control interface for its drive, and between device responses and ADI/R. The DCP does what is necessary to affect the required ADI semantics. It keeps the MLM server's cache (persistent store) up to date regarding DCP configuration, drive configuration, and ready state information. To do this, the DCP sends config and ready commands when it detects changes in state, on a best-effort basis.

6.1.1. Use of Persistent Storage

Currently, the drive configuration and state is moved in one direction only, from a DCP to the MLM server persistent store. The MLM server uses this information to assist with drive selection for cartridge and volume mounts. In future revisions of OpenVault, the DCP may recover some state from the persistent store, so that configuration and state information can flow in both directions. However, the DCP and drive are always considered the authoritative source for state information about a DCP or its drive.

6.1.2. DCP Configuration

In sample implementations, DCP configuration is stored in a configuration file that is local to each DCP. See Section 6.2.1, for more information.

6.2. Initialization Issues

Each DCP must initialize itself in order to contact the MLM server.

Drives may be connected to multiple hosts and thus have multiple control paths. There can be one DCP associated with each control path. Only one DCP at a time may be active for any drive; the MLM server arbitrates which DCP is active.

For example, a DCP could be on the inactive side of a multiconnected library. The DCP boot sequence must not interfere with the active side of a multiconnected library. The MLM server is the arbitrator of control for multiconnected libraries and drives. A DCP should not assume that it is controlling a drive until the MLM server says so.

6.2.1. Configuration File

Each DCP should have a configuration file containing at least the following information:

Address of the controlling MLM server 

This allows the DCP to initiate contact with the controlling MLM server. It is the name of the system, or its numeric IP address. The MLM server is usually available at well-known port number on that system, by default 44444.

OpenVault name for the managed drive 

The MLM server uses this name as an identifier for this physical drive. This is the name of the device that it is managing, not the name of the particular instance of DCP. All names must be unique within an OpenVault domain so that the server can detect multiconnected libraries (multiple LCPs controlling the same library).

DCP instance name 

The instance name is arbitrary, but is required for cases where there are multiconnected libraries.

Control path to the drive 

This is how a DCP talks to the hardware (for example, /dev/rmt/tps0d3). This information is not visible to the MLM server. Some drives are not controlled in this way (VHS videocassette players, for instance), but all DCP implementations need something equivalent.

List of access mode names and access capabilities for this drive  

Although implementation-dependent, a way is needed for administrators to control the capabilities that a DCP advertises to the server. In IRIX implementations, the DCP configuration file, such as shown in Example 6-1, is used. It lists drive names and associated capabilities, which are string tokens. The OpenVault server compares these tokens for equality when looking for drives to satisfy user requests.

Example 6-1. DCP config File

All lines would be prefaced with “cap” in this example:

   name  type   cartridge    shorthand   capacity  device pathname                     slot type 
   7base  DLT DLT7000 DLT7000   35000 /dev/rmt/tps3d5.7000      DLT7000 capabilities 
   7s     DLT DLT7000 DLT7000s  35000 /dev/rmt/tps3d5s.7000     DLT7000 capabilities 
   7nr    DLT DLT7000 DLT7000   35000 /dev/rmt/tps3d5nr.7000    DLT7000 capabilities 
   7nrs   DLT DLT7000 DLT7000s  35000 /dev/rmt/tps3d5nrs.7000   DLT7000 capabilities 
   7c     DLT DLT7000 DLT7000c  70000 /dev/rmt/tps3d5.7000c     DLT7000 capabilities 
   7sc    DLT DLT7000 DLT7000cs 70000 /dev/rmt/tps3d5s.7000c    DLT7000 capabilities 
   7nrc   DLT DLT7000 DLT7000c  70000 /dev/rmt/tps3d5nr.7000c   DLT7000 capabilities 
   7nrsc  DLT DLT7000 DLT7000cs 70000 /dev/rmt/tps3d5nrs.7000c  DLT7000 capabilities 
   7v     DLT DLT7000 DLT7000   35000 /dev/rmt/tps3d5v.7000     DLT7000 capabilities 
   7sv    DLT DLT7000 DLT7000s  35000 /dev/rmt/tps3d5sv.7000    DLT7000 capabilities 
   7nrv   DLT DLT7000 DLT7000   35000 /dev/rmt/tps3d5nrv.7000   DLT7000 capabilities 
   7nrsv  DLT DLT7000 DLT7000s  35000 /dev/rmt/tps3d5nrsv.7000  DLT7000 capabilities 
   7vc    DLT DLT7000 DLT7000c  70000 /dev/rmt/tps3d5v.7000c    DLT7000 capabilities 
   7svc   DLT DLT7000 DLT7000cs 70000 /dev/rmt/tps3d5sv.7000c   DLT7000 capabilities 
   7nrvc  DLT DLT7000 DLT7000c  70000 /dev/rmt/tps3d5nrv.7000c  DLT7000 capabilities 
   7nrsvc DLT DLT7000 DLT7000cs 70000 /dev/rmt/tps3d5nrsv.7000c DLT7000 capabilities 

A UNIX device pathname is included so as to avoid having the DCP understand the format of a dev_t minor number, or equivalent. The DCP can replicate the path (copy dev_t) when it needs to create a handle for that combination of drive and access mode. OpenVault defines the default capabilities of a drive, and the DCP specifies what capabilities it offers in terms of changes to that default set.

For easy editing, DCP configuration files should be composed of readable ASCII text.

6.2.2. DCP Boot Sequence

The DCP boot sequence is composed of the following steps:

  1. When a DCP boots or reboots, it does the following:

    1. Allocates internal data structures and initialize state.

    2. Refrains from talking to the drive.

      The DCP boots into activate disable state, and must wait for the MLM server to tell it when to talk to the drive. If the drive is dual-ported with another DCP actively controlling it, that session should not be interrupted!

      The MLM server issues an activate enable command when conditions permit your DCP to control the drive. If the library is single-ported, activate enable is issued almost immediately.

    3. Reads its configuration file.

    4. Establishes a session with the MLM server.

      The DCP sends the hello message upon opening the connection. In this example, name is the OpenVault name for the drive, and inst is the DCP instance name. If connection fails, retry every two minutes. The DCP blocks until it receives a welcome command telling it which language version to use during this session.

      hello language["ADI"] version["1.0"] client["name"] instance ["inst"];

  2. When the MLM server is first contacted by a DCP, it does the following:

    1. Integrates the drive into its list of managed devices.

      The MLM server checks for other DCPs managing that physical drive. If this DCP is the first, OpenVault allows this DCP to proceed. This sequencing implies that DCPs are given control of their associated drive on a first-come-first-served basis.

    2. (Eventually) issues an activate enable command to the DCP.

  3. When the MLM server says to activate enable, the DCP does the following:

    1. Replies to the MLM server with a ready no command.

      The DCP informs the MLM server that it has started to come up, but is not yet ready to accept drive control commands.

    2. Talks to the drive to determine:

      • That the drive is supported by this DCP.

      • The supported media formats (for example: EXABYTE-8mm-5GB).

      • Whether or not the drive can support the listed access modes.

      • If the drive is loaded or in use at this time.

      • Any other information that may be relevant to drive or DCP operation.

    3. Collects any state or configuration information from the MLM server.

      The DCP can store state or configuration information in the OpenVault persistent store.

    4. Push all the capability information up into the MLM server.

      The DCP needs to update the MLM server's copy of the capability list at boot time, before the DCP has been activated. This is different from an LCP, which must be activated in all cases. By contrast, it is unnecessary to activate all the DCPs that might control a given drive just to determine their capability set.

      The DCP takes all its compiled-in settings and information from its configuration file to generate a config command for the MLM server. There is a possibility that the offered capabilities might change once the DCP has had a chance to talk to the drive hardware, but the MLM server must deal with this if it happens.

    5. Sends a ready command to the MLM server.

      The DCP is now ready to accept drive control commands.

    6. Responds success to the original activate enable command.

      This is defined to be the last step as a convenience to the MLM server, so that the server can block until it receives a response from its activate enable command rather than continually polling for arrival of the ready command.

  4. When the MLM server gets a successful response to activate enable, it sends the DCP its message logging level.

6.2.3. Activation Sequence

When a DCP receives an activate enable command from the MLM server, and the DCP is in ready lost state, it performs these steps:

  1. Accesses its drive to acquire or verify device-specific configuration and state.

    For example, a DCP may consult its drive to determine:

    • If the drive is supported by this DCP

    • Whether the drive is in a usable state for this DCP

    • Optimal block size

  2. Pushes configuration information to the MLM server.

    For example, configuration information includes: supported form factors, media types, bit formats, media capacity, block size, nominal drive load time, drive read and write bandwidth, and drive capabilities. See the tables in the section Section 6.5, for particulars.

  3. Transitions to ready state, and pushes this new state to MLM server.

6.3. DCP Development Framework

The infrastructure developer's kit includes a framework for writing a DCP that helps ease the development, porting, and maintenance effort for DCPs. This section describes the general source tree layout.

6.3.1. OpenVault Client-Server IPC

OpenVault clients and servers communicate with a custom interprocess communication (IPC) layer. DCP modules that deal directly with ADI and ADI/R need to include the following header file, and be loaded with the following C library:


C data structures, macros, and subroutine prototypes for IPC


C library containing IPC subroutines

6.3.2. ADI Parser and ADI/R Generator

OpenVault includes language parsers and generators. DCP modules using these facilities need to include the following header files, and be loaded with the following C libraries:


Supported ADI and ADI/R language version, ADI standard errors, and C data structures for ADI and ADI/R command representation


Parser and generator subroutine prototypes


C data structures for HELLO and WELCOME command representation


C library that contains HELLO parser-generator subroutines


C library that contains ADI parser-generator subroutines

6.3.3. DCP C Library Routines

The DCP(3) man page documents the ADI and ADI/R lexical library routines that you employ when writing a DCP. Table 6-1 offers a summary of these routines.

Table 6-1. ADI and ADI/R Lexical Library Routines

Purpose of Activity

DCP Function

Short Description

To initiate session with MLM server


Begins session with a specific MLM server, including HELLO version negotiation.

To parse ADI command from MLM server


Parses an ADI command and returns an ADI command structure.

To acknowledge ADI command


Informs MLM server that the DCP received an ADI command.

To send ADI/R command to MLM server






Allocates ADIR command structure.

Allocates ADIR ready structure.

Allocates memory for ADIR message.

Puts drive capability info into ADIR capinfo.

Allocates attribute name and value pair.

To send final response for ADI command to MLM server





Allocates ADIR response structure.

Allocates string and links into ADI stringlist.

Transmits ADIR command to MLM server.

Deallocates ADIR command structure.

To free ADI command


Deallocates ADI command structure.

6.3.4. DCP Common Framework

The infrastructure developer's kit includes common utility code for writing a DCP. To use this code, include the following header files, and read the following C module:


Generic command queuing mechanism


Generic representation of DCP and drive state, generic representation of an attribute, common DCP fixed and programmable entry points, and common DCP utility subroutine prototypes


Generic queue and linked list implementation


DCP common fixed-entry points and utility subroutines Generic Representation of a Drive (dcp_lib.h)

Much of a DCP's representation of DCP and drive state can be represented generically. However, the DCP developer needs a way to customize this representation for a particular drive and implementation.

The framework provides a private data area and programmable entry points so the developer can customize the representation of DCP and drive state. The private data area allows the developer to maintain additional information about the DCP and drive; programmable entry points allow the developer to customize actions associated with initialization (booting), deactivation (transition to ready lost state), and shutdown. This arrangement allows the shared framework to invoke these entry points as appropriate.

Example 6-2 shows the framework's generic representation for a drive:

Example 6-2. Framework's Generic Representation

struct driveinfo {
    /* elements from DCP config file. */
    char *client;               /* MLM name of this drive.          */
    char *instance;             /* Client instance.                 */
    char *mlmhost;              /* MLM host.                        */
    int mlmport;                /* MLM port.                        */
    int timeout;                /* ADI receive timeout.             */
    char *addr;                 /* Drive access path for DCP.       */
    /* elements initiated by DCP. */
    enum ADIR_ready_type readystatus; /* ready, not r_, disconnected */
    enum ADIR_msg_severity loglevel;  /* Log level for DCP messages. */
    char *vendor;                     /* Drive vendor name.          */
    queue_t ADI_cmd_queue;            /* ADI command queue.          */
    queue_t ADIR_cmd_queue;           /* ADIR command queue.         */
    int waiting_for_ack;              /* 1 if waiting for ack, or 0  */
    char *taskid_for_ack;             /* TaskID of last ADIR command */
    void(*dcp_deactivate)(struct driveinfo *drivei);   /* deactivate */
    void(*dcp_exit)(*drivei, int abnormal);              /* shutdown */
    void(*dcp_dispatch)(*drivei, struct ADI_command *cmd);
    char *(*dcp_taskid)(*drivei);               /* taskid generation */
    void *private;                        /* DCP private libary info */
}; Common DCP Entry Point

A DCP that makes use of this developer framework must call the dcp_init subroutine, shown in Example 6-3, to initialize the generic and private data areas for DCP and drive information, and set the programmable DCP entry points:

Example 6-3. dcp_init Subroutine

void dcp_init(struct driveinfo *drivei,
              void dcp_init_private(),
              void dcp_deactivate(),
              void dcp_exit(),
              void dcp_dispatch(),
              void dcp_taskid()); Programmable DCP Entry Points

This entry point is called one time only from dcp_init(); so the driveinfo structure does not store it. Required entry point for DCP private data area allocation and initialization:

void dcp_init_private(struct driveinfo *drivei);

Remaining entry points are stored in the libinfo structure. Required entry point for DCP private actions to activate disable:

void dcp_deactivate(struct driveinfo *drivei);

Required entry point for DCP private actions to shut down gracefully and exit:

void dcp_exit(struct driveinfo *drivei);

Required entry point for ADI command dispatch from within command state machine:

void dcp_dispatch(struct driveinfo *drivei, struct ADI_command *cmd);

Required entry point for DCP to generate a task ID for ADI/R commands:

void char *dcp_taskid(struct driveinfo *drivei); DCP Utility Functions

The following functions are provided for ADI command queuing and the state machine:

queue_t * adi_command()

Enqueues ADI command, and initialize command state.

void adi_next()

Sends next ADI command.

void adi_complete()

ADI command finished, so updates state and dequeues it.

void *adi_context()

Sets and returns private command context.

enum cmd_state adi_state()

Returns ADI command state.

The following functions are provided for ADI/R command queuing and MLM server acknowledgment processing:

queue_t *adir_command()

Enqueues ADI/R command for sending.

void adir_abort()

Dequeues pending ADI/R commands.

void adir_next()

Sends next ADI/R command.

int adi_response()

Matches ADI response to ADI/R command.

The following function is provided for DCP ready state processing:

void readystate_change()

DCP standard ready state processing.

The following functions are provided for handling ADI error responses:

void attribute_error()

Handles attribute or show error.

void ready_error()

Handles ready state error.

The following functions are provided for mandatory attribute and show processing:

int attribute_()

DCP generic attribute and show processing.

int dcp_attr()

Attribute and show for generic DCP attribute.

int dcp_name()

Attribute and show DCP name attribute.

int dcp_loglevel()

Attribute and show DCP loglevel attribute.

The following functions are provided for debugging:

void print_stringlist()

Prints ADI stringlist.

void print_attrlist()

Prints ADI attrlist.

6.4. Example DCP Implementation

The EXB-8505XL drive is a SCSI-2 tape device that accepts 8 mm media.

The DCP for an EXABYTE 8505XL drive may be used in combination with the LCP for an EXABYTE 210 media changer.

6.4.1. IRIX Implementation

Control access is three-part, and includes use of the local filesystem, a pass-through SCSI driver, and IRIX magnetic tape interface (MTIO) ioctl() operations. Use of Local Filesystem

This implementation uses a set of drive instance prototypes, which are represented by a set of existing device special files, for example /dev/rmt/tps0d6. So drive instances are already instantiated. Attach and detach commands simply bind a drive handle to an existing instance, or device special file. Creating and removing a binding is done using the local filesystem mknod() and unlink() operations. Direct SCSI Commands

Calls to the pass-through SCSI driver are made with the IRIX C library for generic SCSI operations; see the dslib(3X) man page. Direct SCSI access is by means of this device special file:


In this filename, C is the SCSI controller number, U is the unit number, and L is the logical unit number (lun) for accessing drive control. This information may be determined on IRIX systems by using the hinv command.

Calls to dslib are used to get mode sense information directly from the drive, to check for information such as whether the drive supports partitions, and to issue mode select commands, such as those for moving the tape to a particular position. MTIO Operations

MTIO calls are made by sending ioctl() calls directly to the tape driver associated with the control access path for a particular drive instance. MTIO operations perform load verification and unload.

6.4.2. Source Code Organization

This section describes the DCP source and run-time configuration modules. Configuration Processing

Example 6-4 illustrates the ovsrc/clients/dcp/EXB-8505XL/config file, which describes traits of the drive and MLM server.

Example 6-4. ovsrc/clients/dcp/EXB-8505XL/config File

localhost          # MLM server host name
739                # MLM server TCP socket
fred               # OpenVault name for drive
dcpfred            # DCP instance name
/dev/rmt/tps0d6    # MTIO drive control access path
/dev/scsi/sc0d610  # SCSI drive control access path
60                 # Communications timeout

Remaining lines include supported drive instance prototypes, including mode name, form factor, media type, bit format, capacity, and control capabilities.

The ovsrc/clients/dcp/EXB-8505XL/config.c module parses this file and fills in drive information in both the DCP generic and private data areas. SCSI Control Access

The ovsrc/clients/dcp/EXB-8505XL/control.h header file contains definitions, data type declarations, and subroutine prototypes for control access by means of the pass-through SCSI driver; see the dslib(3X) man page.

The ovsrc/clients/dcp/EXB-8505XL/control.c module contains convenience routines that make SCSI library calls to get mode sense, check for partition support, and change tape partition. Since partition support is currently not implemented, the latter is nonoperational.

Otherwise, device access is made directly from the main ADI semantic module by means of MTIO ioctl() operations. ADI Semantic Do* Layer

This layer, named after its many functions starting with “do,” is where a DCP interprets ADI commands. The programmer customizes this layer, based on the generic drive methods that are provided as part of the DCP developer framework.

The ovsrc/clients/dcp/EXB-8505XL/main.h header file contains the DCP private data area portion of a generic drive representation, as well as macros and subroutine prototypes, including four programmable DCP entry points for use by the framework and semantic support routines.

The ovsrc/clients/dcp/EXB-8505XL/main.c module is where ADI semantic handling routines and entry points are implemented, and where ADI commands are dispatched to the appropriate semantic handling routine. For example, the ADI_load command would be dispatched to the do_load() function.

6.4.3. Future DCP Implementations

There is potential for a single, shared SCSI-2 DCP. An additional device module would be required only for vendor-dependent processing, or for departures from the standard.

More thought and changes to ADI and the DCP framework are needed to support non host-attached devices, such as broadcast video.

The infrastructure developer's kit was developed on IRIX systems, and has yet to be ported to other platforms. The DCP framework does not yet support partitions.

6.5. Defined Tokens List

This section documents the predefined strings that are relevant to DCP development.

6.5.1. Drive Capabilities

OpenVault assumes that there is default set of drive capabilities. Table 6-2 shows the tokens that describe changes from a standard drive.

Table 6-2. Predefined mount Tokens




Mount point allows playing audio data from media (often unimplemented).


Attempts compression of the data stream.


Blocks on the media are a fixed size.


The mount point allows reading of the media.


The mount point allow writing of the media.


Rewinds the media on close of the mount point.


A status-only mount point is also created (in a directory created for the session).


Blocks on the media are variable sized.

Drive capabilities are entirely extensible; so this list is not exhaustive.

6.5.2. Cartridge Form Factors

For a list of predefined cartridge form factors, see Section 4.5.1 in Chapter 4.

6.5.3. Media Bit Formats

The format of bits recorded on media is independent of external cartridge appearance. One well-known case is the EXABYTE 8200 versus EXABYTE 8500 format, both being recorded on 8 mm media.

Table 6-3 shows tokens for each bit format, what form factors use it, and a description of how the format is generated.

Table 6-3. Predefined Bit Format Tokens


Form Factor



8 mm

EXABYTE 8200 native


8 mm

EXABYTE 8200 compressed


8 mm

EXABYTE 8500 native


8 mm

EXABYTE 8500 compressed


8 mm

EXABYTE mammoth native


8 mm

EXABYTE mammoth compressed



3480 native



3490 native



3490E native



IBM Magstar native



STK TimberLine native



STK RedWood native



DLT2000 native



DLT2000 compressed



DLT4000 native



DLT4000 compressed



DLT7000 native



DLT7000 compressed



Digital data storage 1.3 GB



Digital data storage 2.0 GB



Digital data storage 4.0 GB



Ampex DST-310



Sony GY-10



Quarter-inch cartridge 80 MB



Quarter-inch cartridge 100 MB



Quarter-inch cartridge 150 MB



Quarter-inch cartridge 525 MB



Quarter-inch cartridge 1024 MB



DOS-like (8.3) filesystem on CD-ROM

6.5.4. Cartridge Types

Table 6-4 shows tokens used to describe media inside a cartridge.

Table 6-4. Predefined Media Type Tokens


Product Name or Description


12 meter 8 mm


60 meter 8 mm


90 meter 8 mm


112 meter 8 mm


160 meter 8 mm


EXABYTE mammoth


IBM 3480


IBM 3490


IBM 3490E


IBM Magstar native


STK TimberLine native


STK RedWood native


Quantum DLT2000


Quantum DLT2000XT


Quantum DLT4000


Quantum DLT7000


DAT 60 meter


DAT 90 meter


DAT 120 meter


Ampex DST-310 small format


Ampex DST-310 medium format


Ampex DST-310 165GB large format


Sony GY-10


Quarter-inch cartridge tape



6.5.5. Partition Names

The ADI interface assumes that there is a standard set of names used for partitioned media. Table 6-5 shows the tokens used for naming partitions.

Table 6-5. Predefined Partition Name Tokens




The first partition on the media. For magneto-optical or two-sided optical disc, this would be side one or side A.


The second partition on the media. On linear media such as a tape, PART 2 immediately follows PART 1. On non-linear media such as a disk, PART 2 is the second-lowest numbered or lettered partition. Note that PART 2 does not refer to the next partition that is in use, it refers to the next partition.

6.5.6. Attribute Names (DCP)

Table 6-6 shows attributes used in OpenVault, where they are used, and what they mean.

Table 6-6. Predefined Attribute Name Tokens (DCP)

Attribute Name

Where Used

Possible Values




ADI config command, perf clause

Numeric, in bytes per second


The total effective bandwidth that an application should be able to sustain when reading from that drive using the given capability set.


ADI config command, perf clause

Numeric, in bytes per second


The total effective bandwith that an application should be able to sustain when writing to that drive using the given capability set.


ADI config command, perf clause

Numeric, in bytes


The total storage capacity of the cartridge that an application should be able to expect when accessing that drive using the given capability set.


ADI config command, perf clause

Numeric, in bytes


The I/O size that would best use the drive/cartridge combination with that drive with the given capability set.


ADI config command, perf clause

Numeric, in seconds


The number of seconds between the time a cartridge is first inserted into a drive and the time that the drive is ready to read/write data.


ADI config command, config clause

Cartridge FormFactor token ( Table 4-2)


A supported form factor when the drive is using the given capability set.


ADI config command, config clause

MediaType token


A supported media type, usually indicating tape length.


ADI config command, config clause

Bit Format token


A supported recording format when the drive is using the given capability set.


ALI config command, perf clause

Numeric, in seconds


Approximate time it takes for the library to move a cartridge from its home location to a drive, or back, not including drive load/unload time. This is analogous to “nominal seek time” of a disk drive.

It is defined as the total real time to execute a large number of cartridge move-load operations randomly spread through the physical space of a library, divided by the number of such operations performed.