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
— 30 April 1993