#include <smartpqi.h>
static void reinit_io(pqi_io_request_t *io);
static void dump_raid(pqi_state_t *s, void *v, pqi_index_t idx);
static void dump_aio(void *v);
static void show_error_detail(pqi_state_t *s);
static void cmd_start_time(pqi_cmd_t *c);
static void cmd_finish_task(void *v);
#ifdef DEBUG
int pqi_shuffle_delay = 0;
#endif
static void
cmd_remove_group(pqi_cmd_t *c)
{
pqi_io_request_t *io = c->pc_io_rqst;
pqi_device_t *d = c->pc_device;
if (io != NULL) {
pqi_queue_group_t *qg = io->io_queue_group;
int path = io->io_queue_path;
mutex_exit(&c->pc_mutex);
mutex_exit(&d->pd_mutex);
mutex_enter(&qg->submit_lock[path]);
if (list_link_active(&io->io_list_node)) {
list_remove(&qg->request_list[path], io);
}
mutex_exit(&qg->submit_lock[path]);
#ifdef DEBUG
if (pqi_shuffle_delay != 0) {
pqi_state_t *s = c->pc_softc;
pqi_lun_reset(s, d);
delay(pqi_shuffle_delay * drv_usectohz(1000000));
}
#endif
mutex_enter(&d->pd_mutex);
mutex_enter(&c->pc_mutex);
}
}
pqi_cmd_action_t
pqi_cmd_action_nolock(pqi_cmd_t *c, pqi_cmd_action_t a)
{
pqi_device_t *d = c->pc_device;
pqi_state_t *s = c->pc_softc;
struct scsi_pkt *pkt;
mutex_enter(&c->pc_mutex);
if ((c->pc_flags & PQI_FLAG_TIMED_OUT) != 0) {
a = PQI_CMD_FAIL;
goto skipto;
}
c->pc_last_action = c->pc_cur_action;
c->pc_cur_action = a;
switch (a) {
case PQI_CMD_QUEUE:
list_insert_tail(&d->pd_cmd_list, c);
cmd_start_time(c);
break;
case PQI_CMD_START:
if (c->pc_last_action == PQI_CMD_FAIL) {
list_remove(&d->pd_cmd_list, c);
pkt = CMD2PKT(c);
if (pkt == NULL) {
pqi_io_request_t *io = c->pc_io_rqst;
io->io_status = PQI_DATA_IN_OUT_TIMEOUT;
(*io->io_cb)(io, io->io_context);
pqi_free_io(io);
c->pc_io_rqst = NULL;
} else {
pqi_free_io(c->pc_io_rqst);
c->pc_io_rqst = NULL;
(void) ddi_taskq_dispatch(s->s_complete_taskq,
cmd_finish_task, c, 0);
}
a = PQI_CMD_FAIL;
} else {
cmd_start_time(c);
}
break;
case PQI_CMD_FAIL:
if (c->pc_last_action == PQI_CMD_START) {
a = PQI_CMD_START;
} else {
ASSERT(c->pc_last_action == PQI_CMD_TIMEOUT ||
c->pc_last_action == PQI_CMD_QUEUE);
}
break;
case PQI_CMD_TIMEOUT:
list_remove(&d->pd_cmd_list, c);
c->pc_flags |= PQI_FLAG_TIMED_OUT;
cmd_remove_group(c);
ASSERT3U(c->pc_cur_action, ==, PQI_CMD_TIMEOUT);
c->pc_flags &= ~PQI_FLAG_TIMED_OUT;
pkt = CMD2PKT(c);
if (pkt == NULL) {
pqi_io_request_t *io = c->pc_io_rqst;
io->io_status = PQI_DATA_IN_OUT_TIMEOUT;
(*io->io_cb)(io, io->io_context);
pqi_free_io(c->pc_io_rqst);
c->pc_io_rqst = NULL;
} else {
pqi_free_io(c->pc_io_rqst);
c->pc_io_rqst = NULL;
mutex_exit(&c->pc_mutex);
(void) ddi_taskq_dispatch(s->s_complete_taskq,
cmd_finish_task, c, 0);
return (a);
}
break;
case PQI_CMD_CMPLT:
if (c->pc_last_action == PQI_CMD_TIMEOUT)
break;
list_remove(&d->pd_cmd_list, c);
pqi_free_io(c->pc_io_rqst);
c->pc_io_rqst = NULL;
if (CMD2PKT(c) != NULL) {
mutex_exit(&c->pc_mutex);
(void) ddi_taskq_dispatch(s->s_complete_taskq,
cmd_finish_task, c, 0);
return (a);
}
break;
default:
cmn_err(CE_PANIC,
"%s: Unknown action request: %d", __func__, a);
}
skipto:
mutex_exit(&c->pc_mutex);
return (a);
}
pqi_cmd_action_t
pqi_cmd_action(pqi_cmd_t *c, pqi_cmd_action_t a)
{
pqi_device_t *d = c->pc_device;
pqi_cmd_action_t rval;
mutex_enter(&d->pd_mutex);
rval = pqi_cmd_action_nolock(c, a);
mutex_exit(&d->pd_mutex);
return (rval);
}
boolean_t
pqi_is_offline(pqi_state_t *s)
{
return (s->s_offline);
}
pqi_io_request_t *
pqi_alloc_io(pqi_state_t *s)
{
pqi_io_request_t *io = NULL;
uint16_t loop;
uint16_t i;
mutex_enter(&s->s_io_mutex);
i = s->s_next_io_slot;
s->s_io_need++;
for (;;) {
for (loop = 0; loop < s->s_max_io_slots; loop++) {
if (pqi_is_offline(s)) {
mutex_exit(&s->s_io_mutex);
return (NULL);
}
io = &s->s_io_rqst_pool[i];
i = (i + 1) % s->s_max_io_slots;
if (io->io_refcount == 0) {
io->io_refcount = 1;
break;
}
}
if (loop != s->s_max_io_slots)
break;
s->s_io_had2wait++;
s->s_io_wait_cnt++;
if (cv_wait_sig(&s->s_io_condvar, &s->s_io_mutex) == 0) {
s->s_io_sig++;
io = NULL;
break;
}
i = s->s_next_io_slot;
}
s->s_next_io_slot = i;
mutex_exit(&s->s_io_mutex);
if (io != NULL)
reinit_io(io);
return (io);
}
void
pqi_free_io(pqi_io_request_t *io)
{
pqi_state_t *s = io->io_softc;
mutex_enter(&s->s_io_mutex);
ASSERT(io->io_refcount == 1);
io->io_refcount = 0;
reinit_io(io);
if (s->s_io_wait_cnt != 0) {
s->s_io_wait_cnt--;
cv_signal(&s->s_io_condvar);
}
mutex_exit(&s->s_io_mutex);
}
boolean_t
pqi_timeout_io(pqi_io_request_t *io)
{
mutex_enter(&io->io_lock);
if (io->io_serviced) {
mutex_exit(&io->io_lock);
return (B_FALSE);
}
io->io_gen = (io->io_gen + 1) % PQI_NGENS;
mutex_exit(&io->io_lock);
return (B_TRUE);
}
boolean_t
pqi_service_io(pqi_io_request_t *io, uint8_t generation)
{
mutex_enter(&io->io_lock);
if (io->io_gen != generation) {
mutex_exit(&io->io_lock);
return (B_FALSE);
}
io->io_serviced = B_TRUE;
mutex_exit(&io->io_lock);
return (B_TRUE);
}
void
pqi_dump_io(pqi_io_request_t *io)
{
pqi_iu_header_t *hdr = io->io_iu;
pqi_state_t *s;
if (io->io_cmd != NULL) {
s = io->io_cmd->pc_softc;
} else {
s = ddi_get_soft_state(pqi_state, 0);
}
if (hdr->iu_type == PQI_REQUEST_IU_AIO_PATH_IO) {
dump_aio(io->io_iu);
} else if (hdr->iu_type == PQI_REQUEST_IU_RAID_PATH_IO) {
dump_raid(s, io->io_iu, io->io_pi);
}
}
static uint_t supported_event_types[] = {
PQI_EVENT_TYPE_HOTPLUG,
PQI_EVENT_TYPE_HARDWARE,
PQI_EVENT_TYPE_PHYSICAL_DEVICE,
PQI_EVENT_TYPE_LOGICAL_DEVICE,
PQI_EVENT_TYPE_AIO_STATE_CHANGE,
PQI_EVENT_TYPE_AIO_CONFIG_CHANGE,
PQI_EVENT_TYPE_HEARTBEAT
};
int
pqi_map_event(uint8_t event)
{
int i;
for (i = 0; i < sizeof (supported_event_types) / sizeof (uint_t); i++)
if (supported_event_types[i] == event)
return (i);
return (-1);
}
boolean_t
pqi_supported_event(uint8_t event)
{
return (pqi_map_event(event) == -1 ? B_FALSE : B_TRUE);
}
char *
pqi_event_to_str(uint8_t event)
{
switch (event) {
case PQI_EVENT_TYPE_HOTPLUG: return ("Hotplug");
case PQI_EVENT_TYPE_HARDWARE: return ("Hardware");
case PQI_EVENT_TYPE_PHYSICAL_DEVICE:
return ("Physical Device");
case PQI_EVENT_TYPE_LOGICAL_DEVICE: return ("logical Device");
case PQI_EVENT_TYPE_AIO_STATE_CHANGE:
return ("AIO State Change");
case PQI_EVENT_TYPE_AIO_CONFIG_CHANGE:
return ("AIO Config Change");
case PQI_EVENT_TYPE_HEARTBEAT: return ("Heartbeat");
default: return ("Unsupported Event Type");
}
}
char *
bool_to_str(int v)
{
return (v ? "T" : "f");
}
char *
dtype_to_str(int t)
{
switch (t) {
case DTYPE_DIRECT: return ("Direct");
case DTYPE_SEQUENTIAL: return ("Sequential");
case DTYPE_ESI: return ("ESI");
case DTYPE_ARRAY_CTRL: return ("RAID");
default: return ("Ughknown");
}
}
static ddi_dma_attr_t single_dma_attrs = {
.dma_attr_version = DMA_ATTR_V0,
.dma_attr_addr_lo = 0x0ull,
.dma_attr_addr_hi = 0xffffffffffffffffull,
.dma_attr_count_max = 0x7ffffull,
.dma_attr_align = 4096,
.dma_attr_burstsizes = 0x78,
.dma_attr_minxfer = 1,
.dma_attr_maxxfer = 0x007ffffull,
.dma_attr_seg = 0xffffffffull,
.dma_attr_sgllen = 1,
.dma_attr_granular = 512,
.dma_attr_flags = 0,
};
pqi_dma_overhead_t *
pqi_alloc_single(pqi_state_t *s, size_t len)
{
pqi_dma_overhead_t *d;
ddi_dma_cookie_t cookie;
d = kmem_zalloc(sizeof (*d), KM_SLEEP);
d->len_to_alloc = len;
if (ddi_dma_alloc_handle(s->s_dip, &single_dma_attrs,
DDI_DMA_SLEEP, 0, &d->handle) != DDI_SUCCESS)
goto error_out;
if (ddi_dma_mem_alloc(d->handle, len, &s->s_reg_acc_attr,
DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
&d->alloc_memory, &len, &d->acc) != DDI_SUCCESS)
goto error_out;
bzero(d->alloc_memory, len);
if (ddi_dma_addr_bind_handle(d->handle, NULL, d->alloc_memory, len,
DDI_DMA_RDWR, DDI_DMA_SLEEP, 0, &cookie, &d->cookie_count) !=
DDI_SUCCESS)
goto error_out;
d->dma_addr = cookie.dmac_laddress;
if (d->cookie_count != 1)
ddi_dma_nextcookie(d->handle, &d->second);
return (d);
error_out:
pqi_free_single(s, d);
return (NULL);
}
void
pqi_free_single(pqi_state_t *s __unused, pqi_dma_overhead_t *d)
{
(void) ddi_dma_unbind_handle(d->handle);
if (d->alloc_memory != NULL)
ddi_dma_mem_free(&d->acc);
if (d->handle != NULL)
ddi_dma_free_handle(&d->handle);
kmem_free(d, sizeof (*d));
}
void
pqi_show_dev_state(pqi_state_t *s)
{
uint32_t dev_status = G32(s, pqi_registers.device_status);
switch (dev_status & 0xf) {
case 0:
cmn_err(CE_NOTE, "Power_On_And_Reset");
break;
case 1:
cmn_err(CE_NOTE, "PQI_Status_Available");
break;
case 2:
cmn_err(CE_NOTE, "All_Registers_Ready");
break;
case 3:
cmn_err(CE_NOTE,
"Adminstrator_Queue_Pair_Ready");
break;
case 4:
cmn_err(CE_NOTE, "Error: %s %s",
dev_status & 0x100 ? "(OP OQ Error)" : "",
dev_status & 0x200 ? "(OP IQ Error)" : "");
show_error_detail(s);
break;
default:
cmn_err(CE_WARN, "Unknown HBA status: 0x%x", dev_status);
break;
}
}
char *
cdb_to_str(uint8_t scsi_cmd)
{
switch (scsi_cmd) {
case SCMD_INQUIRY: return ("Inquiry");
case SCMD_TEST_UNIT_READY: return ("TestUnitReady");
case SCMD_READ: return ("Read");
case SCMD_READ_G1: return ("Read G1");
case SCMD_RESERVE: return ("Reserve");
case SCMD_RELEASE: return ("Release");
case SCMD_WRITE: return ("Write");
case SCMD_WRITE_G1: return ("Write G1");
case SCMD_START_STOP: return ("StartStop");
case SCMD_READ_CAPACITY: return ("ReadCap");
case SCMD_MODE_SENSE: return ("ModeSense");
case SCMD_MODE_SELECT: return ("ModeSelect");
case SCMD_SVC_ACTION_IN_G4: return ("ActionInG4");
case SCMD_MAINTENANCE_IN: return ("MaintenanceIn");
case SCMD_GDIAG: return ("ReceiveDiag");
case SCMD_SDIAG: return ("SendDiag");
case SCMD_LOG_SENSE_G1: return ("LogSenseG1");
case SCMD_PERSISTENT_RESERVE_IN: return ("PgrReserveIn");
case SCMD_PERSISTENT_RESERVE_OUT: return ("PgrReserveOut");
case BMIC_READ: return ("BMIC Read");
case BMIC_WRITE: return ("BMIC Write");
case CISS_REPORT_LOG: return ("CISS Report Logical");
case CISS_REPORT_PHYS: return ("CISS Report Physical");
default: return ("unmapped");
}
}
char *
io_status_to_str(int val)
{
switch (val) {
case PQI_DATA_IN_OUT_GOOD: return ("Good");
case PQI_DATA_IN_OUT_UNDERFLOW: return ("Underflow");
case PQI_DATA_IN_OUT_ERROR: return ("ERROR");
case PQI_DATA_IN_OUT_PROTOCOL_ERROR: return ("Protocol Error");
case PQI_DATA_IN_OUT_HARDWARE_ERROR: return ("Hardware Error");
default: return ("UNHANDLED");
}
}
char *
scsi_status_to_str(uint8_t val)
{
switch (val) {
case STATUS_GOOD: return ("Good");
case STATUS_CHECK: return ("Check");
case STATUS_MET: return ("Met");
case STATUS_BUSY: return ("Busy");
case STATUS_INTERMEDIATE: return ("Intermediate");
case STATUS_RESERVATION_CONFLICT: return ("Reservation Conflict");
case STATUS_TERMINATED: return ("Terminated");
case STATUS_QFULL: return ("QFull");
case STATUS_ACA_ACTIVE: return ("ACA Active");
case STATUS_TASK_ABORT: return ("Task Abort");
default: return ("Illegal Status");
}
}
char *
iu_type_to_str(int val)
{
switch (val) {
case PQI_RESPONSE_IU_RAID_PATH_IO_SUCCESS: return ("Success");
case PQI_RESPONSE_IU_AIO_PATH_IO_SUCCESS: return ("AIO Success");
case PQI_RESPONSE_IU_GENERAL_MANAGEMENT: return ("General");
case PQI_RESPONSE_IU_RAID_PATH_IO_ERROR: return ("IO Error");
case PQI_RESPONSE_IU_AIO_PATH_IO_ERROR: return ("AIO IO Error");
case PQI_RESPONSE_IU_AIO_PATH_DISABLED: return ("AIO Path Disabled");
default: return ("UNHANDLED");
}
}
void
pqi_free_mem_len(mem_len_pair_t *m)
{
kmem_free(m->mem, m->len);
}
mem_len_pair_t
pqi_alloc_mem_len(int len)
{
mem_len_pair_t m;
m.len = len;
m.mem = kmem_alloc(m.len, KM_SLEEP);
*m.mem = '\0';
return (m);
}
typedef struct qual {
int q_val;
char *q_str;
} qual_t;
typedef struct code_qual {
int cq_code;
qual_t *cq_list;
} code_qual_t;
static qual_t pair0[] = { {0, "No error"}, {0, NULL} };
static qual_t pair1[] = { {0, "Error detected during initialization"},
{ 0, NULL } };
static qual_t pair2[] = { {1, "Invalid PD Function"},
{2, "Invalid paramter for PD function"},
{0, NULL } };
static qual_t pair3[] = { {0, "Error creating admin queue pair"},
{ 1, "Error deleting admin queue pair"},
{ 0, NULL} };
static qual_t pair4[] = { {1, "Invalid IU type in general" },
{2, "Invalid IU length in general admin request"},
{0, NULL} };
static qual_t pair5[] = { {1, "Internal error" },
{2, "OQ spanning conflict"},
{0, NULL} };
static qual_t pair6[] = { {1, "Error completing PQI soft reset"},
{2, "Error completing PQI firmware reset"},
{3, "Error completing PQI hardware reset"},
{0, NULL} };
static code_qual_t cq_table[] = {
{ 0, pair0 },
{ 1, pair1 },
{ 2, pair2 },
{ 3, pair3 },
{ 4, pair4 },
{ 5, pair5 },
{ 6, pair6 },
{ 0, NULL },
};
static void
cmd_finish_task(void *v)
{
pqi_cmd_t *c = v;
struct scsi_pkt *pkt = CMD2PKT(c);
if (c->pc_poll)
sema_v(c->pc_poll);
if (pkt != NULL && (pkt->pkt_flags & FLAG_NOINTR) == 0 &&
(pkt->pkt_comp != NULL))
(*pkt->pkt_comp)(pkt);
}
static void
cmd_start_time(pqi_cmd_t *c)
{
c->pc_start_time = gethrtime();
if (CMD2PKT(c) != NULL) {
c->pc_expiration = c->pc_start_time +
((hrtime_t)c->pc_pkt->pkt_time * NANOSEC);
} else {
c->pc_expiration = c->pc_start_time + 5 * NANOSEC;
}
}
static void
show_error_detail(pqi_state_t *s)
{
uint32_t error_reg = G32(s, pqi_registers.device_error);
uint8_t code, qualifier;
qual_t *p;
code_qual_t *cq;
code = error_reg & 0xff;
qualifier = (error_reg >> 8) & 0xff;
for (cq = cq_table; cq->cq_list != NULL; cq++) {
if (cq->cq_code == code) {
for (p = cq->cq_list; p->q_str != NULL; p++) {
if (p->q_val == qualifier) {
cmn_err(CE_NOTE,
"[code=%x,qual=%x]: %s",
code, qualifier, p->q_str);
return;
}
}
}
}
cmn_err(CE_NOTE, "Undefined code(%x)/qualifier(%x)",
code, qualifier);
}
static void
pqi_catch_release(pqi_io_request_t *io __unused, void *v __unused)
{
cmn_err(CE_NOTE, "%s: caught", __func__);
}
static void
reinit_io(pqi_io_request_t *io)
{
io->io_cb = pqi_catch_release;
io->io_status = 0;
io->io_serviced = B_FALSE;
io->io_error_info = NULL;
io->io_raid_bypass = B_FALSE;
io->io_context = NULL;
io->io_cmd = NULL;
}
mem_len_pair_t
build_cdb_str(uint8_t *cdb)
{
mem_len_pair_t m = pqi_alloc_mem_len(64);
m.mem[0] = '\0';
switch (cdb[0]) {
case SCMD_INQUIRY:
MEMP("%s", cdb_to_str(cdb[0]));
if ((cdb[1] & 0x1) != 0)
MEMP(".vpd=%x", cdb[2]);
else if (cdb[2])
MEMP("Illegal CDB");
MEMP(".len=%x", cdb[3] << 8 | cdb[4]);
break;
case SCMD_READ:
MEMP("%s.lba=%x.len=%x", cdb_to_str(cdb[0]),
(cdb[1] & 0x1f) << 16 | cdb[2] << 8 | cdb[3],
cdb[4]);
break;
case SCMD_MODE_SENSE:
MEMP("%s.dbd=%s.pc=%x.page_code=%x.subpage=%x."
"len=%x", cdb_to_str(cdb[0]),
bool_to_str(cdb[1] & 8), cdb[2] >> 6 & 0x3,
cdb[2] & 0x3f, cdb[3], cdb[4]);
break;
case SCMD_START_STOP:
MEMP("%s.immed=%s.power=%x.start=%s",
cdb_to_str(cdb[0]), bool_to_str(cdb[1] & 1),
(cdb[4] >> 4) & 0xf, bool_to_str(cdb[4] & 1));
break;
case SCMD_SVC_ACTION_IN_G4:
case SCMD_READ_CAPACITY:
case SCMD_TEST_UNIT_READY:
default:
MEMP("%s (%x)", cdb_to_str(cdb[0]), cdb[0]);
break;
}
return (m);
}
mem_len_pair_t
mem_to_arraystr(uint8_t *ptr, size_t len)
{
mem_len_pair_t m = pqi_alloc_mem_len(len * 3 + 20);
int i;
m.mem[0] = '\0';
MEMP("{ ");
for (i = 0; i < len; i++) {
MEMP("%02x ", *ptr++ & 0xff);
}
MEMP(" }");
return (m);
}
static char lun_str[64];
static char *
lun_to_str(uint8_t *lun)
{
int i;
lun_str[0] = '\0';
for (i = 0; i < 8; i++)
(void) snprintf(lun_str + strlen(lun_str),
sizeof (lun_str) - strlen(lun_str), "%02x.", *lun++);
return (lun_str);
}
static char *
dir_to_str(int dir)
{
switch (dir) {
case SOP_NO_DIRECTION_FLAG: return ("NoDir");
case SOP_WRITE_FLAG: return ("Write");
case SOP_READ_FLAG: return ("Read");
case SOP_BIDIRECTIONAL: return ("RW");
default: return ("Oops");
}
}
static char *
flags_to_str(uint32_t flag)
{
switch (flag) {
case CISS_SG_LAST: return ("Last");
case CISS_SG_CHAIN: return ("Chain");
case CISS_SG_NORMAL: return ("Norm");
default: return ("Ooops");
}
}
#define SCRATCH_PRINT(args...) (void)snprintf(scratch + strlen(scratch), \
len - strlen(scratch), args)
static void
dump_raid(pqi_state_t *s, void *v, pqi_index_t idx)
{
int i;
int len = 512;
caddr_t scratch;
pqi_raid_path_request_t *rqst = v;
mem_len_pair_t cdb_data;
caddr_t raw = v;
scratch = kmem_alloc(len, KM_SLEEP);
scratch[0] = '\0';
if (s->s_debug_level & DBG_LVL_RAW_RQST) {
SCRATCH_PRINT("RAW RQST: ");
for (i = 0; i < sizeof (*rqst); i++)
SCRATCH_PRINT("%02x:", *raw++ & 0xff);
cmn_err(CE_NOTE, "%s", scratch);
scratch[0] = '\0';
}
if (s->s_debug_level & DBG_LVL_CDB) {
cdb_data = build_cdb_str(rqst->rp_cdb);
SCRATCH_PRINT("cdb(%s),", cdb_data.mem);
pqi_free_mem_len(&cdb_data);
}
ASSERT0(rqst->header.reserved);
ASSERT0(rqst->reserved1);
ASSERT0(rqst->reserved2);
ASSERT0(rqst->reserved3);
ASSERT0(rqst->reserved4);
ASSERT0(rqst->reserved5);
if (s->s_debug_level & DBG_LVL_RQST) {
SCRATCH_PRINT("pi=%x,h(type=%x,len=%x,id=%x)", idx,
rqst->header.iu_type, rqst->header.iu_length,
rqst->header.iu_id);
SCRATCH_PRINT("rqst_id=%x,nexus_id=%x,len=%x,lun=(%s),"
"proto=%x,dir=%s,partial=%s,",
rqst->rp_id, rqst->rp_nexus_id, rqst->rp_data_len,
lun_to_str(rqst->rp_lun), rqst->protocol_specific,
dir_to_str(rqst->rp_data_dir),
bool_to_str(rqst->rp_partial));
SCRATCH_PRINT("fence=%s,error_idx=%x,task_attr=%x,"
"priority=%x,additional=%x,sg=(",
bool_to_str(rqst->rp_fence), rqst->rp_error_index,
rqst->rp_task_attr,
rqst->rp_pri, rqst->rp_additional_cdb);
for (i = 0; i < PQI_MAX_EMBEDDED_SG_DESCRIPTORS; i++) {
SCRATCH_PRINT("%lx:%x:%s,",
(long unsigned int)rqst->rp_sglist[i].sg_addr,
rqst->rp_sglist[i].sg_len,
flags_to_str(rqst->rp_sglist[i].sg_flags));
}
SCRATCH_PRINT(")");
}
cmn_err(CE_NOTE, "%s", scratch);
kmem_free(scratch, len);
}
static void
dump_aio(void *v)
{
pqi_aio_path_request_t *rqst = v;
int i;
int len = 512;
caddr_t scratch;
mem_len_pair_t cdb_data;
scratch = kmem_alloc(len, KM_SLEEP);
scratch[0] = '\0';
cdb_data = build_cdb_str(rqst->cdb);
SCRATCH_PRINT("cdb(%s)", cdb_data.mem);
pqi_free_mem_len(&cdb_data);
SCRATCH_PRINT("h(type=%x,len=%x,id=%x)",
rqst->header.iu_type, rqst->header.iu_length,
rqst->header.iu_id);
SCRATCH_PRINT("rqst_id=%x,nexus_id=%x,len=%x,lun=(%s),dir=%s,"
"partial=%s,",
rqst->request_id, rqst->nexus_id, rqst->buffer_length,
lun_to_str(rqst->lun_number),
dir_to_str(rqst->data_direction), bool_to_str(rqst->partial));
SCRATCH_PRINT("fence=%s,error_idx=%x,task_attr=%x,priority=%x,"
"num_sg=%x,cdb_len=%x,sg=(",
bool_to_str(rqst->fence), rqst->error_index, rqst->task_attribute,
rqst->command_priority, rqst->num_sg_descriptors, rqst->cdb_length);
for (i = 0; i < PQI_MAX_EMBEDDED_SG_DESCRIPTORS; i++) {
SCRATCH_PRINT("%lx:%x:%s,",
(long unsigned int)rqst->ap_sglist[i].sg_addr,
rqst->ap_sglist[i].sg_len,
flags_to_str(rqst->ap_sglist[i].sg_flags));
}
SCRATCH_PRINT(")");
cmn_err(CE_NOTE, "%s", scratch);
kmem_free(scratch, len);
}