Museum

Home

Lab Overview

Retrotechnology Articles

⇒ Online Manual

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

odio(4)

jbc(8)

jbd(8)

JBIO(7)  —  Special Files

NAME

jbio − optical disk jukebox interface

SYNOPSIS

#include <sys/types.h>
#include <sys/ioctl.h>
#include <ofs/jbio.h>

DESCRIPTION

Optical Disk Jukeboxes (variously called library units, selectors or changers) fall into three general classes, depending upon the method employed to control the selector mechanism:

Class 1 (auto)
changers are optical disk drives with an integral selector mechanism operated by special commands added to the ANSI standard command set for optical disk drives. Changers in this class are controlled by the Perceptics optical disk (od) device driver. 

Class 2 (ANSI)
changers have an independent selector mechanism operated via a separate SCSI control device employing the ANSI standard command set for changer devices. Changers in this class are controlled by the Perceptics jukebox (jb) SCSI device driver. 

Class 3 (ASCII)
changers have an independent selector mechanism operated via an RS-232c serial port using a specialized command language unique to each changer. Changers in this class are controlled by the Perceptics jukebox daemon (see jbd(8)) via the standard serial port (tty) device driver. 

Changers in all three classes are operated by the Perceptics Optical File System (OFS) via special entry points in the Perceptics device drivers, and may also be operated by user-mode utility programs using special I/O Control (ioctl) calls to the appropriate device driver.  The Perceptics Jukebox Control utility (jbc) is furnished to operate class 2 (ANSI) and class 3 (ASCII) changers (see jbc(8)).  No command-level facility is furnished to operate class 1 (auto) changers. 

The I/O control (ioctl) calls used by jbc or other utility programs to operate each class of changer are specific to changers of that class. 

OPERATION

To select a volume in an auto-changer into the imbedded drive:

1.open the appropriate od device node using the O_NDELAY open option;

2.issue an ODIOC_SELECT ioctl call specifying the desired volume;

3.close and then re-open the od device node using the normal open mode to access the selected volume. 

To select a volume in an ANSI changer into one of its drives:

1.open the appropriate jb device node;

2.issue a JBIOC_SELECT ioctl call specifying the desired volume and drive;

3.open the appropriate od device node to access the selected volume. 

To select a volume in an ASCII jukebox into one of its drives:

1.open the appropriate jb device node;

2.issue a JBIOC_COMMAND ioctl call specifying the MOVE command, the desired volume and drive;

3.open the appropriate od device node to access the selected volume. 

In every case, be certain the od device node for the target drive is not open before attempting to select a volume into the drive.  If a volume is still active in the drive, the changer cannot select another volume. 

The Perceptics jukebox (jb) driver accepts these ioctls:

JBIOC_ONLYexclusive access
JBIOC_IDENTdriver identity
JBIOC_RANGEjukebox resources
JBIOC_COMMANDsend command to daemon
JBIOC_SELECTselect volume to drive
JBIOC_RESTORErestore volume to slot
JBIOC_STATEstatus of ANSI changer
JBIOC_INITinitialize ANSI status

The Perceptics optical disk (od) driver accepts these ioctls:

ODIOC_ONLYexclusive access
ODIOC_IDENTdriver identity
ODIOC_SELECTselect volume to drive
ODIOC_CAPACITYvolume capacity
ODIOC_OFFSETblock offset

See odio(4) for more information on optical disk operation. 

/∗ structure for xxIOC_IDENT − driver identity ∗/
struct  ident                   /∗ xxIOC_IDENT ∗/
{
    int         model;          /∗ system type and release ∗/
    int         level;          /∗ Perceptics release level ∗/
    char        title[25];      /∗ driver module description ∗/
    char        time[9];        /∗ build or compile time ∗/
    char        date[12];       /∗ build or compile date ∗/
    char        name[31];       /∗ customer name ∗/
    char        notes[41];      /∗ release notes ∗/
};
 /∗ structure for JBIOC_RANGE − jukebox resource ranges ∗/
structrange/∗ JBIOC_RANGE ∗/
{
    short                           type, class;
    struct { short start, count; }  unit, slot;
    short                           sides, base;
};
/∗ jukebox classes ∗/
#defineCLASS_AUTO1/∗ Auto-changer (LMS/Sony610) ∗/
#defineCLASS_ANSI2/∗ ANSI SCSI jukebox (NKK/HP) ∗/
#defineCLASS_ASCII3/∗ ASCII RS232 (Kodak/Cygnet) ∗/
 /∗ structure for JBIOC_COMMAND − command to jukebox daemon ∗/
struct command/∗ JBIOC_COMMAND ∗/
{
    unsigned int command;
    struct
    { unsigned char type, slot;
    } source, target;
    int response;
    unsigned int status[5];
};
/∗ valid commands ∗/
#define   C_CLEAR       0
#define   C_DEBUG       1
#define   C_SELECT      2
#define   C_MOVE        3
#define   C_RESET       4
#define   C_FLUSH       5
#define   C_GET         6
#define   C_PUT         7
#define   C_INSERT      8
#define   C_EJECT       9
#define   JB_COMMAND(x) ((OFS_IDENT∗40)+(x))
/∗ resource types ∗/
#define   T_NULL        0
#define   T_DEVICE      1
#define   T_SLOT        2
#define   T_INVERT      3
/∗ response codes ∗/
#define   NONE         -8      /∗ no communication ∗/
#define   MATCH        -7      /∗ map inconsistent ∗/
#define   ACCESS       -6      /∗ restricted slot ∗/
#define   TIMER        -5      /∗ access timeout ∗/
#define   FULL         -4      /∗ target active ∗/
#define   EMPTY        -3      /∗ source empty ∗/
#define   RANGE        -2      /∗ out of range ∗/
#define   VOID         -1      /∗ nothing to do ∗/
 /∗ structure for JBIOC_STATE − ANSI changer read status ∗/
