一、 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中包含返回状态