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

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