diff --git a/sm5/scsicmds.c b/sm5/scsicmds.c index 77583b426498baf30b3ae4d6e62e12dc09aa3517..8a037b51b57bd144c647336678eb0b614a8b44b4 100644 --- a/sm5/scsicmds.c +++ b/sm5/scsicmds.c @@ -46,7 +46,7 @@ #include "utility.h" #include "extern.h" -const char *scsicmds_c_cvsid="$Id: scsicmds.c,v 1.62 2003/11/17 11:48:47 dpgilbert Exp $" EXTERN_H_CVSID SCSICMDS_H_CVSID; +const char *scsicmds_c_cvsid="$Id: scsicmds.c,v 1.63 2003/11/18 13:44:46 dpgilbert Exp $" EXTERN_H_CVSID SCSICMDS_H_CVSID; /* for passing global control variables */ extern smartmonctrl *con; @@ -746,15 +746,14 @@ int scsiFetchIECmpage(int device, struct scsi_iec_mode_page *iecp, int modese_le if ((err = scsiModeSense(device, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE, MODE_PAGE_CONTROL_CURRENT, iecp->raw_curr, sizeof(iecp->raw_curr)))) { - if (0 == err) - iecp->modese_len = 6; - else if (SIMPLE_ERR_BAD_OPCODE == err) + if (SIMPLE_ERR_BAD_OPCODE == err) iecp->modese_len = 10; else { iecp->modese_len = 0; return err; } - } + } else if (0 == iecp->modese_len) + iecp->modese_len = 6; } if (10 == iecp->modese_len) { err = scsiModeSense10(device, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE, @@ -829,7 +828,7 @@ int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp) int scsiSetExceptionControlAndWarning(int device, int enabled, const struct scsi_iec_mode_page *iecp) { - int k, offset; + int k, offset, resp_len; int err = 0; UINT8 rout[SCSI_IECMP_RAW_LEN]; int sp, eCEnabled, wEnabled; @@ -841,9 +840,13 @@ int scsiSetExceptionControlAndWarning(int device, int enabled, if (offset < 0) return -EINVAL; memcpy(rout, iecp->raw_curr, SCSI_IECMP_RAW_LEN); - rout[0] = 0; /* Mode Data Length reserved in MODE SELECTs */ - if (10 == iecp->modese_len) - rout[1] = 0; + if (10 == iecp->modese_len) { + resp_len = (rout[0] << 8) + rout[1] + 2; + memset(rout, 0, 2); /* mode data length==0 for mode select */ + } else { + resp_len = rout[0] + 1; + memset(rout, 0, 1); /* mode data length==0 for mode select */ + } sp = (rout[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */ rout[offset] &= 0x7f; /* mask off PS bit */ if (enabled) { @@ -892,9 +895,9 @@ int scsiSetExceptionControlAndWarning(int device, int enabled, } } if (10 == iecp->modese_len) - err = scsiModeSelect10(device, sp, rout, sizeof(rout)); + err = scsiModeSelect10(device, sp, rout, resp_len); else if (6 == iecp->modese_len) - err = scsiModeSelect(device, sp, rout, sizeof(rout)); + err = scsiModeSelect(device, sp, rout, resp_len); return err; } @@ -1564,13 +1567,12 @@ int scsiFetchExtendedSelfTestTime(int device, int * durationSec, int modese_len) if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, MODE_PAGE_CONTROL_CURRENT, buff, sizeof(buff)))) { - if (0 == err) - modese_len = 6; - else if (SIMPLE_ERR_BAD_OPCODE == err) + if (SIMPLE_ERR_BAD_OPCODE == err) modese_len = 10; else return err; - } + } else if (0 == modese_len) + modese_len = 6; } if (10 == modese_len) { err = scsiModeSense10(device, CONTROL_MODE_PAGE, @@ -1732,7 +1734,6 @@ int scsiCountFailedSelfTests(int fd, int noisy) return (fail_hour << 8) + fails; } - /* Returns a negative value if failed to fetch Contol mode page or it was malformed. Returns 0 if GLTSD bit is zero and returns 1 if the GLTSD bit is set. */ @@ -1746,13 +1747,12 @@ int scsiFetchControlGLTSD(int device, int modese_len) if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, MODE_PAGE_CONTROL_CURRENT, buff, sizeof(buff)))) { - if (0 == err) - modese_len = 6; - else if (SIMPLE_ERR_BAD_OPCODE == err) + if (SIMPLE_ERR_BAD_OPCODE == err) modese_len = 10; else return -EINVAL; - } + } else if (0 == modese_len) + modese_len = 6; } if (10 == modese_len) { err = scsiModeSense10(device, CONTROL_MODE_PAGE, @@ -1767,6 +1767,69 @@ int scsiFetchControlGLTSD(int device, int modese_len) return -EINVAL; } +/* Attempts to clear GLTSD bit in Control mode page. Returns 0 if + successful, negative if low level error, > 0 if higher level error (e.g. + SIMPLE_ERR_BAD_PARAM if GLTSD bit is not changeable). */ +int scsiClearControlGLTSD(int device, int modese_len) +{ + int err, offset, resp_len, sp; + UINT8 buff[64]; + UINT8 ch_buff[64]; + + memset(buff, 0, sizeof(buff)); + if (modese_len <= 6) { + if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, + MODE_PAGE_CONTROL_CURRENT, + buff, sizeof(buff)))) { + if (SIMPLE_ERR_BAD_OPCODE == err) + modese_len = 10; + else + return err; + } else if (0 == modese_len) + modese_len = 6; + } + if (10 == modese_len) { + err = scsiModeSense10(device, CONTROL_MODE_PAGE, + MODE_PAGE_CONTROL_CURRENT, + buff, sizeof(buff)); + if (err) + return err; + } + offset = scsiModePageOffset(buff, sizeof(buff), modese_len); + if ((offset < 0) || (buff[offset + 1] < 0xa)) + return SIMPLE_ERR_BAD_RESP; + if (0 == (buff[offset + 2] & 2)) + return 0; /* already clear so nothing to do */ + if (modese_len == 6) + err = scsiModeSense(device, CONTROL_MODE_PAGE, + MODE_PAGE_CONTROL_CHANGEABLE, + ch_buff, sizeof(ch_buff)); + else + err = scsiModeSense10(device, CONTROL_MODE_PAGE, + MODE_PAGE_CONTROL_CHANGEABLE, + ch_buff, sizeof(ch_buff)); + if (err) + return err; + if (0 == (ch_buff[offset + 2] & 2)) + return SIMPLE_ERR_BAD_PARAM; /* GLTSD bit not chageable */ + + if (10 == modese_len) { + resp_len = (buff[0] << 8) + buff[1] + 2; + memset(buff, 0, 2); + } else { + resp_len = buff[0] + 1; + memset(buff, 0, 1); + } + sp = (buff[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */ + buff[offset] &= 0x7f; /* mask off PS bit */ + buff[offset + 2] &= 0xfd; /* clear GLTSD bit in buff */ + if (10 == modese_len) + err = scsiModeSelect10(device, sp, buff, resp_len); + else if (6 == modese_len) + err = scsiModeSelect(device, sp, buff, resp_len); + return err; +} + /* Returns a negative value if failed to fetch Protocol specific port mode page or it was malformed. Returns transport protocol identifier when value >= 0 . */ @@ -1780,13 +1843,12 @@ int scsiFetchTransportProtocol(int device, int modese_len) if ((err = scsiModeSense(device, PROTOCOL_SPECIFIC_PORT_PAGE, MODE_PAGE_CONTROL_CURRENT, buff, sizeof(buff)))) { - if (0 == err) - modese_len = 6; - else if (SIMPLE_ERR_BAD_OPCODE == err) + if (SIMPLE_ERR_BAD_OPCODE == err) modese_len = 10; else return -EINVAL; - } + } else if (0 == modese_len) + modese_len = 6; } if (10 == modese_len) { err = scsiModeSense10(device, PROTOCOL_SPECIFIC_PORT_PAGE, diff --git a/sm5/scsicmds.cpp b/sm5/scsicmds.cpp index 34e9325098fcd74d936af3d7bdd231bcdf072a86..d3af2bbb6afaaf5aaa1ae94f4dcbc4231b8572d1 100644 --- a/sm5/scsicmds.cpp +++ b/sm5/scsicmds.cpp @@ -46,7 +46,7 @@ #include "utility.h" #include "extern.h" -const char *scsicmds_c_cvsid="$Id: scsicmds.cpp,v 1.62 2003/11/17 11:48:47 dpgilbert Exp $" EXTERN_H_CVSID SCSICMDS_H_CVSID; +const char *scsicmds_c_cvsid="$Id: scsicmds.cpp,v 1.63 2003/11/18 13:44:46 dpgilbert Exp $" EXTERN_H_CVSID SCSICMDS_H_CVSID; /* for passing global control variables */ extern smartmonctrl *con; @@ -746,15 +746,14 @@ int scsiFetchIECmpage(int device, struct scsi_iec_mode_page *iecp, int modese_le if ((err = scsiModeSense(device, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE, MODE_PAGE_CONTROL_CURRENT, iecp->raw_curr, sizeof(iecp->raw_curr)))) { - if (0 == err) - iecp->modese_len = 6; - else if (SIMPLE_ERR_BAD_OPCODE == err) + if (SIMPLE_ERR_BAD_OPCODE == err) iecp->modese_len = 10; else { iecp->modese_len = 0; return err; } - } + } else if (0 == iecp->modese_len) + iecp->modese_len = 6; } if (10 == iecp->modese_len) { err = scsiModeSense10(device, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE, @@ -829,7 +828,7 @@ int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp) int scsiSetExceptionControlAndWarning(int device, int enabled, const struct scsi_iec_mode_page *iecp) { - int k, offset; + int k, offset, resp_len; int err = 0; UINT8 rout[SCSI_IECMP_RAW_LEN]; int sp, eCEnabled, wEnabled; @@ -841,9 +840,13 @@ int scsiSetExceptionControlAndWarning(int device, int enabled, if (offset < 0) return -EINVAL; memcpy(rout, iecp->raw_curr, SCSI_IECMP_RAW_LEN); - rout[0] = 0; /* Mode Data Length reserved in MODE SELECTs */ - if (10 == iecp->modese_len) - rout[1] = 0; + if (10 == iecp->modese_len) { + resp_len = (rout[0] << 8) + rout[1] + 2; + memset(rout, 0, 2); /* mode data length==0 for mode select */ + } else { + resp_len = rout[0] + 1; + memset(rout, 0, 1); /* mode data length==0 for mode select */ + } sp = (rout[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */ rout[offset] &= 0x7f; /* mask off PS bit */ if (enabled) { @@ -892,9 +895,9 @@ int scsiSetExceptionControlAndWarning(int device, int enabled, } } if (10 == iecp->modese_len) - err = scsiModeSelect10(device, sp, rout, sizeof(rout)); + err = scsiModeSelect10(device, sp, rout, resp_len); else if (6 == iecp->modese_len) - err = scsiModeSelect(device, sp, rout, sizeof(rout)); + err = scsiModeSelect(device, sp, rout, resp_len); return err; } @@ -1564,13 +1567,12 @@ int scsiFetchExtendedSelfTestTime(int device, int * durationSec, int modese_len) if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, MODE_PAGE_CONTROL_CURRENT, buff, sizeof(buff)))) { - if (0 == err) - modese_len = 6; - else if (SIMPLE_ERR_BAD_OPCODE == err) + if (SIMPLE_ERR_BAD_OPCODE == err) modese_len = 10; else return err; - } + } else if (0 == modese_len) + modese_len = 6; } if (10 == modese_len) { err = scsiModeSense10(device, CONTROL_MODE_PAGE, @@ -1732,7 +1734,6 @@ int scsiCountFailedSelfTests(int fd, int noisy) return (fail_hour << 8) + fails; } - /* Returns a negative value if failed to fetch Contol mode page or it was malformed. Returns 0 if GLTSD bit is zero and returns 1 if the GLTSD bit is set. */ @@ -1746,13 +1747,12 @@ int scsiFetchControlGLTSD(int device, int modese_len) if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, MODE_PAGE_CONTROL_CURRENT, buff, sizeof(buff)))) { - if (0 == err) - modese_len = 6; - else if (SIMPLE_ERR_BAD_OPCODE == err) + if (SIMPLE_ERR_BAD_OPCODE == err) modese_len = 10; else return -EINVAL; - } + } else if (0 == modese_len) + modese_len = 6; } if (10 == modese_len) { err = scsiModeSense10(device, CONTROL_MODE_PAGE, @@ -1767,6 +1767,69 @@ int scsiFetchControlGLTSD(int device, int modese_len) return -EINVAL; } +/* Attempts to clear GLTSD bit in Control mode page. Returns 0 if + successful, negative if low level error, > 0 if higher level error (e.g. + SIMPLE_ERR_BAD_PARAM if GLTSD bit is not changeable). */ +int scsiClearControlGLTSD(int device, int modese_len) +{ + int err, offset, resp_len, sp; + UINT8 buff[64]; + UINT8 ch_buff[64]; + + memset(buff, 0, sizeof(buff)); + if (modese_len <= 6) { + if ((err = scsiModeSense(device, CONTROL_MODE_PAGE, + MODE_PAGE_CONTROL_CURRENT, + buff, sizeof(buff)))) { + if (SIMPLE_ERR_BAD_OPCODE == err) + modese_len = 10; + else + return err; + } else if (0 == modese_len) + modese_len = 6; + } + if (10 == modese_len) { + err = scsiModeSense10(device, CONTROL_MODE_PAGE, + MODE_PAGE_CONTROL_CURRENT, + buff, sizeof(buff)); + if (err) + return err; + } + offset = scsiModePageOffset(buff, sizeof(buff), modese_len); + if ((offset < 0) || (buff[offset + 1] < 0xa)) + return SIMPLE_ERR_BAD_RESP; + if (0 == (buff[offset + 2] & 2)) + return 0; /* already clear so nothing to do */ + if (modese_len == 6) + err = scsiModeSense(device, CONTROL_MODE_PAGE, + MODE_PAGE_CONTROL_CHANGEABLE, + ch_buff, sizeof(ch_buff)); + else + err = scsiModeSense10(device, CONTROL_MODE_PAGE, + MODE_PAGE_CONTROL_CHANGEABLE, + ch_buff, sizeof(ch_buff)); + if (err) + return err; + if (0 == (ch_buff[offset + 2] & 2)) + return SIMPLE_ERR_BAD_PARAM; /* GLTSD bit not chageable */ + + if (10 == modese_len) { + resp_len = (buff[0] << 8) + buff[1] + 2; + memset(buff, 0, 2); + } else { + resp_len = buff[0] + 1; + memset(buff, 0, 1); + } + sp = (buff[offset] & 0x80) ? 1 : 0; /* PS bit becomes 'SELECT's SP bit */ + buff[offset] &= 0x7f; /* mask off PS bit */ + buff[offset + 2] &= 0xfd; /* clear GLTSD bit in buff */ + if (10 == modese_len) + err = scsiModeSelect10(device, sp, buff, resp_len); + else if (6 == modese_len) + err = scsiModeSelect(device, sp, buff, resp_len); + return err; +} + /* Returns a negative value if failed to fetch Protocol specific port mode page or it was malformed. Returns transport protocol identifier when value >= 0 . */ @@ -1780,13 +1843,12 @@ int scsiFetchTransportProtocol(int device, int modese_len) if ((err = scsiModeSense(device, PROTOCOL_SPECIFIC_PORT_PAGE, MODE_PAGE_CONTROL_CURRENT, buff, sizeof(buff)))) { - if (0 == err) - modese_len = 6; - else if (SIMPLE_ERR_BAD_OPCODE == err) + if (SIMPLE_ERR_BAD_OPCODE == err) modese_len = 10; else return -EINVAL; - } + } else if (0 == modese_len) + modese_len = 6; } if (10 == modese_len) { err = scsiModeSense10(device, PROTOCOL_SPECIFIC_PORT_PAGE,