sg_cmds_basic2.c (sdparm-1.11.tgz) | : | sg_cmds_basic2.c (sdparm-1.12.tgz) | ||
---|---|---|---|---|
/* | /* | |||
* Copyright (c) 1999-2019 Douglas Gilbert. | * Copyright (c) 1999-2020 Douglas Gilbert. | |||
* All rights reserved. | * All rights reserved. | |||
* Use of this source code is governed by a BSD-style | * Use of this source code is governed by a BSD-style | |||
* license that can be found in the BSD_LICENSE file. | * license that can be found in the BSD_LICENSE file. | |||
* | * | |||
* SPDX-License-Identifier: BSD-2-Clause | * SPDX-License-Identifier: BSD-2-Clause | |||
*/ | */ | |||
/* | /* | |||
* CONTENTS | * CONTENTS | |||
* Some SCSI commands are executed in many contexts and hence began | * Some SCSI commands are executed in many contexts and hence began | |||
skipping to change at line 927 | skipping to change at line 927 | |||
ret = sense_cat; | ret = sense_cat; | |||
break; | break; | |||
} | } | |||
} else | } else | |||
ret = 0; | ret = 0; | |||
destruct_scsi_pt_obj(ptvp); | destruct_scsi_pt_obj(ptvp); | |||
return ret; | return ret; | |||
} | } | |||
int | ||||
sg_ll_start_stop_unit(int sg_fd, bool immed, int pc_mod__fl_num, | ||||
int power_cond, bool noflush__fl, bool loej, bool start, | ||||
bool noisy, int verbose) | ||||
{ | ||||
int ret; | ||||
struct sg_pt_base * ptvp; | ||||
ptvp = construct_scsi_pt_obj_with_fd(sg_fd, verbose); | ||||
if (NULL == ptvp) | ||||
return sg_convert_errno(ENOMEM); | ||||
ret = sg_ll_start_stop_unit_pt(ptvp, immed, pc_mod__fl_num, power_cond, | ||||
noflush__fl, loej, start, noisy, verbose); | ||||
destruct_scsi_pt_obj(ptvp); | ||||
return ret; | ||||
} | ||||
/* Invokes a SCSI START STOP UNIT command (SBC + MMC). | /* Invokes a SCSI START STOP UNIT command (SBC + MMC). | |||
* Return of 0 -> success, | * Return of 0 -> success, | |||
* various SG_LIB_CAT_* positive values or -1 -> other errors. | * various SG_LIB_CAT_* positive values or -1 -> other errors. | |||
* SBC-3 and MMC partially overlap on the power_condition_modifier(sbc) and | * SBC-3 and MMC partially overlap on the power_condition_modifier(sbc) and | |||
* format_layer_number(mmc) fields. They also overlap on the noflush(sbc) | * format_layer_number(mmc) fields. They also overlap on the noflush(sbc) | |||
* and fl(mmc) one bit field. This is the cause of the awkardly named | * and fl(mmc) one bit field. This is the cause of the awkardly named | |||
* pc_mod__fl_num and noflush__fl arguments to this function. | * pc_mod__fl_num and noflush__fl arguments to this function. | |||
* */ | * */ | |||
int | static int | |||
sg_ll_start_stop_unit_pt(struct sg_pt_base * ptvp, bool immed, | sg_ll_start_stop_unit_com(struct sg_pt_base * ptvp, int sg_fd, bool immed, | |||
int pc_mod__fl_num, int power_cond, bool noflush__fl, | int pc_mod__fl_num, int power_cond, bool noflush__fl, | |||
bool loej, bool start, bool noisy, int verbose) | bool loej, bool start, bool noisy, int verbose) | |||
{ | { | |||
static const char * const cdb_s = "start stop unit"; | static const char * const cdb_s = "start stop unit"; | |||
bool ptvp_given = false; | ||||
bool local_sense = true; | ||||
bool local_cdb = true; | ||||
int res, ret, sense_cat; | int res, ret, sense_cat; | |||
uint8_t ssuBlk[START_STOP_CMDLEN] = {START_STOP_CMD, 0, 0, 0, 0, 0}; | uint8_t ssuBlk[START_STOP_CMDLEN] = {START_STOP_CMD, 0, 0, 0, 0, 0}; | |||
uint8_t sense_b[SENSE_BUFF_LEN]; | uint8_t sense_b[SENSE_BUFF_LEN]; | |||
if (immed) | if (immed) | |||
ssuBlk[1] = 0x1; | ssuBlk[1] = 0x1; | |||
ssuBlk[3] = pc_mod__fl_num & 0xf; /* bits 2 and 3 are reserved in MMC */ | ssuBlk[3] = pc_mod__fl_num & 0xf; /* bits 2 and 3 are reserved in MMC */ | |||
ssuBlk[4] = ((power_cond & 0xf) << 4); | ssuBlk[4] = ((power_cond & 0xf) << 4); | |||
if (noflush__fl) | if (noflush__fl) | |||
ssuBlk[4] |= 0x4; | ssuBlk[4] |= 0x4; | |||
skipping to change at line 979 | skipping to change at line 965 | |||
ssuBlk[4] |= 0x2; | ssuBlk[4] |= 0x2; | |||
if (start) | if (start) | |||
ssuBlk[4] |= 0x1; | ssuBlk[4] |= 0x1; | |||
if (verbose) { | if (verbose) { | |||
char b[128]; | char b[128]; | |||
pr2ws(" %s cdb: %s\n", cdb_s, | pr2ws(" %s cdb: %s\n", cdb_s, | |||
sg_get_command_str(ssuBlk, sizeof(ssuBlk), false, | sg_get_command_str(ssuBlk, sizeof(ssuBlk), false, | |||
sizeof(b), b)); | sizeof(b), b)); | |||
} | } | |||
if (ptvp) { | ||||
clear_scsi_pt_obj(ptvp); | ptvp_given = true; | |||
set_scsi_pt_cdb(ptvp, ssuBlk, sizeof(ssuBlk)); | partial_clear_scsi_pt_obj(ptvp); | |||
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); | if (get_scsi_pt_cdb_buf(ptvp)) | |||
local_cdb = false; /* N.B. Ignores locally built cdb */ | ||||
else | ||||
set_scsi_pt_cdb(ptvp, ssuBlk, sizeof(ssuBlk)); | ||||
if (get_scsi_pt_sense_buf(ptvp)) | ||||
local_sense = false; | ||||
else | ||||
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); | ||||
} else { | ||||
ptvp = construct_scsi_pt_obj_with_fd(sg_fd, verbose); | ||||
if (NULL == ptvp) | ||||
return sg_convert_errno(ENOMEM); | ||||
set_scsi_pt_cdb(ptvp, ssuBlk, sizeof(ssuBlk)); | ||||
set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b)); | ||||
} | ||||
res = do_scsi_pt(ptvp, -1, START_PT_TIMEOUT, verbose); | res = do_scsi_pt(ptvp, -1, START_PT_TIMEOUT, verbose); | |||
ret = sg_cmds_process_resp(ptvp, cdb_s, res, noisy, verbose, &sense_cat); | ret = sg_cmds_process_resp(ptvp, cdb_s, res, noisy, verbose, &sense_cat); | |||
if (-1 == ret) | if (-1 == ret) | |||
ret = sg_convert_errno(get_scsi_pt_os_err(ptvp)); | ret = sg_convert_errno(get_scsi_pt_os_err(ptvp)); | |||
else if (-2 == ret) { | else if (-2 == ret) { | |||
switch (sense_cat) { | switch (sense_cat) { | |||
case SG_LIB_CAT_RECOVERED: | case SG_LIB_CAT_RECOVERED: | |||
case SG_LIB_CAT_NO_SENSE: | case SG_LIB_CAT_NO_SENSE: | |||
ret = 0; | ret = 0; | |||
break; | break; | |||
default: | default: | |||
ret = sense_cat; | ret = sense_cat; | |||
break; | break; | |||
} | } | |||
} else | } else | |||
ret = 0; | ret = 0; | |||
if (ptvp_given) { | ||||
if (local_sense) /* stop caller trying to access local sense */ | ||||
set_scsi_pt_sense(ptvp, NULL, 0); | ||||
if (local_cdb) | ||||
set_scsi_pt_cdb(ptvp, NULL, 0); | ||||
} else { | ||||
if (ptvp) | ||||
destruct_scsi_pt_obj(ptvp); | ||||
} | ||||
return ret; | return ret; | |||
} | } | |||
int | ||||
sg_ll_start_stop_unit(int sg_fd, bool immed, int pc_mod__fl_num, | ||||
int power_cond, bool noflush__fl, bool loej, bool start, | ||||
bool noisy, int verbose) | ||||
{ | ||||
return sg_ll_start_stop_unit_com(NULL, sg_fd, immed, pc_mod__fl_num, | ||||
power_cond, noflush__fl, loej, start, | ||||
noisy, verbose); | ||||
} | ||||
int | ||||
sg_ll_start_stop_unit_pt(struct sg_pt_base * ptvp, bool immed, | ||||
int pc_mod__fl_num, int power_cond, bool noflush__fl, | ||||
bool loej, bool start, bool noisy, int verbose) | ||||
{ | ||||
return sg_ll_start_stop_unit_com(ptvp, -1, immed, pc_mod__fl_num, | ||||
power_cond, noflush__fl, loej, start, | ||||
noisy, verbose); | ||||
} | ||||
/* Invokes a SCSI PREVENT ALLOW MEDIUM REMOVAL command | /* Invokes a SCSI PREVENT ALLOW MEDIUM REMOVAL command | |||
* [was in SPC-3 but displaced from SPC-4 into SBC-3, MMC-5, SSC-3] | * [was in SPC-3 but displaced from SPC-4 into SBC-3, MMC-5, SSC-3] | |||
* prevent==0 allows removal, prevent==1 prevents removal ... | * prevent==0 allows removal, prevent==1 prevents removal ... | |||
* Return of 0 -> success, | * Return of 0 -> success, | |||
* various SG_LIB_CAT_* positive values or -1 -> other errors */ | * various SG_LIB_CAT_* positive values or -1 -> other errors */ | |||
int | int | |||
sg_ll_prevent_allow(int sg_fd, int prevent, bool noisy, int verbose) | sg_ll_prevent_allow(int sg_fd, int prevent, bool noisy, int verbose) | |||
{ | { | |||
static const char * const cdb_s = "prevent allow medium removal"; | static const char * const cdb_s = "prevent allow medium removal"; | |||
int res, ret, sense_cat; | int res, ret, sense_cat; | |||
End of changes. 7 change blocks. | ||||
26 lines changed or deleted | 55 lines changed or added |