USB テープ・クライアント・デバイス・ドライバー

目的

順次アクセス・テープ・デバイス・ドライバー用の USB (Universal Serial Bus) プロトコルをサポートします。

構文

#include <sys/devinfo.h>
#include <sys/usb.h>
#include <sys/tape.h>
#include <sys/usbdi.h>

装置依存のサブルーチン

ほとんどのテープ操作は、 opencloseread、および write サブルーチンを使用してインプリメントされます。 ただし、デバイスを Diagnostic モードで開く必要がある場合は、 openx サブルーチンを使用する必要があります。

サブルーチンのオープンとクローズ

openx サブルーチンは、主に診断コマンドおよびユーティリティーに使用されます。 サブルーチンを実行するには、適切な権限が必要です。 を実行するとopenx必要な権限を持たないサブルーチンの場合、サブルーチンは次の値を返します。-1そして、エラーグローバル変数をEPERM

openx サブルーチンは、デバイス・ドライバーの Diagnostic モードを使用可能にし、コマンド再試行ロジックを使用不可にします。 このアクションにより、診断処理に関連した特殊な機能を実行する ioctl 操作が可能になります。 openx サブルーチンは、オープンを強制し、予約を保持することもできます。

open サブルーチンは、オブジェクト・データ・マネージャー (ODM) reserve_policy 属性に基づく予約ポリシーを適用します。 USB テープ・デバイスは Small Computer System Interface (SCSI) 予約コマンドをサポートしない可能性があるため、これらのコマンドは無視される可能性があります。

openx サブルーチンに渡される ext パラメーターは、ターゲット・デバイスに使用される操作を選択します。 /usr/include/sys/scsi.h ファイルは、 ext パラメーターに指定できる値を定義します。

内線 パラメーターには、以下のフラグ値の任意の論理組み合わせを含めることができます。

項目 説明
SC_FORCED_OPEN アクセスを禁止できるデバイス上のすべてのタイプの予約を削除することにより、デバイスへのアクセスを強制します。 予約を削除するアクションのタイプは、設定された予約の特定のタイプによって異なります。 このフラグを指定すると、大容量ストレージ・バルク・デバイスである USB テープに対して大容量ストレージ・リセット・コマンドが発行されます。
SC_診断 選択したデバイスを Diagnostic モードにします。 このモードは単独で使用できます。 つまり、デバイスが Diagnostic モードの場合、 open または close 操作中に SCSI 操作が実行され、エラー・ロギングは無効になります。 Diagnostic モードでは、 close 操作と ioctl 操作のみが受け入れられます。 その他のデバイス対応サブルーチンは、-1そして、エラーグローバル変数をEACCES

ターゲット装置が現在オープンされていない場合にのみ、装置を Diagnostic モードでオープンすることができます。 デバイスをDiagnosticモードで、ターゲットデバイスがすでに開いている場合、サブルーチンは値を返します。-1そして、エラーグローバル変数をEACCES

ioctl サブルーチン

USB テープ・デバイスでは、以下の ioctl 操作がサポートされます。

操作 説明
IOCINFO 呼び出し元によって渡される devinfo 引数に、以下の値を設定します。
        devinfo.devtype           = DD_SCTAPE;
        devinfo.flags             = 0;
        devinfo.devsubtype        = 0x00;
        devinfo.un.scmt.type      = DT_STREAM;
        devinfo.un.scmt.blksize   = Block Size Set for the Tape Device;
スティオクトップ src/bos/usr/include/sys/tape.h ファイルに定義されている停止構造のアドレスを指定します。 停止構造内の st_op フィールドにある操作は、巻き戻し、消去、および保存の操作を除き、 st_count 回実行されます。

この ioctl コマンドは、それぞれの実装の詳細を使用して、以下の操作をサポートします。

ストリーム
テープ装置に対して REWIND コマンドを発行して、テープを巻き戻します。
STERASE
SCSI ERASE コマンドを発行して、テープ・メディアの内容を消去します。 読み取り専用テープでは消去は許可されません。
STRETEN または STINSRT
コマンドのバイト 4 に Load および Reten ビットを設定して SCSI LOAD コマンドを発行します。
STWEOF (E)
ファイルの終わりのマークをテープに書き込みます。 Write End-of-Filemark 操作は、読み取り専用テープでは許可されません。  
標準の停止
テープの終わり検査コマンドを使用不可にします。
STFSF (ソフトウェア)
Forward Space File コマンドを発行します。 st_count フィールドは、テープが進むファイル・マークの数を指定します。
STFSR (サービス要求)
Forward Space Record コマンドを発行します。 st_count フィールドは、テープが進むレコードの数です。
STRSF (鉄道)
Reverse Space File コマンドを発行します。 st_count フィールドは、テープが反転するファイル・マークの数です。
STRSR (要求)
Reverse Space Record コマンドを発行します。 st_count フィールドは、テープが反転するレコードの数です。
STOFFL または STEJECT
テープ・ドライブからテープを排出します。 この操作は、ゼロに設定されたコマンド記述子ブロック (CDB) のバイト 4 に Load ビットを指定して SCSI LOAD コマンドを発行します。
STIOCHGP
この磁気テープ装置のブロック・サイズを動的に変更するための ioctl コマンドを定義します。 ブロック・サイズはオープン操作の長さに合わせて変更され, 次のオープン操作で元の値に戻されます。 この操作が実行されると, テープは強制的に BOT (テープの始め) になります。

この ioctl コマンドのパラメーターは、 src/bos/usr/include/sys/tape.h ファイルに定義されている stchgp 構造体のアドレスを指定します。 構造体の st_blksize フィールドは、設定するブロック・サイズ値を指定します。

STIOCTOP (続き)
STIOCMD
装置が正常にオープンされると、 STIOCMD 操作は指定された磁気テープ装置に SCSI コマンドを発行します。

SCSI 状況バイトおよびアダプター状況バイトは、 scsi_iocmd 構造体のアドレスを含む arg パラメーターを介して戻されます。 この構造は、 /usr/include/sys/scsi_buf.h ファイルで定義されます。 STIOCMD 操作は、 scsi_iocmd 構造の scsi_cdb セクションで SCSI コマンドを受け取り、それを USB テープ・デバイスに発行します。 もし、STIOCMD操作が失敗した場合、サブルーチンは値を返します。-1そして、エラーグローバル変数をゼロ以外の値に設定します。 この場合、呼び出し側は、戻された状況バイトを評価して、操作の失敗の原因とリカバリー・アクションを判別する必要があります。

ユーザーによって渡される versioncommand_length、および timeout_value の値は検証され、無効な場合はエラー値 EINVAL が返されます。

最大I/O転送サイズの1MB以上を転送する場合、サブルーチンは次の値を返します。-1そして、エラーグローバル変数をEINVAL

検査条件では、以下のエラー状況値が sc_passthru 構造体に設定されます。

    status_validity  = SC_SCSI_ERROR
    scsi_bus_status = SC_CHECK_CONDITION
    adap_set_flags will have SC_AUTOSENSE_DATA_VALID flag set.

以下の例は、 INQUIRY SCSI コマンドを発行するために USB テープに対して STIOCMD 操作を発行する疑似コードです。

    struct scsi_iocmd cmd;
    char inq_data[255];
    char sense_data[255];
..
    fd = open(“/dev/rmt0”, O_RDWR);
..
    memset(&cmd, '\0', sizeof(struct sc_passthru));
    cmd.version = SCSI_VERSION_1;
    cmd.timeout_value = 30;
    cmd.command_length = 6;
    cmd.autosense_length = 255;
    cmd.autosense_buffer_ptr = &sense_data[0];
    cmd.data_length = 0xFF;
    cmd.buffer = inq_data;

   cmd.flags = B_READ;

   cmd.scsi_cdb[0] = SCSI_INQUIRY;
    cmd.scsi_cdb[1] = (0x00 | vpd);  /* Standard Inquiry - vpd=1 
                 for Extended Inquiry */
    cmd.scsi_cdb[2] = page_code;    /* Page Code - valid if vpd=1 */
    cmd.scsi_cdb[3] = 0x00;
    cmd.scsi_cdb[4] = 0xFF;
    cmd.scsi_cdb[5] = 0x00;

   if ((rc=ioctl(fd, STIOCMD, &cmd)) != 0){
         if (cmd.adap_set_flags & SC_AUTOSENSE_DATA_VALID) { 
        /* look at sense data */
         } /* end SC_AUTOSENSE_DATA_VALID */

         printf("STPASSTHRU: Ioctl FAIL errno %d\n",errno);
         printf("status_validity: %x, scsi_status: %x, adapter_status:%x\n", 
      cmd.status_validity, cmd.scsi_bus_status, cmd.adapter_status);
         printf("Residual: %x\n", cmd.residual);
         exit(-1);
     } else {
         printf("STPASSTHRU : Ioctl PASS\n");
         printf("status_validity: %x, scsi_status: %x, adapter_status:%x\n", 
      cmd.status_validity, cmd.scsi_bus_status, cmd.adapter_status);     }
STPASSTHRU (標準 RU) sc_passthru 構造の scsi_cdb セクション内の SCSI コマンドを受け取り、それを USB テープ・ドライバーに発行します。 この操作は STIOCMD ioctl 操作と似ていますが、唯一の例外として、エラーに関する詳細情報を提供する sc_passthru 構造体の追加情報フィールドがあります。

以下の例は、 INQUIRY SCSI コマンドを発行するために USB テープに対して STPASSTHRU 操作を発行する疑似コードです。

    struct sc_passthru cmd;
    char inq_data[255];
    char sense_data[255];
..
    fd = open(“/dev/rmt0”, O_RDWR);
..
    memset(&cmd, '\0', sizeof(struct sc_passthru));
    cmd.version = SCSI_VERSION_1;
    cmd.timeout_value = 30;
    cmd.command_length = 6;
    cmd.autosense_length = 255;
    cmd.autosense_buffer_ptr = &sense_data[0];
    cmd.data_length = 0xFF;
    cmd.buffer = inq_data;

   cmd.flags = B_READ;

   cmd.scsi_cdb[0] = SCSI_INQUIRY;
    cmd.scsi_cdb[1] = (0x00 | vpd);  /* Standard Inquiry - vpd=1
                                 for Extended Inquiry */
    cmd.scsi_cdb[2] = page_code;      /* Page Code - valid if vpd=1 */
    cmd.scsi_cdb[3] = 0x00;
    cmd.scsi_cdb[4] = 0xFF;
    cmd.scsi_cdb[5] = 0x00;

   if ((rc=ioctl(fd, STPASSTHRU, &cmd)) != 0){
       if (cmd.adap_set_flags & SC_AUTOSENSE_DATA_VALID) {
             /* look at sense data */
         } /* end SC_AUTOSENSE_DATA_VALID */

         printf("STPASSTHRU: Ioctl FAIL errno %d\n",errno);
         printf("status_validity: %x, scsi_status: %x, adapter_status:%x\n", 
       cmd.status_validity, cmd.scsi_bus_status, cmd.adapter_status);
         printf("Residual: %x\n", cmd.residual);
         exit(-1);
     } else {
         printf("STPASSTHRU : Ioctl PASS\n");
         printf("status_validity: %x, scsi_status: %x, adapter_status:%x\n", 
       cmd.status_validity, cmd.scsi_bus_status, cmd.adapter_status);
     }