SCSI指令C编程

一、 Windows系统scsi协议编码
1. 结构体定义:
#define SPT_SENSE_LENGTH 32
#define SPTWB_DATA_LENGTH 2148  //大小自定义,可能是根据硬件定义

typedef struct _SCSI_PASS_THROUGH {
  USHORT    Length;    //sizeof(SCSI_PASS_THROUGH)
  UCHAR     ScsiStatus;    //defalut 0
  UCHAR     PathId; //defalut 0
  UCHAR     TargetId;//defalut 0
  UCHAR     Lun;    //逻辑单元号
  UCHAR     CdbLength;    //cdb长度
  UCHAR     SenseInfoLength; //defalut 0x24
  UCHAR     DataIn;    //从设备读取数据SCSI_IOCTL_DATA_IN, 写数据到设备SCSI_IOCTL_DATA_OUT,  SCSI_IOCTL_DATA_UNSPECIFIED
  ULONG     DataTransferLength; //写数据到设备时实际数据长度
  ULONG     TimeOutValue;    //defalut 40s
  ULONG_PTR DataBufferOffset; //ucSenseBuf在SCSI_PASS_THROUGH_WITH_BUFFERS结构中相对于结构体起始的偏移,按照结构体对其规则的偏移
  ULONG     SenseInfoOffset;  //ucSenseBuf在SCSI_PASS_THROUGH_WITH_BUFFERS结构中相对于结构体起始的偏移,按照结构体对其规则的偏移
  UCHAR     Cdb[16];    //command block,self-define length
} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;

typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS {
    SCSI_PASS_THROUGH spt;
    ULONG             Filler;      // realign buffers to double word boundary
    UCHAR             ucSenseBuf[SPT_SENSE_LENGTH];
    UCHAR             ucDataBuf[SPTWB_DATA_LENGTH];
} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;

2. 打开设备使用CreateFileA(devName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);

3. 发送函数
DeviceIoControl(hHandle,IOCTL_SCSI_PASS_THROUGH,&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS),&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS),&retLen,FALSE)

4. 返回数据
ucSenseBuf中包含自定义结构的设备返回状态;
在2中retLen表示返回数据结构体,如果retLen小于DataBufferOffset表示无数据返回,这种情况是有异常的。
实际数据在ucDataBuf中,长度为:retLen-DataBufferOffset


二、linux系统scsi协议编码
1. 结构体定义:
typedef struct sg_io_hdr
{
    int interface_id;           /* [i] 'S' for SCSI generic (required) */固定
    int dxfer_direction;        /* [i] data transfer direction  */ 传输方向:读-SG_DXFER_FROM_DEV,写-SG_DXFER_TO_DEV
    unsigned char cmd_len;      /* [i] SCSI command length ( <= 16 bytes) */ CDB
    unsigned char mx_sb_len;    /* [i] max length to write to sbp */    senselen 一般固定0x24
    unsigned short iovec_count; /* [i] 0 implies no scatter gather */ default 0
    unsigned int dxfer_len;     /* [i] byte count of data transfer */ 读取或者写入的数据长度
    void *dxferp;                /* [i], [*io] points to data transfer memory or scatter gather list */ 数据输入输出缓冲区
    unsigned char *cmdp;        /* [i], [*i] points to command to perform */ CDB缓冲区
    void *sbp;                    /* [i], [*o] points to sense_buffer memory */    sense缓冲区
    unsigned int timeout;       /* [i] MAX_UINT->no timeout (unit: millisec) */ dafault 40s
    unsigned int flags;         /* [i] 0 -> default, see SG_FLAG... */ dafault 0
    int pack_id;                /* [i->o] unused internally (normally) */
    void * usr_ptr;             /* [i->o] unused internally */
    unsigned char status;       /* [o] scsi status */
    unsigned char masked_status;/* [o] shifted, masked scsi status */
    unsigned char msg_status;   /* [o] messaging level data (optional) */
    unsigned char sb_len_wr;    /* [o] byte count actually written to sbp */
    unsigned short host_status; /* [o] errors from host adapter */
    unsigned short driver_status;/* [o] errors from software driver */
    int resid;                  /* [o] dxfer_len - actual_transferred */
    unsigned int duration;      /* [o] time taken by cmd (unit: millisec) */
    unsigned int info;          /* [o] auxiliary information */
} sg_io_hdr_t;   

2. 打开设备使用open(devName, O_RDWR | O_DIRECT);

3. 发送函数
ret = ioctl(hHandle, SG_IO, &scsi_hdr);

4. 返回数据
返回数据在scsi_hdr.dxferp中
senseBuf中包含返回状态
 

你可能感兴趣的:(编程语言)