6

SSDにscsiread (10)write(10)を発行しようとしています。このサンプルコードをリファレンス/基本コードとして使用します。

これは私のscsiの読み取りです:

#define READ_REPLY_LEN 32
#define READ_CMDLEN 10
void scsi_read()
{
  unsigned char Readbuffer[ SCSI_OFF + READ_REPLY_LEN ];
  unsigned char cmdblk [ READ_CMDLEN ] =
      {        0x28,  /* command */
                  0,  /* lun/reserved */
                  0,  /* lba */
                  0,  /* lba */
                  0,  /* lba */
                  0,  /* lba */
                  0,  /* reserved */
                  0,  /* transfer length */
     READ_REPLY_LEN,  /* transfer length */
                  0 };/* reserved/flag/link */
  memset(Readbuffer,0,sizeof(Readbuffer));
  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(Readbuffer) - SCSI_OFF, Readbuffer )) {
      fprintf( stderr, "read failed\n" );
      exit(2);
  }
  hex_dump(Readbuffer,sizeof(Readbuffer));
}

そしてこれは私のscsi書き込みです:

void scsi_write ( void )
{
  unsigned char Writebuffer[SCSI_OFF];
  unsigned char cmdblk [] =
      {        0x2A,  /* 0: command */
                  0,  /* 1: lun/reserved */
                  0,  /* 2: LBA */
                  0,  /* 3: LBA */
                  0,  /* 4: LBA */
                  0,  /* 5: LBA */
                  0,  /* 6: reserved */
                  0,  /* 7: transfer length */
                  0,  /* 8: transfer length */
                  0 };/* 9: control */

  memset(Writebuffer,0,sizeof(Writebuffer));
  memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );
  cmd[SCSI_OFF+sizeof(cmdblk)+0] = 'A';
  cmd[SCSI_OFF+sizeof(cmdblk)+1] = 'b';
  cmd[SCSI_OFF+sizeof(cmdblk)+2] = 'c';
  cmd[SCSI_OFF+sizeof(cmdblk)+3] = 'd';
  cmd[SCSI_OFF+sizeof(cmdblk)+4] = 'e';
  cmd[SCSI_OFF+sizeof(cmdblk)+5] = 'f';
  cmd[SCSI_OFF+sizeof(cmdblk)+6] = 'g';
  cmd[SCSI_OFF+sizeof(cmdblk)+7] = 0;
  /*
   * +------------------+
   * | struct sg_header | <- cmd
   * +------------------+
   * | copy of cmdblk   | <- cmd + SCSI_OFF
   * +------------------+
   * | data to write    | 
   * +------------------+
   */

  if (handle_scsi_cmd(sizeof(cmdblk), 8, cmd, 
                      sizeof(Writebuffer) - SCSI_OFF, Writebuffer )) {
      fprintf( stderr, "write failed\n" );
      exit(2);
  }
}

次の例では、

  1. scsi読み取り
  2. scsi書き込み
  3. scsi読み取り

そして、書き込まれたデータ(scsi書き込み)と読み取られたデータ(scsi読み取り)の16進ダンプを出力します。

Read(10)
[0000]   00 00 00 44 00 00 00 44   00 00 00 00 00 00 00 00   ...D...D ........
[0010]   00 2C 00 00 00 00 00 00   00 00 00 00 00 00 00 00   ........ ........
[0020]   00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00   ........ ........
[0030]   00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00   ........ ........
[0040]   00 00 00 00                                         ....

Write(10):
[0000]   00 00 00 00 00 00 00 24   00 00 00 00 00 00 00 00   ........ ........
[0010]   00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00   ........ ........
[0020]   00 00 00 00 2A 00 00 00   00 00 00 00 00 00 41 62   ........ ......Ab
[0030]   63 64 65 66 67 00                                   cdefg.

Read(10):
[0000]   00 00 00 44 00 00 00 44   00 00 00 00 00 00 00 00   ...D...D ........
[0010]   04 00 20 00 70 00 02 00   00 00 00 0A 00 00 00 00   ....p... ........
[0020]   04 00 00 00 41 62 63 64   65 66 67 00 00 00 00 00   ....Abcd efg.....
[0030]   00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00   ........ ........
[0040]   00 00 00 00                                         ....

3つのコマンドを再度実行した後Abcdefg、最初の読み取りで読み取る必要があります。右?しかし、それらを再度実行しても何も変わりません。これで、使用するメモリには以前の関数のデータが残っていると想定できますがmemset(Readbuff,0,sizeof(Readbuff))、発生する前に実行しても同じ結果が得られsys_read()ます。

私が書き込もうとしているLBAはおそらく書き込みが禁止されていると思い、キャッシュを読み取りました。しかし、0x00〜0xFFのLBAアドレスを介して対話しても、何も変わりません。つまり、同じデータを読み取ります(Abcdefg)。

scsiジェネリックインターフェイスを使用したscsi読み取りまたは書き込みの実装例を知っていますか?

4

1 に答える 1

5

In SCSI, the units of the LBA and the transfer length are in blocks, sometimes called sectors. This is almost always 512 bytes. So, you can't read or write just 32 bytes. At a minimum, you'll have to do 512 bytes == one block. This one point is most of what you need to fix.

Your transfer length is zero in your scsi_write implementation, so it's not actually going to write any data.

You should use different buffers for the CDB and the write/read data. I suspect that confusion about these buffers is leading your implementation to write past the end of one of your statically-allocated arrays and over your ReadBuffer. Run it under valgrind and see what shows up.

And lastly, a lot could go wrong in whatever is in handle_scsi_cmd. It can be tricky to set up the data transfer... in particular, make sure you're straight on which way the data is going in the I/O header's dxfer_direction: SG_DXFER_TO_DEV for write, SG_DXFER_FROM_DEV for read.

Check out this example of how to do a read(16). This is more along the lines of what you're trying to accomplish.

https://github.com/hreinecke/sg3_utils/blob/master/examples/sg_simple16.c

于 2012-08-10T14:35:50.110 に答える