これが C 言語によるプログラム例です。これは製造者/モデルを要求し、 メディアが装置に塔載されているかどうかを報告します。
#define DEVICE "/dev/sgc"
/* 汎用 SCSI インターフェースを実際に動かしてみる見本プログラム */
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <scsi/sg.h>
#define SCSI_OFF sizeof(struct sg_header)
static unsigned char cmd[SCSI_OFF + 18]; /* SCSI コマンド バッファ */
int fd; /* SCSI デバイス/ファイル ディスクリプタ */
/* 完結した SCSI コマンドを処理。 汎用 SCSI インターフェースを使用 */
static int handle_scsi_cmd(unsigned cmd_len, /* コマンド長 */
unsigned in_size, /* 入力データサイズ */
unsigned char *i_buff, /* 入力バッファ */
unsigned out_size, /* 出力データサイズ */
unsigned char *o_buff /* 出力バッファ */
)
{
int status = 0;
struct sg_header *sg_hd;
/* 安全性検査 */
if (!cmd_len) return -1; /* cmd_len != 0 が必要 */
if (!i_buff) return -1; /* 入力バッファが NULL でないこと */
#ifdef SG_BIG_BUFF
if (SCSI_OFF + cmd_len + in_size > SG_BIG_BUFF) return -1;
if (SCSI_OFF + out_size > SG_BIG_BUFF) return -1;
#else
if (SCSI_OFF + cmd_len + in_size > 4096) return -1;
if (SCSI_OFF + out_size > 4096) return -1;
#endif
if (!o_buff) out_size = 0;
/* 汎用 SCSI デバイスヘッダの構築 */
sg_hd = (struct sg_header *) i_buff;
sg_hd->reply_len = SCSI_OFF + out_size;
sg_hd->twelve_byte = cmd_len == 12;
sg_hd->result = 0;
#if 0
sg_hd->pack_len = SCSI_OFF + cmd_len + in_size; /* 不要 */
sg_hd->pack_id; /* 未使用 */
sg_hd->other_flags; /* 未使用 */
#endif
/* コマンド送出 */
status = write( fd, i_buff, SCSI_OFF + cmd_len + in_size );
if ( status < 0 || status != SCSI_OFF + cmd_len + in_size ||
sg_hd->result ) {
/* なんらかのエラーが発生 */
fprintf( stderr, "write(generic) result = 0x%x cmd = 0x%x\n",
sg_hd->result, i_buff[SCSI_OFF] );
perror("");
return status;
}
if (!o_buff) o_buff = i_buff; /* バッファのポインタをチェック */
/* 結果を回収 */
status = read( fd, o_buff, SCSI_OFF + out_size);
if ( status < 0 || status != SCSI_OFF + out_size || sg_hd->result ) {
/* なんらかのエラーが発生 */
fprintf( stderr, "read(generic) result = 0x%x cmd = 0x%x\n",
sg_hd->result, o_buff[SCSI_OFF] );
fprintf( stderr, "read(generic) sense "
"%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
sg_hd->sense_buffer[0], sg_hd->sense_buffer[1],
sg_hd->sense_buffer[2], sg_hd->sense_buffer[3],
sg_hd->sense_buffer[4], sg_hd->sense_buffer[5],
sg_hd->sense_buffer[6], sg_hd->sense_buffer[7],
sg_hd->sense_buffer[8], sg_hd->sense_buffer[9],
sg_hd->sense_buffer[10], sg_hd->sense_buffer[11],
sg_hd->sense_buffer[12], sg_hd->sense_buffer[13],
sg_hd->sense_buffer[14], sg_hd->sense_buffer[15]);
if (status < 0)
perror("");
}
/* 受け取るべきものを受け取ったかどうかをみる */
if (status == SCSI_OFF + out_size) status = 0; /* 全部もらった */
return status; /* 0 はエラーなしを意味 */
}
#define INQUIRY_CMD 0x12
#define INQUIRY_CMDLEN 6
#define INQUIRY_REPLY_LEN 96
#define INQUIRY_VENDOR 8 /* 返答データ内のベンダ名のオフセット */
/* ベンダのブランドとモデルを要求 */
static unsigned char *Inquiry ( void )
{
static unsigned char Inqbuffer[ SCSI_OFF + INQUIRY_REPLY_LEN ];
unsigned char cmdblk [ INQUIRY_CMDLEN ] =
{ INQUIRY_CMD, /* command */
0, /* lun/reserved */
0, /* page code */
0, /* reserved */
INQUIRY_REPLY_LEN, /* allocation length */
0 };/* reserved/flag/link */
memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );
/*
* +------------------+
* | struct sg_header | <- cmd
* +------------------+
* | copy of cmdblk | <- cmd + SCSI_OFF
* +------------------+
*/
if (handle_scsi_cmd(sizeof(cmdblk), 0, cmd,
sizeof(Inqbuffer) - SCSI_OFF, Inqbuffer )) {
fprintf( stderr, "Inquiry failed\n" );
exit(2);
}
return (Inqbuffer + SCSI_OFF);
}
#define TESTUNITREADY_CMD 0
#define TESTUNITREADY_CMDLEN 6
#define ADD_SENSECODE 12
#define ADD_SC_QUALIFIER 13
#define NO_MEDIA_SC 0x3a
#define NO_MEDIA_SCQ 0x00
int TestForMedium ( void )
{
/* READY 状態を要求 */
static unsigned char cmdblk [TESTUNITREADY_CMDLEN] = {
TESTUNITREADY_CMD, /* command */
0, /* lun/reserved */
0, /* reserved */
0, /* reserved */
0, /* reserved */
0};/* reserved */
memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );
/*
* +------------------+
* | struct sg_header | <- cmd
* +------------------+
* | copy of cmdblk | <- cmd + SCSI_OFF
* +------------------+
*/
if (handle_scsi_cmd(sizeof(cmdblk), 0, cmd,
0, NULL)) {
fprintf (stderr, "Test unit ready failed\n");
exit(2);
}
return
*(((struct sg_header*)cmd)->sense_buffer +ADD_SENSECODE) !=
NO_MEDIA_SC ||
*(((struct sg_header*)cmd)->sense_buffer +ADD_SC_QUALIFIER) !=
NO_MEDIA_SCQ;
}
void main( void )
{
fd = open(DEVICE, O_RDWR);
if (fd < 0) {
fprintf( stderr, "Need read/write permissions for "DEVICE".\n" );
exit(1);
}
/* Inquiry の結果の一部のフィールドを表示 */
printf( "%s\n", Inquiry() + INQUIRY_VENDOR );
/* メディアが塔載されているかどうかをみる */
if (!TestForMedium()) {
printf("device is unloaded\n");
} else {
printf("device is loaded\n");
}
}