Add unmarshalling of PERSISTENT_RESERVE_IN/READ_KEYS DATA-IN blob

This commit is contained in:
Ronnie Sahlberg
2012-12-17 19:26:43 -08:00
parent c60093eafe
commit 2b46e4adfa
2 changed files with 72 additions and 0 deletions

View File

@@ -681,6 +681,14 @@ struct scsi_report_supported_op_codes {
struct scsi_command_descriptor descriptors[0];
};
struct scsi_persistent_reserve_in_read_keys {
uint32_t prgeneration;
uint32_t additional_length;
uint32_t num_keys;
uint64_t keys[0];
};
struct scsi_read10_cdb {
enum scsi_opcode opcode;
uint8_t rdprotect;

View File

@@ -161,6 +161,19 @@ scsi_sense_ascq_str(int ascq)
return value_string_find(ascqs, ascq);
}
inline uint64_t
scsi_get_uint64(const unsigned char *c)
{
uint64_t val;
val = ntohl(*(uint32_t *)c);
val <<= 32;
c += 4;
val |= ntohl(*(uint32_t *)c);
return val;
}
inline uint32_t
scsi_get_uint32(const unsigned char *c)
{
@@ -590,6 +603,53 @@ scsi_serviceactionin_datain_unmarshall(struct scsi_task *task)
}
}
/*
* persistent_reserve_in unmarshall
*/
static inline uint8_t
scsi_persistentreservein_sa(const struct scsi_task *task)
{
return task->cdb[1] & 0x1f;
}
static int
scsi_persistentreservein_datain_getfullsize(struct scsi_task *task)
{
switch (scsi_persistentreservein_sa(task)) {
case SCSI_PERSISTENT_RESERVE_READ_KEYS:
return scsi_get_uint32(&task->datain.data[4]) + 8;
default:
return -1;
}
}
static void *
scsi_persistentreservein_datain_unmarshall(struct scsi_task *task)
{
struct scsi_persistent_reserve_in_read_keys *rk;
int i;
switch (scsi_persistentreservein_sa(task)) {
case SCSI_PERSISTENT_RESERVE_READ_KEYS:
i = scsi_get_uint32(&task->datain.data[4]);
rk = scsi_malloc(task, offsetof(struct scsi_persistent_reserve_in_read_keys, keys) + i);
if (rk == NULL) {
return NULL;
}
rk->prgeneration = scsi_get_uint32(&task->datain.data[0]);
rk->additional_length = scsi_get_uint32(&task->datain.data[4]);
rk->num_keys = rk->additional_length / 8;
for (i = 0; i < (int)rk->num_keys; i++) {
rk->keys[i] = scsi_get_uint64(&task->datain.data[8 + i * 8]);
}
return rk;
default:
return NULL;
}
}
static inline int
scsi_maintenancein_return_timeouts(const struct scsi_task *task)
{
@@ -2320,6 +2380,8 @@ scsi_datain_getfullsize(struct scsi_task *task)
return scsi_readtoc_datain_getfullsize(task);
case SCSI_OPCODE_REPORTLUNS:
return scsi_reportluns_datain_getfullsize(task);
case SCSI_OPCODE_PERSISTENT_RESERVE_IN:
return scsi_persistentreservein_datain_getfullsize(task);
case SCSI_OPCODE_MAINTENANCE_IN:
return scsi_maintenancein_datain_getfullsize(task);
}
@@ -2346,6 +2408,8 @@ scsi_datain_unmarshall(struct scsi_task *task)
return scsi_reportluns_datain_unmarshall(task);
case SCSI_OPCODE_SERVICE_ACTION_IN:
return scsi_serviceactionin_datain_unmarshall(task);
case SCSI_OPCODE_PERSISTENT_RESERVE_IN:
return scsi_persistentreservein_datain_unmarshall(task);
case SCSI_OPCODE_MAINTENANCE_IN:
return scsi_maintenancein_datain_unmarshall(task);
}