📄 scsicmds.cpp
字号:
int scsiModeSense(int device, int pagenum, int subpagenum, int pc, UINT8 *pBuf, int bufLen){ struct scsi_cmnd_io io_hdr; struct scsi_sense_disect sinfo; UINT8 cdb[6]; UINT8 sense[32]; int status; if ((bufLen < 0) || (bufLen > 255)) return -EINVAL; memset(&io_hdr, 0, sizeof(io_hdr)); memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; cdb[0] = MODE_SENSE; cdb[2] = (pc << 6) | (pagenum & 0x3f); cdb[3] = subpagenum; cdb[4] = bufLen; io_hdr.cmnd = cdb; io_hdr.cmnd_len = sizeof(cdb); io_hdr.sensep = sense; io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl); if (0 != status) return status; scsi_do_sense_disect(&io_hdr, &sinfo); status = scsiSimpleSenseFilter(&sinfo); if (SIMPLE_ERR_TRY_AGAIN == status) { status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl); if (0 != status) return status; scsi_do_sense_disect(&io_hdr, &sinfo); status = scsiSimpleSenseFilter(&sinfo); } if ((0 == status) && (ALL_MODE_PAGES != pagenum)) { int offset; offset = scsiModePageOffset(pBuf, bufLen, 0); if (offset < 0) return SIMPLE_ERR_BAD_RESP; else if (pagenum != (pBuf[offset] & 0x3f)) return SIMPLE_ERR_BAD_RESP; } return status;}/* Sends a 6 byte MODE SELECT command. Assumes given pBuf is the response * from a corresponding 6 byte MODE SENSE command. Such a response should * have a 4 byte header followed by 0 or more 8 byte block descriptors * (normally 1) and then 1 mode page. Returns 0 if ok, 1 if NOT READY, * 2 if command not supported (then MODE SELECT(10) may be supported), * 3 if field in command not supported, 4 if bad parameter to command * or returns negated errno. SPC-3 sections 6.7 and 7.4 (rev 22a) */int scsiModeSelect(int device, int sp, UINT8 *pBuf, int bufLen){ struct scsi_cmnd_io io_hdr; struct scsi_sense_disect sinfo; UINT8 cdb[6]; UINT8 sense[32]; int status, pg_offset, pg_len, hdr_plus_1_pg; pg_offset = 4 + pBuf[3]; if (pg_offset + 2 >= bufLen) return -EINVAL; pg_len = pBuf[pg_offset + 1] + 2; hdr_plus_1_pg = pg_offset + pg_len; if (hdr_plus_1_pg > bufLen) return -EINVAL; pBuf[0] = 0; /* Length of returned mode sense data reserved for SELECT */ pBuf[pg_offset] &= 0x7f; /* Mask out PS bit from byte 0 of page data */ memset(&io_hdr, 0, sizeof(io_hdr)); memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = hdr_plus_1_pg; io_hdr.dxferp = pBuf; cdb[0] = MODE_SELECT; cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */ cdb[4] = hdr_plus_1_pg; /* make sure only one page sent */ io_hdr.cmnd = cdb; io_hdr.cmnd_len = sizeof(cdb); io_hdr.sensep = sense; io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl); if (0 != status) return status; scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo);}/* MODE SENSE (10 byte). Returns 0 if ok, 1 if NOT READY, 2 if command * not supported (then MODE SENSE(6) might be supported), 3 if field in * command not supported or returns negated errno. * SPC-3 sections 6.10 and 7.4 (rev 22a) [mode subpage==0] */int scsiModeSense10(int device, int pagenum, int subpagenum, int pc, UINT8 *pBuf, int bufLen){ struct scsi_cmnd_io io_hdr; struct scsi_sense_disect sinfo; UINT8 cdb[10]; UINT8 sense[32]; int status; memset(&io_hdr, 0, sizeof(io_hdr)); memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; cdb[0] = MODE_SENSE_10; cdb[2] = (pc << 6) | (pagenum & 0x3f); cdb[3] = subpagenum; cdb[7] = (bufLen >> 8) & 0xff; cdb[8] = bufLen & 0xff; io_hdr.cmnd = cdb; io_hdr.cmnd_len = sizeof(cdb); io_hdr.sensep = sense; io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl); if (0 != status) return status; scsi_do_sense_disect(&io_hdr, &sinfo); status = scsiSimpleSenseFilter(&sinfo); if (SIMPLE_ERR_TRY_AGAIN == status) { status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl); if (0 != status) return status; scsi_do_sense_disect(&io_hdr, &sinfo); status = scsiSimpleSenseFilter(&sinfo); } if ((0 == status) && (ALL_MODE_PAGES != pagenum)) { int offset; offset = scsiModePageOffset(pBuf, bufLen, 1); if (offset < 0) return SIMPLE_ERR_BAD_RESP; else if (pagenum != (pBuf[offset] & 0x3f)) return SIMPLE_ERR_BAD_RESP; } return status;}/* Sends a 10 byte MODE SELECT command. Assumes given pBuf is the response * from a corresponding 10 byte MODE SENSE command. Such a response should * have a 8 byte header followed by 0 or more 8 byte block descriptors * (normally 1) and then 1 mode page. Returns 0 if ok, 1 NOT REAFY, 2 if * command not supported (then MODE SELECT(6) may be supported), 3 if field * in command not supported, 4 if bad parameter to command or returns * negated errno. SPC-3 sections 6.8 and 7.4 (rev 22a) */int scsiModeSelect10(int device, int sp, UINT8 *pBuf, int bufLen){ struct scsi_cmnd_io io_hdr; struct scsi_sense_disect sinfo; UINT8 cdb[10]; UINT8 sense[32]; int status, pg_offset, pg_len, hdr_plus_1_pg; pg_offset = 8 + (pBuf[6] << 8) + pBuf[7]; if (pg_offset + 2 >= bufLen) return -EINVAL; pg_len = pBuf[pg_offset + 1] + 2; hdr_plus_1_pg = pg_offset + pg_len; if (hdr_plus_1_pg > bufLen) return -EINVAL; pBuf[0] = 0; pBuf[1] = 0; /* Length of returned mode sense data reserved for SELECT */ pBuf[pg_offset] &= 0x7f; /* Mask out PS bit from byte 0 of page data */ memset(&io_hdr, 0, sizeof(io_hdr)); memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_TO_DEVICE; io_hdr.dxfer_len = hdr_plus_1_pg; io_hdr.dxferp = pBuf; cdb[0] = MODE_SELECT_10; cdb[1] = 0x10 | (sp & 1); /* set PF (page format) bit always */ cdb[8] = hdr_plus_1_pg; /* make sure only one page sent */ io_hdr.cmnd = cdb; io_hdr.cmnd_len = sizeof(cdb); io_hdr.sensep = sense; io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl); if (0 != status) return status; scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo);}/* Standard INQUIRY returns 0 for ok, anything else is a major problem. * bufLen should be 36 for unsafe devices (like USB mass storage stuff) * otherwise they can lock up! SPC-3 sections 6.4 and 7.6 (rev 22a) */int scsiStdInquiry(int device, UINT8 *pBuf, int bufLen){ struct scsi_sense_disect sinfo; struct scsi_cmnd_io io_hdr; UINT8 cdb[6]; UINT8 sense[32]; int status; if ((bufLen < 0) || (bufLen > 255)) return -EINVAL; memset(&io_hdr, 0, sizeof(io_hdr)); memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; cdb[0] = INQUIRY; cdb[4] = bufLen; io_hdr.cmnd = cdb; io_hdr.cmnd_len = sizeof(cdb); io_hdr.sensep = sense; io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl); if (0 != status) return status; scsi_do_sense_disect(&io_hdr, &sinfo); return scsiSimpleSenseFilter(&sinfo);}/* INQUIRY to fetch Vital Page Data. Returns 0 if ok, 1 if NOT READY * (unlikely), 2 if command not supported, 3 if field in command not * supported, 5 if response indicates that EVPD bit ignored or returns * negated errno. SPC-3 section 6.4 and 7.6 (rev 22a) */int scsiInquiryVpd(int device, int vpd_page, UINT8 *pBuf, int bufLen){ struct scsi_cmnd_io io_hdr; struct scsi_sense_disect sinfo; UINT8 cdb[6]; UINT8 sense[32]; int status, res; if ((bufLen < 0) || (bufLen > 255)) return -EINVAL; memset(&io_hdr, 0, sizeof(io_hdr)); memset(cdb, 0, sizeof(cdb)); if (bufLen > 1) pBuf[1] = 0x0; io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; cdb[0] = INQUIRY; cdb[1] = 0x1; /* set EVPD bit (enable Vital Product Data) */ cdb[2] = vpd_page; cdb[4] = bufLen; io_hdr.cmnd = cdb; io_hdr.cmnd_len = sizeof(cdb); io_hdr.sensep = sense; io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl); if (0 != status) return status; scsi_do_sense_disect(&io_hdr, &sinfo); if ((res = scsiSimpleSenseFilter(&sinfo))) return res; /* Guard against devices that ignore EVPD bit and do standard INQUIRY */ if (bufLen > 1) { if (vpd_page == pBuf[1]) { if ((0x80 == vpd_page) && (bufLen > 2) && (0x0 != pBuf[2])) return SIMPLE_ERR_BAD_RESP; } else return SIMPLE_ERR_BAD_RESP; } return 0;}/* REQUEST SENSE command. Returns 0 if ok, anything else major problem. * SPC-3 section 6.27 (rev 22a) */int scsiRequestSense(int device, struct scsi_sense_disect * sense_info){ struct scsi_cmnd_io io_hdr; UINT8 cdb[6]; UINT8 sense[32]; UINT8 buff[18]; int status, len; UINT8 ecode; memset(&io_hdr, 0, sizeof(io_hdr)); memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = DXFER_FROM_DEVICE; io_hdr.dxfer_len = sizeof(buff); io_hdr.dxferp = buff; cdb[0] = REQUEST_SENSE; cdb[4] = sizeof(buff); io_hdr.cmnd = cdb; io_hdr.cmnd_len = sizeof(cdb); io_hdr.sensep = sense; io_hdr.max_sense_len = sizeof(sense); io_hdr.timeout = SCSI_TIMEOUT_DEFAULT; status = do_scsi_cmnd_io(device, &io_hdr, con->reportscsiioctl); if ((0 == status) && (sense_info)) { ecode = buff[0] & 0x7f; sense_info->error_code = ecode; sense_info->sense_key = buff[2] & 0xf; sense_info->asc = 0; sense_info->ascq = 0; if ((0x70 == ecode) || (0x71 == ecode)) { len = buff[7] + 8; if (len > 13) { sense_info->asc = buff[12]; sense_info->ascq = buff[13]; } } } return status;}/* SEND DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if command * not supported, 3 if field in command not supported or returns negated * errno. SPC-3 section 6.28 (rev 22a) */int scsiSendDiagnostic(int device, int functioncode, UINT8 *pBuf, int bufLen){ struct scsi_cmnd_io io_hdr; struct scsi_sense_disect sinfo; UINT8 cdb[6]; UINT8 sense[32]; int status; memset(&io_hdr, 0, sizeof(io_hdr)); memset(cdb, 0, sizeof(cdb)); io_hdr.dxfer_dir = bufLen ? DXFER_TO_DEVICE: DXFER_NONE; io_hdr.dxfer_len = bufLen; io_hdr.dxferp = pBuf; cdb[0] = SEND_DIAGNOSTIC; if (SCSI_DIAG_DEF_SELF_TEST == functioncode) cdb[1] = 0x4; /* SelfTest bit */ else if (SCSI_DIAG_NO_SELF_TEST != functioncode) cdb[1] = (functioncode & 0x7) << 5; /* SelfTest _code_ */ else /* SCSI_DIAG_NO_SELF_TEST == functioncode */ cdb[1] = 0x10; /* PF bit */ cdb[3] = (bufLen >> 8) & 0xff; cdb[4] = bufLen & 0xff; io_hdr.cmnd = cdb; io_hdr.cmnd_len = sizeof(cdb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -