差分表示


*SCSIコマンドに関して
*実装
SCSIコマンドには沢山あるが、大雑把に大別するとデバイスに記録されているデータをrwするコマンド(READ/WRITE)とデバイスを制御/診断するもの(INQUIRY/FORMAT/READ ATTRIBUTE)とかがあるっぽい。どんなのあるかの詳しくはwikiとか仕様書とかを参照ってことでw

コード例がLinuxのHowToにあるが、あれはSGドライバのVersion 3.0以前のdriverを
直接 read/writeしてデータブロックをやり取りするのものだが、3.0以降は
SGドライバに SG_IOと言うioctl()が新設されており、こちらを利用して
SCSIのデータブロックをrwするのが、現在のトレンドだとおもう、多分w
*コード例
ってことで、例によって後は実装で
HowToで提供されている handle_scsi_cmd()に対応する handle_scsi3_cmd()を作成してみた。
**handle_scsi_cmd()
[[ここ>http://www.linux.or.jp/JF/JFdocs/SCSI-Programming-HOWTO-8.html]]を参照
**handle_scsi3_cmd()
いい加減に実装しているので使い易いか分らないが、自分で必要と考えていた
INQUIRYとREAD ATTRIBUTEの供用として使えたので、まぁいいんだろう。
---(
#define SG_VERSION3 30000
int handle_cmd_sg3(
  int fd, 
  unsigned char *cdb, 
  int cdblen,
  int dxfer,
  unsigned char *rbuf,
  int rbuflen
) {
  int ret, k, i;
  sg_io_hdr_t sg_hdr;
  sg_io_hdr_t *p = &sg_hdr;

  int senselen = 0xffff;
  unsigned char sense_buffer[senselen];

  // SG_IOが使えるかチェックする前置き
  if ( ioctl(fd, SG_GET_VERSION_NUM, &k) < 0 ||
    k < SG_VERSION3 ) {
    fprintf(stderr, 
      "unable to use this, bacause SG version is elder than %d\n", 
      SG_VERSION3);
    return -1;
  }

  memset(p, 0, sizeof(sg_io_hdr_t));
  p->interface_id = 'S';// required and fixed
  p->cmd_len = cdblen;
  p->cmdp = cdb;
  // p->iovec_count = 0; vec ioする場合

  p->dxfer_direction = dxfer;
  /*
    SG_DXFER_NONE      SCSI test unit ready command
    SG_DXFER_TO_DEV      SCSI WRITE command
    SG_DXFER_FROM_DEV    SCSI READ command
    SG_DXFER_TO_FROM_DEV  use only relevant to indirect I/O
    SG_DEXFER_UNKNOWN    misc. For vendor specific.
  */
  p->dxfer_len = rbuflen;
  p->dxferp = rbuf;

  p->mx_sb_len = sizeof(sense_buffer);
  p->sbp = sense_buffer;

  p->timeout = 10000;// timeout 10sec

  //p->flags = 0;
  //p->pack_id = 0;
  //p->usr_ptr = NULL;

  ret = ioctl(fd, SG_IO, p);
  if ( ret == -1 ) {
    fprintf(stderr, "ioctl(SG_IO) : %s[%d]\n", strerror(errno), errno);
    return -1;
  }

  // handling response
  if ( (p->info & SG_INFO_OK_MASK) != SG_INFO_OK ) {
    // failure case
    if ( p->sb_len_wr > 0 ) {
      fprintf(stderr, "SENSE DATA: ");
      for ( i = 0; i < p->sb_len_wr; i++ ) {
        printf("0x%02x ", sense_buffer[i]);
      }
      printf("\n");
    }

    if ( p->masked_status ) 
      printf("SCSI STATUS : 0x%x\n", p->status);
    if ( p->host_status ) 
      printf("HOST STATUS : 0x%x\n", p->host_status);
    if ( p->driver_status ) 
      printf("DRIVER STATUS : 0x%x\n", p->driver_status);
    return -1;
  } 

  return 0;
}
---)

*参考文献
Linuxの開発参考文献はonlineで必要なものは大体手に入る。
-SGドライバのドキュメント
--http://sg.torque.net/sg/p/sg_v3_ho.html
-Linux JFのSCSI機器用プログラミングHowTo
--http://www.linux.or.jp/JF/JFdocs/SCSI-Programming-HOWTO.html
--http://archive.linux.or.jp/JF/JFdocs/SCSI-Programming-HOWTO.html
-SCSIの仕様
--http://www.t10.org/drafts.htm


Last-modified: 2010-11-15 18:07:16