如何为连续的LBA执行SCSI写入,例如“ 0x0000至0x1000”

时间:2019-04-02 11:37:59

标签: c# scsi

灌木丛的日志使我困惑。日志是这样的。

//block a

{ 
    9 CMD 2a 00 00 00 00 00 00 00 80 00 WRITE 3317238.1.0
    9 CMD 2a 00 00 00 00 80 00 00 80 00 WRITE 3317239.1.0
    9 CMD 2a 00 00 00 01 00 00 00 80 00 WRITE 3317240.1.0
    9 CMD 2a 00 00 00 01 80 00 00 80 00 WRITE 3317241.1.0
    . . ~ . . for 32 times

    9 OUT 03 00 00 00 03 00 00 00 04 00 00 00 03 00 00 00 05 00 00 00 03 00 00 00 06 00 00 00 03 00 00 00 ................................ 3317238.2.0
    07 00 00 00 03 00 00 00 08 00 00 00 03 00 00 00 09 00 00 00 03 00 00 00 0a 00 00 00 03 00 00 00 ................................ 3317238.2.32
    0b 00 00 00 03 00 00 00 0c 00 00 00 03 00 00 00 0d 00 00 00 03 00 00 00 0e 00 00 00 03 00 00 00 ................................ 3317238.2.64
    0f 00 00 00 03 00 00 00 10 00 00 00 03 00 00 00 11 00 00 00 03 00 00 00 12 00 00 00 03 00 00 00 ................................ 3317238.2.96
    . . ~ . . for 1KB data 
}

//end of block a

据我所知,是通过多个SCSI写入命令将数据从0x0000到0x1000写入LBA,还是由一个SCSI写入命令完成?

我可以执行SCSI向设备写入64KB的操作。丛林日志是这样的。

// block b

{
    13 CMD 2a 00 00 00 00 00 00 00 80 00 WRITE 394.1.0
    13 CMD 00 00 00 00 00 00 TEST UNIT READY 395.1.0
    13 OUT 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 .;...;...;...;...;...;...;...;.. 394.2.0
    7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 .;...;...;...;...;...;...;...;.. 394.2.32
    7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 .;...;...;...;...;...;...;...;.. 394.2.64
    7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 7d 3b ef 84 .;...;...;...;...;...;...;...;.. 394.2.96
    . . ~ . . for 1KB data
}

//end of block b

如果我发送了32次SCSI写命令,那么我的日志将成为b块中的32次。

我正在C#中使用这些代码进行SCSI写入。如果len> 128,则返回0x57。所以这是64KB的限制。

private Boolean SendCMD(byte OPCode, ref byte[] buf, long len, long addr, ref int errorCode)
{
    bool result = false;
    SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptwb = null;
    sptwb = new SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER((UInt32)(len * 512));
    sptwb.sptd.Cdb[1] = 0x00;
    sptwb.sptd.Cdb[2] = (byte)((addr >> 24) & 0xFF);    // MSB of lba
    sptwb.sptd.Cdb[3] = (byte)((addr >> 16) & 0xFF);
    sptwb.sptd.Cdb[4] = (byte)((addr >> 8) & 0xFF);
    sptwb.sptd.Cdb[5] = (byte)((addr) & 0xFF);          // LSB of lba
    sptwb.sptd.Cdb[6] = 0x00;
    sptwb.sptd.Cdb[7] = (byte)((len >> 8) & 0xFF);      // MSB of num blocks
    sptwb.sptd.Cdb[8] = (byte)((len) & 0xFF);           // LSB of num blocks
    sptwb.sptd.Cdb[9] = 0x00;

    sptwb.sptd.DataIn = SCSI_IOCTL_DATA_OUT;

    Marshal.Copy(buf, 0, ptrBuf, (int)(len * 512));

    sptwb.sptd.CdbLength = 10;
    sptwb.sptd.Cdb[0] = OPCode;
    sptwb.sptd.DataBuffer = ptrBuf;

    int outByte = 0;
    int inputSize = Marshal.SizeOf(typeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));

    IntPtr input = Marshal.AllocHGlobal(inputSize);
    Marshal.StructureToPtr(sptwb, input, true);

    result = DeviceIoControl(m_hDrive, IOCTL_SCSI_PASS_THROUGH_DIRECT, input, inputSize, input, inputSize, ref outByte, System.IntPtr.Zero);

    return result;
}

是否有一种像日志块a一样发送SCSI写操作的方法?谢谢,感谢您的帮助!

对不起,也许我应该更改我的问题。

是否可以通过SCSI命令将LBA 0x00000000的SD卡写入LBA的末尾?我可以发送不超过MaximumTransferLength的数据的单个SCSI write10。尽管我可以发送许多SCSI写入来完成SD卡的完全写入操作,但是从SD卡的角度来看,它仍然不是单个的多重写入操作。如何通过发送SCSI命令(如日志A一样)来写大数据(大于MaximumTransferLength)(这是SD卡级别的单个多次写操作)?

0 个答案:

没有答案