struct state/∗ JBIOC_STATE s=sent r=received ∗/
{
    char        mode;    /∗ -r ANSI changer element status byte ∗/
    unsigned    type:7;  /∗ s-  resource type: 0=device, 1=slot ∗/
                         /∗ -r  drive volume origin status valid ∗/
    unsigned    side:1;  /∗ -r  media surface: 0=obverse, 1=reverse ∗/
    short       slot;    /∗ sr  slot or device resource index ∗/
};
 /∗ structure for xxIOC_SELECT − select volume ∗/
struct select/∗ for SELECT/RESTORE ∗/
{
    short drive;
    short volume;
};

EXAMPLES

To access a volume in a class 1 (auto) changer:

#include <ofs/odio.h>
int od, volume;
 if ((od = open ("/dev/od?", O_NDELAY, 0)) < 0)
{ perror ("can’t open od?"); exit ~0; }
if (ioctl (od, ODIOC_SELECT, &volume) < 0)
{ perror ("can’t select"); exit ~0; }
close (od);/∗ volume selected ∗/
 if ((od = open ("/dev/od?", O_RDWR, 0)) < 0)
{ perror ("can’t open od?"); exit ~0; }
    ... optical disk operations ...
close (od);/∗ volume restored ∗/

To manipulate a volume in a class 2 (ANSI) changer:

#include <ofs/jbio.h>
struct state state;
struct access ∗access = (struct access ∗)&state.mode;
struct select select;
int jb, od;
 if ((jb = open ("/dev/jb?", 0, 0)) < 0)
{ perror ("can’t open jb?"); exit ~0; }
 state.type = 1;/∗ query slot ∗/
state.slot = slot;
if (ioctl (jb, JBIOC_STATE, &state) < 0)
{ perror ("can’t query"); exit ~0; }
if (access->full)
{ puts ("target active"); exit FULL; }
 select.drive = 0;/∗ entry to slot ∗/
select.volume = slot << 1;
if (ioctl (jb, JBIOC_RESTORE, &select) < 0)
{ perror ("can’t insert"); exit ~0; }
 state.type = 0;/∗ query drive ∗/
state.slot = drive;
if (ioctl (jb, JBIOC_STATE, &state) < 0)
{ perror ("can’t query"); exit ~0; }
if (access->full)
{ puts ("target active"); exit FULL; }
 select.drive = drive;/∗ slot to drive ∗/
select.volume = (slot << 1) | side;
if (ioctl (jb, JBIOC_SELECT, &select) < 0)
{ perror ("can’t select"); exit ~0; }
 if ((od = open ("/dev/od?", O_RDWR, 0)) < 0)
{ perror ("can’t open od?"); exit ~0; }
    ... optical disk operations ...
close (od);
 state.type = 0;/∗ query drive ∗/
state.slot = drive;
if (ioctl (jb, JBIOC_STATE, &state) < 0)
{ perror ("can’t query"); exit ~0; }
if (!access->full)
{ puts ("source empty"); exit EMPTY; }
if (!state.type)
{ puts ("origin unknown"); exit VOID; }
 select.drive = drive;/∗ drive to slot ∗/
select.volume = (state.slot << 1) | state.side;
if (ioctl (jb, JBIOC_RESTORE, &select) < 0)
{ perror ("can’t restore"); exit ~0; }
 select.drive = 0;/∗ slot to exit ∗/
select.volume = slot << 1;
if (ioctl (jb, JBIOC_SELECT, &select) < 0)
{ perror ("can’t eject"); exit ~0; }
 close (jb);

To manipulate a volume in a class 3 (ASCII) jukebox:

#include <ofs/jbio.h>
struct command command;
int jb, od;
 void transfer ()
{
  int response = 0;
  if (ioctl (jb, JBIOC_COMMAND, &command))
  { perror ("can’t access"); return ~0; }
   if (command.response < 0)
    printf ("error %d\n", command.response);
  else while (response < command.response)
    printf ("fault %.4s\n", &command.status[response]);
}
if ((jb = open ("/dev/jb?", 0, 0)) < 0)
{ perror ("can’t open"); exit ~0; }
command.command = JB_COMMAND(C_MOVE);
 command.source.slot = 0;
command.source.type = T_DEVICE;
command.target.slot = slot;
command.target.type = T_SLOT;
transfer ();/∗ entry to slot ∗/
 command.source.slot = slot;
command.source.type = T_SLOT + side;
command.target.slot = drive;
command.target.type = T_DEVICE;
transfer ();/∗ slot to drive ∗/
 if ((od = open ("/dev/od?", O_RDWR, 0)) < 0)
{ perror ("can’t open od?"); exit ~0; }
    ... optical disk operations ...
close (od);
 command.source.slot = drive;
command.source.type = T_DEVICE;
command.target.slot = slot;
command.target.type = T_SLOT + side;
transfer ();/∗ drive to slot ∗/
 command.source.slot = slot;
command.source.type = T_SLOT;
command.target.slot = 0;
command.target.type = T_DEVICE;
transfer ();/∗ slot to exit ∗/
 close (jb);

FILES

/dev/od∗

/dev/jb∗

SEE ALSO

odio(4), jbc(8), jbd(8)

  —  30 April 1993

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026