Add POWER_CONDITION modepage marshalling/unmarshalling

This commit is contained in:
Ronnie Sahlberg
2013-07-20 15:35:38 -07:00
parent 0013ae25e6
commit 52a83e91af
9 changed files with 149 additions and 30 deletions

View File

@@ -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);

View File

@@ -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;
};
};

View File

@@ -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;

View File

@@ -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;

View File

@@ -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));

View File

@@ -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;

View File

@@ -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",

View File

@@ -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 "

View File

@@ -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 "