scsi_vhci_tpgs.c revision 3c1daac4bec6560b90a1e9046e8279b4aaec609f
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* External function definitions
*/
extern void vhci_mpapi_update_tpg_data(struct scsi_address *, char *, int);
int *mode);
int *preferred);
int
int tpg_id)
{
char *bufp;
len = 8;
" failed getrbuf"));
return (1);
}
"request packet allocation for %d failed....", len));
return (1);
}
"!vhci_tpgs_set_target_groups: scsi_init_pkt error\n"));
return (1);
}
/*
* Sends 1 TPG descriptor only. Hence Parameter list length pkt_cdbp[9]
* is set to 8 bytes - Refer SPC3 for details.
*/
"!vhci_tpgs_set_target_groups: sending set target port group:"
#ifdef DEBUG
#endif
if (rval == 0) {
" vhci_do_scsi_cmd failed\n"));
return (-1);
&(((struct scsi_arq_status *)(uintptr_t)
if ((skey == KEY_UNIT_ATTENTION) &&
(asc == STD_SCSI_ASC_STATE_CHG) &&
(ascq == STD_SCSI_ASCQ_STATE_CHG_SUCC)) {
"!vhci_tpgs_set_target_groups:"
" sense:%x, add_code: %x, qual_code:%x"
} else if ((skey == KEY_ILLEGAL_REQUEST) &&
(asc == STD_SCSI_ASC_INVAL_PARAM_LIST)) {
"!vhci_tpgs_set_target_groups:"
" sense:%x, add_code: %x, qual_code:%x"
} else if ((skey == KEY_ILLEGAL_REQUEST) &&
(asc == STD_SCSI_ASC_INVAL_CMD_OPCODE)) {
"!vhci_tpgs_set_target_groups:"
" sense_key:%x, add_code: %x, qual_code:%x"
} else {
/*
* At this point sns data may be for power-on-reset
* UNIT ATTN hardware errors, vendor unqiue sense etc.
* For all these cases, sense is unknown.
*/
"!vhci_tpgs_set_target_groups: "
" sense UNKNOWN: sense key:%x, ASC:%x, ASCQ:%x\n",
}
if (ss == SCSI_SENSE_STATE_CHANGED) {
return (0);
}
return (0);
}
return (1);
}
/*
* get the failover mode, ownership and if it has extended failover
* both. The state is defined as online-optimized(0h),
* online-nonoptimized(1h), standby(2h), offline(3h),
* and transitioning(fh). Currently, there is online,
* standby, and offline(defined in sunmdi.h).
* Online-nonoptimized will be a mode of secondary
* and an ownership of online. Thought about using a different mode but
* it appears the states are really for the states for secondary mode.
* We currently have IS_ONLINING, IS_OFFLINING - should we have TRANSITIONING
* to mean from online-optimized to online-nonoptimized or does onlining
* cover this?
*/
/* ARGSUSED */
int
{
int retval = 0;
struct scsi_address *ap;
"!vhci_tpgs_get_target_fo_mode: enter\n"));
" failed getrbuf\n"));
return (1);
}
" failed vhci_tpgs_inquiry\n"));
retval = 1;
" failed vhci_tpgs_page83\n"));
retval = 1;
" failed vhci_tpgs_report_target_groups\n"));
retval = 1;
}
if (retval == 0) {
"SUCCESS\n"));
}
return (retval);
}
static int
{
struct scsi_inquiry inq;
int retval;
*mode = 0;
if (retval == 0) {
" returned from vhci_do_scsi_cmd"));
return (1);
}
"!vhci_tpgs_inquiry: zero tpgs_bits"));
return (1);
}
retval = 0;
} else {
"!vhci_tpgs_inquiry: Illegal mode returned: %x mode: %x",
retval = 1;
}
return (retval);
}
static int
{
char *bufp;
/*
* lets start the buf size with 512 bytes. If this
* if found to be insufficient, we can allocate
* appropriate size in the next iteration.
*/
buf_len = 512;
"request packet allocation for %d failed....",
buf_len));
return (1);
}
"!vhci_tpgs_page83: Failure returned from scsi_init_pkt"));
return (1);
}
if (vhci_do_scsi_cmd(pkt) == 0) {
"!vhci_tpgs_page83: vhci_do_scsi_cmd failed\n"));
return (1);
}
/*
* Now lets check if the size that was provided was
* sufficient. If not, allocate the appropriate size
* and retry the command again.
*/
rx_bsize += 4;
/*
* Need to allocate more buf and retry again
*/
"bufsize: %d greater than allocated buf: %d\n",
rx_bsize));
goto once_again;
}
"desc[1/4/5/6/7]:%x %x %x %x %x\n",
*rel_tgt_port = 0;
"!vhci_tpgs_page83: relative target port: %x\n",
*rel_tgt_port));
*tgt_port = 0;
"!vhci_tpgs_page83: target port: %x\n", *tgt_port));
*lu = 0;
"!vhci_tpgs_page83: logical unit: %x\n", *lu));
}
}
return (0);
}
#ifdef DEBUG
static void
{
int i = 0, j;
for (j = 0; j < loop; j++) {
"!buf[%d-%d]: %x %x %x %x %x %x %x %x",
i += 8;
}
if (left) {
"NOTICE: buf[%d-%d]:", i, i + left));
for (j = 0; j < left; j++) {
}
}
}
#endif
static int
{
unsigned int rtpg_len = 0;
unsigned int l_tgt_port = 0, tpgs_state = 0;
unsigned int tgt_port_cnt = 0, lr_tgt_port = 0;
int i, len;
/*
* Start with buffer size of 512.
* If this is found to be insufficient, required size
* will be allocated and the command will be retried.
*/
len = 512;
" request packet allocation for %d failed....", len));
return (1);
}
"!vhci_tpgs_report_target_groups: scsi_init_pkt error\n"));
return (1);
}
"!vhci_tpgs_report_target_groups: sending target port group:"
if (vhci_do_scsi_cmd(pkt) == 0) {
" vhci_do_scsi_cmd failed\n"));
return (1);
}
" returned from target"
" port group: buf[0/1/2/3]: %x/%x/%x/%x\n",
rtpg_len += 4;
" bufsize: %d greater than allocated buf: %d\n",
rtpg_len));
goto try_again;
}
#ifdef DEBUG
#endif
ptr += 4;
" tpgs state: %x"
" tgt_group: %x count: %x\n", tpgs_state,
ptr += 8;
for (i = 0; i < tgt_port_cnt; i++) {
lr_tgt_port = 0;
if ((lr_tgt_port == rel_tgt_port) &&
(l_tgt_port == tgt_port)) {
"!vhci_tpgs_report_tgt_groups:"
" found tgt_port: %x rel_tgt_port:%x"
tpgs_state));
/*
* once we have the preferred flag
* and a non-optimized state flag
* we will get preferred flag from the
* report target groups
*/
if (tpgs_state == STD_ACTIVE_OPTIMIZED) {
} else if (tpgs_state ==
} else if (tpgs_state == STD_STANDBY) {
*pstate = STD_STANDBY;
} else {
}
return (0);
}
"!vhci_tpgs_report_tgt_groups:"
" tgt_port: %x rel_tgt_port:%x\n", tgt_port,
rel_tgt_port));
ptr += 4;
}
}
"NO rel_TGTPRT MATCH!!! Assigning Default: state: %x "
return (1);
}