SCSI读取(10)和写入(10)与SCSI通用接口

我尝试发出scsi 读(10)并写入(10)到SSD。 我使用这个示例代码作为参考/基本代码。

这是我的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写入)的hexdump和读取的内容(scsi读取)

 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 .... 

为了再次运行这三个命令,我应该先阅读Abcdefg 。 对? 但是再次运行它们并没有改变。 你现在可以假设,我使用的内存仍然是以前的function的数据,但即使在sys_read()发生之前运行memset(Readbuff,0,sizeof(Readbuff))我也会得到相同的结果。

我认为,我试图写的LBA可能是禁止写的,我读了caching。 但是通过LBA地址从0x00-0xFF进行交换并不会改变 – 也就是说,我读取了相同的数据( Abcdefg )。

你知道scsi读写的一个示例实现吗?

Solutions Collecting From Web of "SCSI读取(10)和写入(10)与SCSI通用接口"

在SCSI中,LBA的单位和传输长度是块的,有时也称为扇区。 这几乎总是512字节。 所以,你不能只读或写32字节。 至少,你将不得不做512个字节==一个块。 这一点是你需要解决的大部分问题。

您的scsi_write实现中传输长度为零,所以实际上并不会写入任何数据。

您应该为CDB和写入/读取数据使用不同的缓冲区。 我怀疑这些缓冲区的混乱是导致你的实现写过去的静态分配的数组之一,并通过您的ReadBuffer。 在valgrind下运行,看看出现了什么。

最后,handle_scsi_cmd中的任何内容都会出错。 设置数据传输可能会非常棘手,尤其是确保您直接在I / O头的dxfer_direction中写入数据:SG_DXFER_TO_DEV用于写入,SG_DXFER_FROM_DEV用于读取。

看看这个如何做一个读取(16)的例子。 这更符合你正在努力完成的任务。

http://fossies.org/linux/misc/sg3_utils-1.33.tgz:a/sg3_utils-1.33/examples/sg_simple16.c