目次
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()ここを参照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で必要なものは大体手に入る。
|