Add POWER_CONDITION modepage marshalling/unmarshalling
This commit is contained in:
@@ -342,7 +342,7 @@ void modesense6_cb(struct iscsi_context *iscsi, int status, void *command_data,
|
||||
full_size = scsi_datain_getfullsize(task);
|
||||
if (full_size > task->datain.size) {
|
||||
printf("did not get enough data for mode sense, sening modesense again asking for bigger buffer\n");
|
||||
if (iscsi_modesense6_task(iscsi, clnt->lun, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES, 0, full_size, modesense6_cb, private_data) == NULL) {
|
||||
if (iscsi_modesense6_task(iscsi, clnt->lun, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, full_size, modesense6_cb, private_data) == NULL) {
|
||||
printf("failed to send modesense6 command\n");
|
||||
scsi_free_scsi_task(task);
|
||||
exit(10);
|
||||
@@ -391,7 +391,7 @@ void inquiry_cb(struct iscsi_context *iscsi, int status, void *command_data, voi
|
||||
|
||||
printf("Device Type is %d. VendorId:%s ProductId:%s\n", inq->device_type, inq->vendor_identification, inq->product_identification);
|
||||
printf("Send MODESENSE6\n");
|
||||
if (iscsi_modesense6_task(iscsi, clnt->lun, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES, 0, 4, modesense6_cb, private_data) == NULL) {
|
||||
if (iscsi_modesense6_task(iscsi, clnt->lun, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 4, modesense6_cb, private_data) == NULL) {
|
||||
printf("failed to send modesense6 command\n");
|
||||
scsi_free_scsi_task(task);
|
||||
exit(10);
|
||||
|
||||
@@ -664,6 +664,26 @@ struct scsi_mode_page_caching {
|
||||
int cache_segment_size;
|
||||
};
|
||||
|
||||
struct scsi_mode_page_power_condition {
|
||||
int pm_bg_precedence;
|
||||
int standby_y;
|
||||
|
||||
int idle_c;
|
||||
int idle_b;
|
||||
int idle_a;
|
||||
int standby_z;
|
||||
|
||||
uint32_t idle_a_condition_timer;
|
||||
uint32_t standby_z_condition_timer;
|
||||
uint32_t idle_b_condition_timer;
|
||||
uint32_t idle_c_condition_timer;
|
||||
uint32_t standby_y_condition_timer;
|
||||
|
||||
int ccf_idle;
|
||||
int ccf_standby;
|
||||
int ccf_stopped;
|
||||
};
|
||||
|
||||
struct scsi_mode_page_control {
|
||||
int tst;
|
||||
int tmf_only;
|
||||
@@ -719,16 +739,30 @@ struct scsi_mode_page_informational_exceptions_control {
|
||||
};
|
||||
|
||||
enum scsi_modesense_page_code {
|
||||
SCSI_MODESENSE_PAGECODE_READ_WRITE_ERROR_RECOVERY = 0x01,
|
||||
SCSI_MODESENSE_PAGECODE_DISCONNECT_RECONNECT = 0x02,
|
||||
SCSI_MODESENSE_PAGECODE_VERIFY_ERROR_RECOVERY = 0x07,
|
||||
SCSI_MODESENSE_PAGECODE_CACHING = 0x08,
|
||||
SCSI_MODESENSE_PAGECODE_XOR_CONTROL = 0x10,
|
||||
SCSI_MODESENSE_PAGECODE_CONTROL = 0x0a,
|
||||
SCSI_MODESENSE_PAGECODE_INFORMATIONAL_EXCEPTIONS_CONTROL = 0x1c,
|
||||
SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES = 0x3f
|
||||
SCSI_MODEPAGE_READ_WRITE_ERROR_RECOVERY = 0x01,
|
||||
SCSI_MODEPAGE_DISCONNECT_RECONNECT = 0x02,
|
||||
SCSI_MODEPAGE_VERIFY_ERROR_RECOVERY = 0x07,
|
||||
SCSI_MODEPAGE_CACHING = 0x08,
|
||||
SCSI_MODEPAGE_XOR_CONTROL = 0x10,
|
||||
SCSI_MODEPAGE_CONTROL = 0x0a,
|
||||
SCSI_MODEPAGE_POWER_CONDITION = 0x1a,
|
||||
SCSI_MODEPAGE_INFORMATIONAL_EXCEPTIONS_CONTROL = 0x1c,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES = 0x3f
|
||||
};
|
||||
|
||||
|
||||
/* Do not use in new code.
|
||||
* Backward compatibility macros
|
||||
*/
|
||||
#define SCSI_MODESENSE_PAGECODE_READ_WRITE_ERROR_RECOVERY SCSI_MODEPAGE_READ_WRITE_ERROR_RECOVERY
|
||||
#define SCSI_MODESENSE_PAGECODE_DISCONNECT_RECONNECT SCSI_MODEPAGE_DISCONNECT_RECONNECT
|
||||
#define SCSI_MODESENSE_PAGECODE_VERIFY_ERROR_RECOVERY SCSI_MODEPAGE_VERIFY_ERROR_RECOVERY
|
||||
#define SCSI_MODESENSE_PAGECODE_CACHING SCSI_MODEPAGE_CACHING
|
||||
#define SCSI_MODESENSE_PAGECODE_XOR_CONTROL SCSI_MODEPAGE_XOR_CONTROL
|
||||
#define SCSI_MODESENSE_PAGECODE_CONTROL SCSI_MODEPAGE_CONTROL
|
||||
#define SCSI_MODESENSE_PAGECODE_INFORMATIONAL_EXCEPTIONS_CONTROL SCSI_MODEPAGE_INFORMATIONAL_EXCEPTIONS_CONTROL
|
||||
#define SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES SCSI_MODEPAGE_RETURN_ALL_PAGES
|
||||
|
||||
struct scsi_mode_page {
|
||||
struct scsi_mode_page *next;
|
||||
int ps;
|
||||
@@ -741,6 +775,7 @@ struct scsi_mode_page {
|
||||
struct scsi_mode_page_control control;
|
||||
struct scsi_mode_page_disconnect_reconnect disconnect_reconnect;
|
||||
struct scsi_mode_page_informational_exceptions_control iec;
|
||||
struct scsi_mode_page_power_condition power_condition;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -2392,6 +2392,42 @@ scsi_parse_mode_control(struct scsi_task *task, int pos, struct scsi_mode_page *
|
||||
task_get_uint16(task, pos + 8);
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_parse_mode_power_condition(struct scsi_task *task, int pos, struct scsi_mode_page *mp)
|
||||
{
|
||||
mp->power_condition.pm_bg_precedence =
|
||||
(task_get_uint8(task, pos) >> 6) & 0x03;
|
||||
mp->power_condition.standby_y =
|
||||
!!(task_get_uint8(task, pos) & 0x01);
|
||||
|
||||
mp->power_condition.idle_c =
|
||||
!!(task_get_uint8(task, pos + 1) & 0x08);
|
||||
mp->power_condition.idle_b =
|
||||
!!(task_get_uint8(task, pos + 1) & 0x04);
|
||||
mp->power_condition.idle_a =
|
||||
!!(task_get_uint8(task, pos + 1) & 0x02);
|
||||
mp->power_condition.standby_z =
|
||||
!!(task_get_uint8(task, pos + 1) & 0x01);
|
||||
|
||||
mp->power_condition.idle_a_condition_timer =
|
||||
task_get_uint32(task, pos + 2);
|
||||
mp->power_condition.standby_z_condition_timer =
|
||||
task_get_uint32(task, pos + 6);
|
||||
mp->power_condition.idle_b_condition_timer =
|
||||
task_get_uint32(task, pos + 10);
|
||||
mp->power_condition.idle_c_condition_timer =
|
||||
task_get_uint32(task, pos + 14);
|
||||
mp->power_condition.standby_y_condition_timer =
|
||||
task_get_uint32(task, pos + 18);
|
||||
|
||||
mp->power_condition.ccf_idle =
|
||||
(task_get_uint8(task, pos + 37) >> 6) & 0x03;
|
||||
mp->power_condition.ccf_standby =
|
||||
(task_get_uint8(task, pos + 37) >> 4) & 0x03;
|
||||
mp->power_condition.ccf_stopped =
|
||||
(task_get_uint8(task, pos + 37) >> 2) & 0x03;
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_parse_mode_disconnect_reconnect(struct scsi_task *task, int pos, struct scsi_mode_page *mp)
|
||||
{
|
||||
@@ -2503,18 +2539,21 @@ scsi_modesense_datain_unmarshall(struct scsi_task *task, int is_modesense6)
|
||||
}
|
||||
|
||||
switch (mp->page_code) {
|
||||
case SCSI_MODESENSE_PAGECODE_CACHING:
|
||||
case SCSI_MODEPAGE_CACHING:
|
||||
scsi_parse_mode_caching(task, pos, mp);
|
||||
break;
|
||||
case SCSI_MODESENSE_PAGECODE_CONTROL:
|
||||
case SCSI_MODEPAGE_CONTROL:
|
||||
scsi_parse_mode_control(task, pos, mp);
|
||||
break;
|
||||
case SCSI_MODESENSE_PAGECODE_DISCONNECT_RECONNECT:
|
||||
case SCSI_MODEPAGE_DISCONNECT_RECONNECT:
|
||||
scsi_parse_mode_disconnect_reconnect(task, pos, mp);
|
||||
break;
|
||||
case SCSI_MODESENSE_PAGECODE_INFORMATIONAL_EXCEPTIONS_CONTROL:
|
||||
case SCSI_MODEPAGE_INFORMATIONAL_EXCEPTIONS_CONTROL:
|
||||
scsi_parse_mode_informational_exceptions_control(task, pos, mp);
|
||||
break;
|
||||
case SCSI_MODEPAGE_POWER_CONDITION:
|
||||
scsi_parse_mode_power_condition(task, pos, mp);
|
||||
break;
|
||||
default:
|
||||
/* TODO: process other pages, or add raw data to struct
|
||||
* scsi_mode_page. */
|
||||
@@ -2611,6 +2650,48 @@ scsi_modesense_marshall_control(struct scsi_task *task,
|
||||
return data;
|
||||
}
|
||||
|
||||
static struct scsi_data *
|
||||
scsi_modesense_marshall_power_condition(struct scsi_task *task,
|
||||
struct scsi_mode_page *mp,
|
||||
int hdr_size)
|
||||
{
|
||||
struct scsi_data *data;
|
||||
|
||||
data = scsi_malloc(task, sizeof(struct scsi_data));
|
||||
|
||||
data->size = 40 + hdr_size;
|
||||
data->data = scsi_malloc(task, data->size);
|
||||
|
||||
data->data[hdr_size + 2] |=
|
||||
(mp->power_condition.pm_bg_precedence << 6) & 0xc0;
|
||||
if (mp->power_condition.standby_y) data->data[hdr_size + 2] |= 0x01;
|
||||
|
||||
if (mp->power_condition.idle_c) data->data[hdr_size + 3] |= 0x08;
|
||||
if (mp->power_condition.idle_b) data->data[hdr_size + 3] |= 0x04;
|
||||
if (mp->power_condition.idle_a) data->data[hdr_size + 3] |= 0x02;
|
||||
if (mp->power_condition.standby_z) data->data[hdr_size + 3] |= 0x01;
|
||||
|
||||
scsi_set_uint32(&data->data[hdr_size + 4],
|
||||
mp->power_condition.idle_a_condition_timer);
|
||||
scsi_set_uint32(&data->data[hdr_size + 8],
|
||||
mp->power_condition.standby_z_condition_timer);
|
||||
scsi_set_uint32(&data->data[hdr_size + 12],
|
||||
mp->power_condition.idle_b_condition_timer);
|
||||
scsi_set_uint32(&data->data[hdr_size + 16],
|
||||
mp->power_condition.idle_c_condition_timer);
|
||||
scsi_set_uint32(&data->data[hdr_size + 20],
|
||||
mp->power_condition.standby_y_condition_timer);
|
||||
|
||||
data->data[hdr_size + 39] |=
|
||||
(mp->power_condition.ccf_idle << 6) & 0xc0;
|
||||
data->data[hdr_size + 39] |=
|
||||
(mp->power_condition.ccf_standby << 4) & 0x30;
|
||||
data->data[hdr_size + 39] |=
|
||||
(mp->power_condition.ccf_stopped << 2) & 0x0c;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static struct scsi_data *
|
||||
scsi_modesense_marshall_disconnect_reconnect(struct scsi_task *task,
|
||||
struct scsi_mode_page *mp,
|
||||
@@ -2680,18 +2761,21 @@ scsi_modesense_dataout_marshall(struct scsi_task *task,
|
||||
int hdr_size = is_modeselect6 ? 4 : 8;
|
||||
|
||||
switch (mp->page_code) {
|
||||
case SCSI_MODESENSE_PAGECODE_CACHING:
|
||||
case SCSI_MODEPAGE_CACHING:
|
||||
data = scsi_modesense_marshall_caching(task, mp, hdr_size);
|
||||
break;
|
||||
case SCSI_MODESENSE_PAGECODE_CONTROL:
|
||||
case SCSI_MODEPAGE_CONTROL:
|
||||
data = scsi_modesense_marshall_control(task, mp, hdr_size);
|
||||
break;
|
||||
case SCSI_MODESENSE_PAGECODE_DISCONNECT_RECONNECT:
|
||||
case SCSI_MODEPAGE_DISCONNECT_RECONNECT:
|
||||
data = scsi_modesense_marshall_disconnect_reconnect(task, mp, hdr_size);
|
||||
break;
|
||||
case SCSI_MODESENSE_PAGECODE_INFORMATIONAL_EXCEPTIONS_CONTROL:
|
||||
case SCSI_MODEPAGE_INFORMATIONAL_EXCEPTIONS_CONTROL:
|
||||
data = scsi_modesense_marshall_informational_exceptions_control(task, mp, hdr_size);
|
||||
break;
|
||||
case SCSI_MODEPAGE_POWER_CONDITION:
|
||||
data = scsi_modesense_marshall_power_condition(task, mp, hdr_size);
|
||||
break;
|
||||
default:
|
||||
/* TODO error reporting ? */
|
||||
return NULL;
|
||||
|
||||
@@ -179,7 +179,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
sense_task = iscsi_modesense10_sync(iscsi, iscsi_url->lun,
|
||||
0, 1, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODESENSE_PAGECODE_CONTROL,
|
||||
SCSI_MODEPAGE_CONTROL,
|
||||
0, 255);
|
||||
if (sense_task == NULL) {
|
||||
printf("Failed to send MODE_SENSE10 command: %s\n",
|
||||
@@ -199,7 +199,7 @@ int main(int argc, char *argv[])
|
||||
ret = 10;
|
||||
goto finished;
|
||||
}
|
||||
mp = scsi_modesense_get_page(ms, SCSI_MODESENSE_PAGECODE_CONTROL, 0);
|
||||
mp = scsi_modesense_get_page(ms, SCSI_MODEPAGE_CONTROL, 0);
|
||||
if (mp == NULL) {
|
||||
printf("failed to read control mode page\n");
|
||||
ret = 10;
|
||||
|
||||
@@ -72,7 +72,7 @@ int T0300_readonly(const char *initiator, const char *url)
|
||||
|
||||
/* verify the device is readonly */
|
||||
task = iscsi_modesense6_sync(iscsi, lun, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES, 0,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0,
|
||||
4);
|
||||
if (task == NULL) {
|
||||
printf("Failed to send modesense6 command: %s\n", iscsi_get_error(iscsi));
|
||||
@@ -82,7 +82,7 @@ int T0300_readonly(const char *initiator, const char *url)
|
||||
if (full_size > task->datain.size) {
|
||||
scsi_free_scsi_task(task);
|
||||
task = iscsi_modesense6_sync(iscsi, lun, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES, 0,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES, 0,
|
||||
full_size);
|
||||
if (task == NULL) {
|
||||
printf("Failed to send modesense6 command: %s\n", iscsi_get_error(iscsi));
|
||||
|
||||
@@ -6028,7 +6028,7 @@ int set_swp(struct iscsi_context *iscsi, int lun)
|
||||
logging(LOG_VERBOSE, "Read CONTROL page");
|
||||
sense_task = iscsi_modesense6_sync(iscsi, lun,
|
||||
1, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODESENSE_PAGECODE_CONTROL,
|
||||
SCSI_MODEPAGE_CONTROL,
|
||||
0, 255);
|
||||
if (sense_task == NULL) {
|
||||
logging(LOG_NORMAL, "Failed to send MODE_SENSE6 command: %s",
|
||||
@@ -6049,7 +6049,7 @@ int set_swp(struct iscsi_context *iscsi, int lun)
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
mp = scsi_modesense_get_page(ms, SCSI_MODESENSE_PAGECODE_CONTROL, 0);
|
||||
mp = scsi_modesense_get_page(ms, SCSI_MODEPAGE_CONTROL, 0);
|
||||
if (mp == NULL) {
|
||||
logging(LOG_NORMAL, "failed to read control mode page");
|
||||
ret = -1;
|
||||
@@ -6095,7 +6095,7 @@ int clear_swp(struct iscsi_context *iscsi, int lun)
|
||||
logging(LOG_VERBOSE, "Read CONTROL page");
|
||||
sense_task = iscsi_modesense6_sync(iscsi, lun,
|
||||
1, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODESENSE_PAGECODE_CONTROL,
|
||||
SCSI_MODEPAGE_CONTROL,
|
||||
0, 255);
|
||||
if (sense_task == NULL) {
|
||||
logging(LOG_NORMAL, "Failed to send MODE_SENSE6 command: %s",
|
||||
@@ -6116,7 +6116,7 @@ int clear_swp(struct iscsi_context *iscsi, int lun)
|
||||
ret = -1;
|
||||
goto finished;
|
||||
}
|
||||
mp = scsi_modesense_get_page(ms, SCSI_MODESENSE_PAGECODE_CONTROL, 0);
|
||||
mp = scsi_modesense_get_page(ms, SCSI_MODEPAGE_CONTROL, 0);
|
||||
if (mp == NULL) {
|
||||
logging(LOG_NORMAL, "failed to read control mode page");
|
||||
ret = -1;
|
||||
|
||||
@@ -1185,7 +1185,7 @@ main(int argc, char *argv[])
|
||||
|
||||
/* check if the device is write protected or not */
|
||||
task = iscsi_modesense6_sync(iscsic, lun, 0, SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES,
|
||||
0, 255);
|
||||
if (task == NULL) {
|
||||
printf("Failed to send MODE_SENSE6 command: %s\n",
|
||||
|
||||
@@ -41,7 +41,7 @@ test_modesense6_all_pages(void)
|
||||
logging(LOG_VERBOSE, "Send MODESENSE6 command to fetch AllPages");
|
||||
task = iscsi_modesense6_sync(iscsic, tgt_lun, 0,
|
||||
SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES,
|
||||
0, 255);
|
||||
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Failed to send MODE_SENSE6 "
|
||||
|
||||
@@ -42,7 +42,7 @@ test_modesense6_residuals(void)
|
||||
}
|
||||
task = iscsi_modesense6_sync(iscsic, tgt_lun, 0,
|
||||
SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES,
|
||||
0, 4);
|
||||
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Failed to send MODE_SENSE6 "
|
||||
@@ -82,7 +82,7 @@ test_modesense6_residuals(void)
|
||||
}
|
||||
task = iscsi_modesense6_sync(iscsic, tgt_lun, 0,
|
||||
SCSI_MODESENSE_PC_CURRENT,
|
||||
SCSI_MODESENSE_PAGECODE_RETURN_ALL_PAGES,
|
||||
SCSI_MODEPAGE_RETURN_ALL_PAGES,
|
||||
0, 255);
|
||||
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
|
||||
logging(LOG_VERBOSE, "[FAILED] Failed to send MODE_SENSE6 "
|
||||
|
||||
Reference in New Issue
Block a user